How to create marquee infinite loop of logos slider with css only

47.2k Views Asked by At

Right now my code makes the logos animate from right to left and once it hits the end, it restarts. How can I make it continue in a loop so that the first logo follows the last one when a new cycle starts?

EDIT: I rather not use extra js libraries, so if there is a simple way of doing this with jquery that would be much better

img {
  width: 100px;
}
.marquee {
  position: relative;
  width: 100%;
  height: 100px;
  border: 1px solid black;
  overflow: hidden;
}
.marquee div {
  display: block;
  position: absolute;
  width: 300%;
  overflow: hidden;
  animation: marquee 20s linear infinite;
}
.marquee div:hover {
  animation-play-state: paused;
}
.marquee span {
  float: left;
  width: 50%;
}

@keyframes marquee {
  0% { left: 0; }
  100% { left: -100%; }
}
<div class="marquee">
  <div>
    <img src="http://static.bragdeal.com/logo.png" alt="">
    <img src="http://static.bragdeal.com/logo.png" alt="">
    <img src="http://static.bragdeal.com/logo.png" alt="">
    <img src="http://static.bragdeal.com/logo.png" alt="">
    <img src="http://static.bragdeal.com/logo.png" alt="">
    <img src="http://static.bragdeal.com/logo.png" alt="">
    <img src="http://static.bragdeal.com/logo.png" alt="">
    <img src="http://static.bragdeal.com/logo.png" alt="">
  </div>
</div>

3

There are 3 best solutions below

3
Parth Patel On BEST ANSWER

HTML:

  <div class='marquee'>
       .... 
       images
       ....
    </div>

CSS:

.marquee {
    width: 100%;
    overflow: hidden;
    border:1px solid #ccc;
}

JavaScript:

$(function () {
    $('.marquee').marquee({
        duration: 5000,
         duplicated: true,
         gap: 00, 
         direction: 'left',
         pauseOnHover: true
    });
});

This is what i have done to make it run using JQuery Marquee.

External links:

  1. jquery.pause.js
  2. jquery.marquee.min.js

Also you can follow this Fiddle

4
Bmd On

I updated your fiddle https://jsfiddle.net/gkpnx34v/2/ --- took a little tinkering, but that should give you the idea.

.tech-slideshow {
  height: 100px;
  max-width: 100%;
  margin: 0 auto;
  position: relative;
  overflow: hidden;
  border:1px solid black;
  font-size:0; /* THIS IS A HACK TO REMOVE THE "WHITESPACE" BETWEEN IMAGES.
                  YOU COULD ALSO PUT ALL OF THE IMAGES ON THE SAME LINE
                  (eg: <img src=""><img src=""><img src=""> 
                  with no spaces or line-breaks),
                  BUT THAT MAKES THE CODE LESS READABLE SO I'M DOING THIS
                  FOR THE SAKE OF CREATING THIS EXAMPLE FOR YOU */
}

.mover-1 {
  height: 150px;
  width: max-content;
  
  position: absolute;
  overflow-x:hidden;
  top: 0;
  left: 0;

  animation: moveSlideshow 5s linear infinite;
}

.mover-1 img {
  display:inline-block;
  vertical-align:middle;
  width:100px;
  margin:0;
}

@keyframes moveSlideshow {
  100% { 
    transform: translateX(-500px);  
  }
}
<div class="tech-slideshow">
  <div class="mover-1">
    <img src="https://placekitten.com/100/150">
    <img src="https://placekitten.com/100/100">
    <img src="https://placekitten.com/100/100">
    <img src="https://placekitten.com/100/100">
    <img src="https://placekitten.com/100/100">

    <img src="https://placekitten.com/100/150">
    <img src="https://placekitten.com/100/100">
    <img src="https://placekitten.com/100/100">
    <img src="https://placekitten.com/100/100">
    <img src="https://placekitten.com/100/100">

    <img src="https://placekitten.com/100/150">
    <img src="https://placekitten.com/100/100">
    <img src="https://placekitten.com/100/100">
    <img src="https://placekitten.com/100/100">
    <img src="https://placekitten.com/100/100">
  </div>
</div>

Set your .mover-1 container's width to max-content (to auto-size to whatever width is necessary). You could also set it to an arbitrary (huge) width just so you won't have to worry about having logos roll over to the next line.

Then set some styles on your images so they'll line up nicely.

Finally, set the moveSlideshow translateX distance to THE EXACT WIDTH OF ONE SET OF LOGOS.

The point is, you want to have 2 sets of logos -- the initial set and then a duplicate that you roll into view. Set your animation to move exactly the width of 1 set and it should loop smoothly.

Just for posterity (and because it's REALLY easy to copy and paste code and doesn't take any extra bandwidth to render) I actually added a 3rd set of logos just to make sure my block of logos was wide enough to never have a gap on wide screens.

P.S. The difference in heights I set on the kitten images (some of them being 150px tall instead of 100px) has nothing to do with the functionality; I just wanted to make sure that you can tell when the animation loops.

P.P.S. Rather than a) manually calculating the total width of the logos or b) adding redundant blocks of logos, you could easily use jQuery to find the width of that .mover-1 container ($('.mover-1')[0].width()) and set your keyframe to move that distance. Then make an array of the images ($('.mover-1 img')), then append/prepend them to the original set.

This code (untested) should get you close:

var logos = $('mover-1 img');
$('.mover-1').append(logos).append(logos);
0
Cybernetic On

I know the question says CSS only, but I find all attempts using only keyframes and HTML leads to unwanted spacing between the logo, overlapping logos, parallax effects, etc.

For those willing to use some JavaScript the following works for me:

HTML:

<div id="hold_logos"></div>

CSS:

body {
  background: black;
}

#hold_logos {
  height: 200px;
  background: #218c74;
  display: flex;
  align-items: center;
  margin-top: 100px;
}

.logo {
    position: absolute;
    cursor: pointer;
    width: 140px;
    border-radius: 4px;
    animation: marquee 10s linear infinite;
}

@keyframes marquee {
    0% {
        transform: translateX(1400px);
   }
    100% {
        transform: translateX(-200px);
   }
}

JS:

images = ["https://www.strunkmedia.com/wp-content/uploads/2018/05/bigstock-221516158.jpg", "https://cms-assets.tutsplus.com/cdn-cgi/image/width=360/uploads/users/2273/posts/32751/image/TwoPeaks-Logo.jpg", "https://png.pngtree.com/png-clipart/20210711/original/pngtree-colorful-nature-logo-png-image_6511888.jpg", "https://designshack.net/wp-content/uploads/symbol-logo-example.jpg", "https://cdn.thebrandingjournal.com/wp-content/uploads/2019/05/chanel_logo_the_branding_journal.jpg"];
const number_of_logos = 5;
const spacing = (window.innerWidth / number_of_logos)*10;
const duration = (number_of_logos*spacing);
var int_cnt = -1;
var marquee = document.getElementById("hold_logos");
partner_interval = setInterval(function() {
    int_cnt++;
    if(int_cnt < number_of_logos) {
           const img = document.createElement("img");
           img.className = "logo";
           img.src = images[int_cnt];
           marquee.append(img);
    }
}, spacing/1.4);

setTimeout(function() {
    clearInterval(partner_interval);
}, duration);

Result:

enter image description here

The result is smoother than what the GIF shows since it's still using keyframes.

Here's the CodePen.