< Koba ! >

Infinite Custom Marquee

Last updated: October 03, 2024

Have a marquee on your site? Don't like the default behaviour that leaves that big nasty gap every scroll-cycle? Tired of these stupid questions?? This is the resource for you!

But okay, on a serious note; After combing through a lot of tutorials and resources online, I found that a lot of people don't account for having multiple unique items inside of a custom marquee. A lot of the examples I found only had a working "infinite" effect on a single string of text, and that was super annoying! So I finally figured out how to make my own marquee, that works with (theorhetically) an infinite amount of items inside of it!

So without futher waiting, let's jump right into it.

Part 1: HTML

The HTML is actually very simple! The marquee consists of 3 main parts:

  1. The main marquee element
  2. A "container" div which will hold all the items inside your marquee, and
  3. The marquee items (Buttons, stamps, text, etc.)

For this resource, I will simply be copying the marquee that you can find on my home page!


<div class="marquee">
  <div class="marquee-items">
    <a href="https://joosh.nekoweb.org/" target="_blank"><img src="https://koba.nekoweb.org/imgs/buttons/joosh.gif"></a>
    <a href="https://trademarkhell.net/"><img src="https://koba.nekoweb.org/imgs/buttons/tmsspecialhell.png"
        alt="trademarkization company of 2003"></a>
    <a href="https://dimden.dev/"><img src="https://koba.nekoweb.org/imgs/buttons/dimden.gif"></a>
    <a href="https://foxball.nekoweb.org" title="The Vulpe Zone"><img
        src="https://koba.nekoweb.org/imgs/buttons/foxball.png" alt="Foxball's Nekoweb" /></a>
    <a href="https://social.nekoweb.org/" title="Nekoweb Cafe"><img
        src="https://koba.nekoweb.org/imgs/buttons/nekowebcafe.gif" alt="Nekoweb Cafe"></a>
    <a href="https://max.nekoweb.org/"><img src="https://koba.nekoweb.org/imgs/buttons/max.gif"
        alt="max's apartment"></a>
  </div>
</div>
        

Part 2: CSS

Next up is the CSS. This is where most of the actual "magic" of the custom marquee happens. First, we have to set up a keyframes animation, and create a class that runs that animation.


@keyframes scroll-l2r {
  from {
    transform: translateX(0);
  }

  to {
    transform: translateX(-100%);
  }
}

.scroll-l2r {
  animation: scroll-l2r 10s linear infinite;
}
        

Notice how the animation is named with -l2r? Keep this in mind for later!

Next, we have to style all of the HTML elements we created! The most important part is the overflow and flex, but almost everything else can be customized to your preference!


.marquee {
  overflow: hidden;
  display: flex;
  flex-wrap: nowrap;
  /* The following items are not required but make the effect look better! */
  /* For the best looking effect, try to have the width of your marquee */
  /* less than the total width of all the items inside of it. */
  height: 31px;
  width: 500px;
}

.marquee-items {
  display: flex;
  flex-shrink: 0;
  height: inherit;
  min-width: 100%;
  position: relative;
}

.marquee-items a {
  margin: 0;
  height: 31px;
}
        

Part 3: JavaScript

Don't worry! The JavaScript is actually really simple. If you named your divs the same as I have (.marquee, .marquee-items) then you shouldn't have to modify this at all. One additional thing that is nice, is that this script will handle every single custom marquee on your page at the same time! Just copy and add this script to the bottom of your page, before the </body> tag.


<script>
function handleMarquee() {
// Get all marquees on page
const marquees = document.querySelectorAll(".marquee");

// Loop through each marquee
  marquees.forEach((marquee) => {
    // Get the main container and clone it
    // And then add the clone to the marquee
    const container = marquee.querySelector(".marquee-items");
    let clone = container.cloneNode(true);
    marquee.appendChild(clone);
    
    // Finally, add the scroll class at the same time so there is no gaps in the scrolling effect
    // We also determine if the items should be scrolling right-to-left instead by default, and adjust the marquees flex
    // direction and which animation the containers use if so
    if (marquee.dataset.direction == "right") {
      marquee.style.flexDirection = "row-reverse";
      container.classList.add("scroll-r2l");
      clone.classList.add("scroll-r2l");
    } else {
      container.classList.add("scroll-l2r");
      clone.classList.add("scroll-l2r");
    }
  });
}
handleMarquee();
</script>
        

Now hold on there! Some of you might be asking now, "Koba, what's that if-statement there talking about with dataset direction? You didn't show us that!"

Remember how I said to keep in mind how the CSS animation is named with -l2r? Thats where that comes in!

Part 4: Reversing the direction

So, if you don't want your marquee to scroll from right-to-left, then you can basically stop here. Otherwise, we just need to make some minor adjustments and/or additions to the HTML and CSS!

HTML

To tell our script that we want to scroll the items from right-to-left instead, we just need to add a custom data attribute to the main marquee element:


<div class="marquee" data-direction="right">
  ...
</div>
        

This custom data attribute is what is read during that if-statement in our script! If our script finds this data, and the data reads "right", then the script adjusts our custom marquee element to have a flex-direction of "row-reverse". This means that all of the containers within the marquee will be placed in reverse order.

CSS

Then, we just have to add in another keyframes animation and a class:


@keyframes scroll-r2l {
  from {
    transform: translateX(0);
  }

  to {
    transform: translateX(100%);
  }
}

.scroll-r2l {
  animation: scroll-r2l 10s linear infinite;
}
        

And with all of that, you should have a result that looks something like this!

trademarkization company of 2003 Foxball's Nekoweb Nekoweb Cafe max's apartment

trademarkization company of 2003 Foxball's Nekoweb Nekoweb Cafe max's apartment

If you want to see this without all of my blabbing, check out my CodePen where you can see and play around with this exact code to see what everything does!


<< Return to main blog

Hosted by  

Made by me! ©2024