I developed an HTML code and I intend to display the text related to each link with a fade-in animation when the link is clicked.
In this code, I have a card with two columns. The first column contains 5 links, and the second column contains 5 text elements wrapped in
tags. In the second column, only one
tag should be visible at a time.
When I don’t use the display style, all the
tags remain in the DOM, and the fade-in animation works correctly. However, all the text and
tags that are not related to the active link should not be displayed. For this purpose, when I use the display style, the fade-in animation doesn’t work properly.
const links = document.querySelectorAll('.links a');
const content = document.querySelectorAll('.content p');
function showContent(index) {
links.forEach((link, i) => {
if (i === index - 1) {
link.classList.add('active');
} else {
link.classList.remove('active');
}
});
content.forEach((c, i) => {
if (i === index - 1) {
c.classList.add('active');
} else {
c.classList.remove('active');
}
});
}
.container {
display: flex;
width: 80%;
margin: 40px auto;
}
.links {
width: 20%;
background-color: #f0f0f0;
padding: 20px;
}
.links a {
text-decoration: none;
color: #000;
padding: 10px;
display: block;
border-bottom: 1px solid #ccc;
}
.links a.active {
background-color: #ff4444;
color: #fff;
}
.content {
width: 80%;
padding: 20px;
}
.content p {
font-size: 18px;
color: #333;
opacity: 0;
transition: opacity 0.5s ease-in-out;
display: none;
}
.content p.active {
display: block;
opacity: 1;
}
<div class="container">
<div class="links">
<a href="#" class="active" onclick="showContent(1)">Link (1)</a>
<a href="#" onclick="showContent(2)">Link (2)</a>
<a href="#" onclick="showContent(3)">Link (3)</a>
<a href="#" onclick="showContent(4)">Link (4)</a>
<a href="#" onclick="showContent(5)">Link (5)</a>
</div>
<div class="content">
<p id="content-1" class="active">Text related with Link (1)</p>
<p id="content-2">Text related with Link (2)</p>
<p id="content-3">Text related with Link (3)</p>
<p id="content-4">Text related with Link (4)</p>
<p id="content-5">Text related with Link (5)</p>
</div>
</div>
Using opacity should be fine in this case. I changed the function a bit, so that it is only the anchor that gets a new class name. The content is shown using a CSS selector where I combine :has() with the next-sibling combinator.
const links = document.querySelector('.links');
links.addEventListener('click', e => {
e.preventDefault();
if (e.target.nodeName == 'A') {
let id = e.target.getAttribute('href');
showContent(id);
}
});
function showContent(id) {
links.querySelectorAll('a').forEach(link => link.classList.remove('active'));
links.querySelector(`a[href="${id}"]`).classList.add('active');
}
.container {
display: flex;
width: 80%;
margin: 40px auto;
}
.links {
width: 20%;
background-color: #f0f0f0;
padding: 20px;
}
.links a {
text-decoration: none;
color: #000;
padding: 10px;
display: block;
border-bottom: 1px solid #ccc;
}
.links a.active {
background-color: #ff4444;
color: #fff;
}
.content {
width: 80%;
padding: 20px;
position: relative;
}
.content p {
font-size: 18px;
color: #333;
transition: opacity 0.5s ease-in-out;
position: absolute;
top: 0;
}
div.links:has(a)+div.content>p {
opacity: 0;
}
div.links:has(a.active[href="1"])+div.content>#content-1,
div.links:has(a.active[href="2"])+div.content>#content-2,
div.links:has(a.active[href="3"])+div.content>#content-3,
div.links:has(a.active[href="4"])+div.content>#content-4,
div.links:has(a.active[href="5"])+div.content>#content-5 {
opacity: 1;
}
<div class="container">
<div class="links">
<a href="1" class="active">Link (1)</a>
<a href="2">Link (2)</a>
<a href="3">Link (3)</a>
<a href="4">Link (4)</a>
<a href="5">Link (5)</a>
</div>
<div class="content">
<p id="content-1" class="active">Text related with Link (1)</p>
<p id="content-2">Text related with Link (2)</p>
<p id="content-3">Text related with Link (3)</p>
<p id="content-4">Text related with Link (4)</p>
<p id="content-5">Text related with Link (5)</p>
</div>
</div>