skip to Main Content

I want to crossfade several text quotes (coming from a CMS) having various lengths within a container div of a specific width. This is what I came up with, but it’s 2024 and I feel like there has to be an easier way to do this, either using only CSS or not having to resort to using onResize. What I’m doing is looping through all the quotes twice: one for display and the other for size calculation – determining the tallest quote and setting the parent div to that height.

I don’t want to resort to importing a gallery/carousel library or js framework as a dependency for something that seems so simple. Just wondering if anyone has any ideas on simplifying this. Thanks!


screenshot of codepen

2

Answers


  1. You could consider using a CSS grid system. Have the .wrapper be a grid layout consisting of one single grid area. Have the quotes all occupy this same grid area. This allows them to overlap, while having the tallest one dictate the size of the grid element.

    const wrapperEl = document.getElementById('wrapper')
    
    const animTimer = setInterval(() => {
      if (!wrapperEl) {
        return
      }
    
      const active = wrapperEl.querySelector('.active')
      let next = active?.nextElementSibling
      if (!next) {
        next = active?.parentElement?.firstElementChild
      }
    
      active?.classList.remove('active')
      next?.classList.add('active')
    }, 4500)
    :root {
      --width: 70%;
    }
    
    .wrapper {
      display: grid;
      grid-template: 1fr / 1fr;
      align-items: center;
      width: var(--width);
      /* or any specific width */
      min-height: 200px;
      background-color: #efefef;
      overflow: hidden;
    }
    
    .wrapper>div {
      opacity: 0;
      grid-area: 1 / 1 / -1 / -1;
      /* padding: 20px; */
      font-size: 40px;
      font-weight: bold;
      background-color: #ccf;
      transition: opacity 0.5s;
    }
    
    .wrapper .active {
      opacity: 1;
    }
    
    blockquote {
      margin: 0;
      padding: 0;
    }
    
    cite {
      display: inline-block;
      font-size: 1.5rem;
      padding-block-start: 20px;
    }
    
    p {
      width: var(--width);
    }
    <p>
      Welcome to this web site. Welcome to this web site. Welcome to this web site. Welcome to this web site. Welcome to this web site. Welcome to this web site. Welcome to this web site. Welcome to this web site.
    </p>
    <div id="wrapper" class="wrapper">
      <div class="active">
        <blockquote>"This is a medium quote or possibly just a regular one."</blockquote>
        <cite>-Mark Twain</cite>
      </div>
      <div>
        <blockquote>"This is a short quote."</blockquote>
        <cite>-Jeb Lawrence</cite>
      </div>
      <div>
        <blockquote>"This is quite possibly the longest quote known to anyone who has lived on earth and ever knew anything about what it takes to make a good quote."</blockquote>
        <cite>-Morgan Freeman</cite>
      </div>
      <div>
        <blockquote>"This is another somewhat long quote, or depending on your point of view, a short one."</blockquote>
        <cite>-Chris Smith</cite>
      </div>
    </div>
    
    <p>
      Welcome to this web site. Welcome to this web site. Welcome to this web site. Welcome to this web site. Welcome to this web site. Welcome to this web site. Welcome to this web site. Welcome to this web site.
    </p>
    Login or Signup to reply.
  2. You can use CSS Grid to lay the quotes on top of each other. The .wrapper will be the grid area. Then you can just use querySelectorAll() to get the quotes and infinitely cycle through the returned node list with setInterval() to add/remove the .active class which will be applied via a CSS Transition like so:

    const quotes = document.querySelectorAll('.quotes');
    if(quotes.length){
       let count = 0;
       setInterval(() =>{
          quotes[count].classList.remove('active');
          if(count === quotes.length -1){
             count = 0;
          }else{
             count++
          }
          quotes[count].classList.add('active');
       }, 2000);
    }
    main{
       max-width: 70%;
    }
    .wrapper {
       display: grid;
       grid-template: 1fr / 1fr;
       background-color: #efefef;
       padding: 40px 0;
    }
    .wrapper > .quotes {
       grid-column: 1 / 1;
       grid-row: 1 / 1;
       font-size: 40px;
       font-weight: bold;
       background-color: #ccf;
    }
    .quotes{
       opacity: 0;
    }
    .quotes.active{
       opacity: 1;
       transition: opacity 0.5s ease-in;
    }
    blockquote{
       margin: 0;
       padding: 0;
    }
    cite{
       display: inline-block;
       font-size: 1.5rem;
       padding-block-start: 20px;
    }
    <main>
       <p>Welcome to this web site. Welcome to this web site. Welcome to this web site. Welcome to this web site. Welcome to this web site. Welcome to this web site. Welcome to this web site. Welcome to this web site.
       </p>
       <section class="wrapper">
          <article class="quotes active">
             <blockquote>"This is a medium quote or possibly just a regular one</blockquote>
             <cite>-Mark Twain</cite>
          </article>
          <article class="quotes">
             <blockquote>"This is a short quote."</blockquote>
             <cite>-Jeb Lawrence</cite>
          </article>
          <article class="quotes">
             <blockquote>"This is quite possibly the longest quote known to anyone who has lived on earth and ever knew anything about what it takes to make a good quote."         </blockquote>
             <cite>-Morgan Freeman</cite>
          </article>
          <article class="quotes">
             <blockquote>"This is another somewhat long quote, or depending on your point of view, a short one."</blockquote>
             <cite>-Chris Smith</cite>
          </article>
       </section>
       <p>Welcome to this web site. Welcome to this web site. Welcome to this web site. Welcome to this web site. Welcome to this web site. Welcome to this web site. Welcome to this web site. Welcome to this web site.
       </p>
    </main>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search