Build a quote switcher with Vanilla JS

Build a quote switcher with Vanilla JS

Listen to this article

Hello again, my friend.

This time we're going to do something more practical, visual, and frontend-focused.

Also, since JavaScript has had several updates throughout the years, you would be surprised to see all the different things we can now create without the need for a framework.

Just plain good ol' vanilla JS.

You wanna know what it is? Well, let's jump right in!

jumping in

What are we going to build?

It will be this nice-looking, component that displays a quote when clicking on its author's image.

And it all works with just plain HTML, CSS, and JS.

Here's how it looks.

quotes.png

What we'll need

The Markup

Let's start with the markup. First, we will need a container for the component and some space for both the author and the quote.

It can be something like this...

<div class="switcher">
  <div class="authors">
      ... 
  </div>
  <div class="quotes">
     ...
  </div>
</div>

Now, we can add the text of the quote and the name of the author.

  <div class="quote">
    <div class="quote-text">
        <div>
            <p>
                ...
            </p>
        </div>
        <div class="quote-author">
            <h3>...</h3>
        </div>
    </div>
  </div>

Lastly, let's add the code for the button and the author's image.

 <button class="author-btn" type="button" data-index="0">
   <img class="btn-image" src="https://image.jpg" alt="Author Image" />
 </button>

That's pretty much all the code that we'll need to make this happen.

You can modify this markup to your liking or adapt it if you're using a preprocessor. Something like Pug for example.

The Styling

Now for the styling, that's another thing that you can freely change to make the end result what you want it to be.

Also, if you want to use another preprocessor like SASS or Stylus, go right ahead. (The first one is my personal preference)

In this case, I'll be using this styling.

.switcher {
  margin: 1rem;
  background-color: #fff;
  border: 1px solid #eee;
  border-radius: 8px;
  font-family: "Helvetica", sans-serif;
  margin-bottom: 1.875rem;
  max-width: 550px;
}

.btn-image {
  display: block;
  height: 100%;
  width: 100%;
}

.author-btn {
  border: 0.125rem solid #4caf50;
  border-radius: 50%;
  height: 4.5rem;
  padding: 0.02rem;
  margin-bottom: 1rem;
  margin-left: 1rem;
  margin-top: 1rem;
  overflow: hidden;
  transition: opacity 0.2s ease-out;
  width: 4.5rem;
}

.author-btn:focus {
  opacity: 1;
  outline: 0;
}

.author-btn-dimmed {
  border-color: #bdbdbd;
  border-width: 0.0625rem;
  opacity: 0.5;
}

.quotes {
  margin-top: 1rem;
  background-color: #fafafa;
}

.title {
  margin: 0;
  padding: 0.5rem 0;
  text-align: center;
}

.quote-container {
  background-color: #fafafa;
  width: 100%;
}

.quote-container-hidden {
  display: none;
}

.quote {
  border-bottom: 0.06rem solid #e0e0e0;
  width: 100%;
}

.quote-text {
  width: calc(100% - 2rem);
  margin-left: 1rem;
}

.quote-author {
  margin: 1rem 0;
}

The JavaScript

And now, here comes the fun part. Or I should say the interactive part.

It's now time to give it some movin' & groovin' with a bit of JS.

First, we'll need to get references to the elements that we'll be interacting with.

const authorsList = document.querySelectorAll(".author-btn");
const quotesList = document.querySelectorAll(".quote-container");

Now, we'll need to add the event listener for when the author button gets clicked. We'll do for all the authors with this code.

authorsList.forEach((author) => {
  author.addEventListener('click', handleClick)
})

For that handleClick function, we have to retrieve the value of the index for that particular button. It can be something like this.

function handleClick(event) {
  const selectedQuote = parseInt(event.currentTarget.dataset.index, 10);

  showQuote(selectedQuote);
}

Now that we have that particular index, we'll call a helper function that will do the 'switching' of the selected quote.

That function showQuote will basically compare what's is the active quote being displayed and what's the new quote that's going to be displayed.

For that, we need to keep track of what's our current index. Something like this will do

let quoteIndex = 0;

That will go at the start of the file alongside the authors and quotes lists.

Now, to implement the missing function. Here's what will do the trick.

function showQuote(index) {
  if(index === quoteIndex) return;

  authorsList[quoteIndex].classList.toggle("author-btn-dimmed");
  quotesList[quoteIndex].classList.toggle("quote-container-hidden");
  authorsList[index].classList.toggle("author-btn-dimmed");
  quotesList[index].classList.toggle("quote-container-hidden");
  quoteIndex = index;
}

And what we're doing here is a game of toggling CSS classes with a little animation to get that 'switching' effect.

And that's in a nutshell everything necessary to make the component work.

Putting it all together

Ok, with all those pieces in place we can interact with it and see it working.

We can add more authors and quotes by duplicating the markup for each of those and adding the corresponding text.

See this codepen for an example of the component built.

And like I said before if there are some tweaks and adjustments you want to do to this component, feel free to change it to your heart's content.

Conclusion

Well, there you have it! A fully functioning quote switching component built entirely with plain ol' vanilla JS and some HTML & CSS.

It's interesting the kind of dynamic things we can build just by using the technologies of the lean web.

That is not to say that frameworks are not useful or bad. But knowing how the system behind works without a bunch of abstractions, it gives us a better understanding and allows us to do our job much better.

Instead of not knowing how things work and depending on the mercy of "whenever the program wants to work properly".

That's it for this post. As always thanks a lot for reading. If you have any questions or comments send them my way through the little blue bird.


Photo by capnsnap on <a href="unsplash.com/s/photos/quotes>Unsplash

 
Share this