Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@Jaskaranbir
Created July 2, 2016 23:56
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Jaskaranbir/eb0f26d0ba47f55e25fde3b63d8b7ef4 to your computer and use it in GitHub Desktop.
Save Jaskaranbir/eb0f26d0ba47f55e25fde3b63d8b7ef4 to your computer and use it in GitHub Desktop.
Inifinite Continuous Scrolling Marquee in CSS without any explicit framework
<div id="maindiv">
<!-- Need to have two divs with same content.
One div will translate completely out of parent and other div will fill the void till the transition for first div starts again. -->
<div id="div1">
&nbsp;Test-1 Test-2 Test-3 Test-4 Test-5 Test-6 Test-7 Test-8 Test-9 Test-10 Test-11
</div>
<div id="div2">
&nbsp;Test-1 Test-2 Test-3 Test-4 Test-5 Test-6 Test-7 Test-8 Test-9 Test-10 Test-11
</div>
</div>
<style>
#maindiv{
border: 2px solid black;
/* These are absolutely necessary */
overflow: hidden;
white-space: nowrap;
}
#div1 {
display: inline-block;
animation: marquee 10s linear infinite;
}
#div2 {
display: inline-block;
animation: marquee2 10s linear infinite;
/* Must be half the animation duration of both divs so it stats in sync to fill void left by completed transtition of first div */
animation-delay: 5s;
}
@keyframes marquee {
from {
transform: translateX(100%);
}
to {
transform: translateX(-100%);
}
}
@keyframes marquee2 {
from {
transform: translateX(0%);
}
to {
transform: translateX(-200%);
}
}
</style>
<script src="https://code.jquery.com/jquery-3.0.0.min.js"></script>
<script>
// It is absolute necessity that div should be smaller than individual text content.
$('#maindiv').width($('#div1').width());
</script>
@amichel86
Copy link

Hey man, hope you're doing well, thanks for this code. Is it possible to have this 100% of the viewport and that the text loops flawlessly?

@Jaskaranbir
Copy link
Author

Hey man, hope you're doing well, thanks for this code. Is it possible to have this 100% of the viewport and that the text loops flawlessly?

Hey Alex, its been a while since I worked with jQuery and I wont be able to get into this anytime soon with my ongoing schedule. However, I am sure there has to be some library/plugin that already implements this better...

@amichel86
Copy link

Hey man, hope you're doing well, thanks for this code. Is it possible to have this 100% of the viewport and that the text loops flawlessly?

Hey Alex, its been a while since I worked with jQuery and I wont be able to get into this anytime soon with my ongoing schedule. However, I am sure there has to be some library/plugin that already implements this better...

We went for a different animation so it's all good, thanks for taking the time to reply! :)

@msbajracharya
Copy link

Thank you for the solution but i wanted to know what should be changed if scrolling needs to be vertical.

@adrianenriquez
Copy link

Good. But only works if the items are same.

@mar-han
Copy link

mar-han commented Jan 22, 2021

Thanks for this! Is there a way to put spacing between the items? In your example, I mean the Test-1, Test-2, Test-3, etc.

@Jaskaranbir
Copy link
Author

Jaskaranbir commented Jan 23, 2021

Thanks for this! Is there a way to put spacing between the items? In your example, I mean the Test-1, Test-2, Test-3, etc.

There are a variety of approaches you can try/experiment with:

  • Enclose each item in div with inline-block display (or span), and add left-right margin/padding
  • Use multiple &nbsp;, a bit rudimentary way
  • Use <pre> HTML-tag around text, another rudimentary approach

@Markuswindt
Copy link

Hey :) Thank you very much for this! I've got two questions maybe you've got the time. 1. For me this works without your jQuery code - what is it supposed to do? 2. what would I have to do in order to start the marquee somewhere in the middle - because rn it is always coming from the right an it takes some seconds to fill the whole width with text - I want to start the animation at 0% and not 100% but I can't really figure out the other values - it just doesn't work

@Markuswindt
Copy link

I'd also pay you some cash if you could make this work for me - I can't get my head around this

@Jaskaranbir
Copy link
Author

Jaskaranbir commented May 23, 2021

Hi @Markuswindt,

Its actually fairly easy to remove jQuery from this code. You would just need to replace line#54 with something like:

document.getElementById("maindiv").style.width = document.getElementById("div1").clientWidth + "px"

There are various other types of widths (such as the method above doesnt include margin-width, you would need different property for that). Feel free to explore docs about various ways to get element-widths and use as required.

As for starting from the middle, you will have to run the animation in 2-parts: 1st is playing from middle to end once, then from start to end infinitely.

Here's some sample code to achieve this, feel free to tweak/refactor this (for example: hardcoding those durations is a bad idea, see if you can refactor this to use some variables + offsets using SCSS/JavaScript/etc.).

Click to expand code
<div id="maindiv">
<!-- Need to have two divs with same content.
One div will translate completely out of parent and other div will fill the void till the transition for first div starts again. -->
  <div id="div1">
    <div>
    &nbsp;Test-1 Test-2 Test-3 Test-4 Test-5 Test-6 Test-7 Test-8 Test-9 Test-10 Test-11
    </div>
  </div>
  <div id="div2">
    &nbsp;Test-1 Test-2 Test-3 Test-4 Test-5 Test-6 Test-7 Test-8 Test-9 Test-10 Test-11
  </div>
</div>

<style>
#maindiv{
  border: 2px solid black;
  /* These are absolutely necessary */
  overflow: hidden;
  white-space: nowrap;
}

#div1 {
  display: inline-block;
  /* 7.5s instead of 10s cos 1/4 route is already covered (starting from middle instead of end) */
  animation: half-marquee 7.5s linear 1;
}
 
#div1 div {
  animation: marquee 10s linear infinite;
  animation-delay: 7.5s; /* Wait for parent (#div1) animation */
}

#div2 {
  display: inline-block;
  animation: marquee2 10s linear infinite;
  /* Roughly 33% of half-marquee animation to fill void */
  animation-delay: 2.45s;
}

@keyframes half-marquee {
  from {
    transform: translateX(50%);
  }
  to {
    transform: translateX(-100%);
  }
}

@keyframes marquee {
  from {
    transform: translateX(100%);
  }
  to {
    transform: translateX(-100%);
  }
}

@keyframes marquee2 {
  from {
    transform: translateX(0%);
  }
  to {
    transform: translateX(-200%);
  }
}
</style>

<script>
  const div1Width = document.getElementById("div1").clientWidth;
  // It is absolute necessity that div should be smaller than individual text content.
  document.getElementById("maindiv").style.width = div1Width + "px";
</script>

And there's no need for cash, I mainly do this stuff for fun ;)

@Markuswindt
Copy link

Thank you very much for your detailed answer! I will try my best to tweak your code and work through this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment