javascripthtmlcss

Css using display style with fade-in animation togather


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>


Solution

  • 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>