Text carousel and image carousel using CSS?
Tags: css, html, javascript, webdev
Published: 2022-07-16 06:51:26

---
title: Text carousel and image carousel using CSS?
published: true
description: Use frame-by-frame animation and tweened animation to achieve an infinite loop carousel effect！
tags: CSS, HTML5, Javascript, webdev
# cover_image: https://miro.medium.com/max/400/0*rVLix0pJYyvO78RX.gif
# Use a ratio of 100:42 for best results.
---

Today, I will share an animation technique that can be used in real business.

Skillfully use frame-by-frame animation and tweened animation to achieve an infinite loop carousel effect, like this:

![](https://user-images.githubusercontent.com/8554143/169294742-34a2bb8f-9129-4a7b-a11b-8d60fe6b1d26.gif)

Seeing the above diagram, maybe you will say, isn’t this a very simple translation animation?

Let’s make a simple analysis. On the surface, it seems that there are only elements `transform: translate()` in displacement, but note that there are two difficulties here:

1. This is an infinite carousel effect, our animation needs to support infinite carousel switching of any number of elements
2. Because it is a carousel, when it runs to the last one, it needs to animate to the first element

At this point, you can pause and think for a moment. If there are 20 elements and you need to perform a similar infinite carousel broadcast, using CSS to achieve, how would you do it?

## Frame-by-frame animation controls overall switching

First, I need to use the frame-by-frame animation effect, also known as the **step easing function**, using the steps in `animation-timing-function`, the syntax is as follows:

```CSS
{
    /* Keyword values */
    animation-timing-function: step-start;
    animation-timing-function: step-end;
    /* Function values */
    animation-timing-function: steps(6, start)
    animation-timing-function: steps(4, end);
}
```

Suppose we have this HTML structure:

```HTML
<div class="g-container">
  <ul>
    <li>Lorem ipsum 1111111</li>
    <li>Lorem ipsum 2222222</li>
    <li>Lorem ipsum 3333333</li>
    <li>Lorem ipsum 4444444</li>
    <li>Lorem ipsum 5555555</li>
    <li>Lorem ipsum 6666666</li>
  </ul>
</div>
```

First, we implement a simple layout like this:

![](https://user-images.githubusercontent.com/8554143/169681177-3bcc9a3e-f32f-4892-9156-8ab38d515db9.png)

Here, to achieve a carousel effect, and it is an arbitrary number, we can use `animation-timing-function: steps()`：

```CSS
:root {
  // the number of items
  --s: 6;
  // container's height
  --h: 36;
  // per animation duration
  --speed: 1.5s;
}
.g-container {
  width: 300px;
  height: calc(var(--h) * 1px);
}
ul {
  display: flex;
  flex-direction: column;
  animation: move calc(var(--speed) * var(--s)) steps(var(--s)) infinite;
}
ul li {
  width: 100%;
}
@keyframes move {
  0% {
    transform: translate(0, 0);
  }
  100% {
    transform: translate(0, calc(var(--s) * var(--h) * -1px));
  }
}
```

Don’t panic when you see a few CSS variables above, it’s actually quite understandable:

1. `calc(var(--speed) * var(--s))`：The duration of a single animation * the number of rotations, that is, the total animation duration
2. `steps(var(--s))`  is the frame number of the frame-by-frame animation, here is `steps(6)`, well understood
3. `calc(var(--s) * var(--h) * -1px))` The height of a single li container * the number of carousels, which is actually the overall height of the ul, which is used to set the end value of the frame-by-frame animation

The above effect is actually as follows:

![](https://user-images.githubusercontent.com/8554143/169681483-f4ccced1-0d2e-475e-af60-2ca54e9402f5.gif)

If we add `overflow: hidden` to the container, this is the effect:

![](https://user-images.githubusercontent.com/8554143/169681559-3aae3e2c-6f7e-4eac-84cc-f014d74a05c9.gif)

In this way, we get the overall structure, at least, the whole effect is circular.

But since it’s just frame-by-frame animation, only the transition can be seen, but there is no transition animation effect between each frame. So, next, we have to introduce motion tweens.

## Use tween animation to switch between two sets of data

We need to use tween animation to achieve dynamic switching effects.

This step is actually very simple. What we need to do is to move a set of data from state A to state B using `transform`.

If you take one out for demonstration, the rough code is as follows:

```HTML
<div class="g-container">
  <ul style="--s: 6">
    <li>Lorem ipsum 1111111</li>
    <li>Lorem ipsum 2222222</li>
    <li>Lorem ipsum 3333333</li>
    <li>Lorem ipsum 4444444</li>
    <li>Lorem ipsum 5555555</li>
    <li>Lorem ipsum 6666666</li>
  </ul>
</div>
```
```CSS
:root {
  --h: 36;
  --speed: 1.5s;
}
ul li {
  height: 36px;
  animation: liMove calc(var(--speed)) infinite;
}
@keyframes liMove {
  0% {
    transform: translate(0, 0);
  }
  80%,
  100%  {
    transform: translate(0, -36px);
  }
}
```

A very simple animation:

![](https://user-images.githubusercontent.com/8554143/169817246-ead74236-d1a4-4629-b5a4-ca6a03ca5e68.gif)

Based on the above effects, if we combine the **frame-by-frame animation** mentioned at the beginning with the **tween animation** here, the overall movement of ul is stacked with the single movement of li:

```CSS
:root {
  --s: 6;
  --h: 36;
  --speed: 1.5s;
}
.g-container {
  width: 300px;
  height: calc(var(--h) * 1px);
}
ul {
  display: flex;
  flex-direction: column;
  animation: move calc(var(--speed) * var(--s)) steps(var(--s)) infinite;
}
ul li {
  width: 100%;
  animation: liMove calc(var(--speed)) infinite;
}
@keyframes move {
  0% {
    transform: translate(0, 0);
  }
  100% {
    transform: translate(0, calc(var(--s) * var(--h) * -1px));
  }
}
@keyframes liMove {
  0% {
    transform: translate(0, 0);
  }
  80%,
  100%  {
    transform: translate(0, calc(var(--h) * -1px));
  }
}
```

You can get this effect:

![](https://user-images.githubusercontent.com/8554143/169817863-a4fd2e15-aeb4-4e20-85db-1be2d0d7926a.gif)

Wow, the magical chemical reaction happened! Based on the combination of **frame-by-frame animation** and **tween animation**, we have almost achieved a carousel effect.

Of course, there is a slight flaw. You can see that the last set of data is `transformed` from the sixth set of data to a set of empty data:

![](https://user-images.githubusercontent.com/8554143/169818210-a0229c86-55a7-460c-8828-04cee5d70c95.png)

### Fill the first set of data in the header at the end

Someone who has actually developed a carousel must know that here, it is actually very easy to handle. We only need to fill in the first data of a group of headers at the end:

Modify our HTML:

```HTML
<div class="g-container">
  <ul>
    <li>Lorem ipsum 1111111</li>
    <li>Lorem ipsum 2222222</li>
    <li>Lorem ipsum 3333333</li>
    <li>Lorem ipsum 4444444</li>
    <li>Lorem ipsum 5555555</li>
    <li>Lorem ipsum 6666666</li>
    <!-- Fill the first set of data -->
    <li>Lorem ipsum 1111111</li>
  </ul>
</div>
```

So, let’s look at the effect again：

![](https://user-images.githubusercontent.com/8554143/169818781-4a1aab0f-2f69-4d79-b89c-57257f3cc9c2.gif)

Beautiful！If you still have doubts, we add overflow: hidden to the container, the actual effect is as follows, through the additional last set of data, our entire animation is just perfectly connected, a perfect carousel effect:

![](https://user-images.githubusercontent.com/8554143/169294742-34a2bb8f-9129-4a7b-a11b-8d60fe6b1d26.gif)

For the complete code, you can click here：[CodePen Demo -- Vertical Infinity Loop](https://codepen.io/Chokcoco/pen/RwQVByx)

### Horizontal infinite carousel

Of course, the vertical rotation is realized, and the horizontal effect is the same.

In addition, we can fill in the CSS variable value in the style in the HTML structure, and pass in the actual number of li, so as to adapt to different animations according to the number of li:

```HTML
<div class="g-container">
  <ul style="--s: 6">
    <li>Lorem ipsum 1111111</li>
    <li>Lorem ipsum 2222222</li>
    <li>Lorem ipsum 3333333</li>
    <li>Lorem ipsum 4444444</li>
    <li>Lorem ipsum 5555555</li>
    <li>Lorem ipsum 6666666</li>
    <!--Fill the first set of data-->
    <li>Lorem ipsum 1111111</li>
  </ul>
</div>
```

The CSS code of the whole animation is basically the same. We only need to change the `transform` value of the two animations, from vertical displacement to horizontal displacement:

```CSS
:root {
  --w: 300;
  --speed: 1.5s;
}
.g-container {
  width: calc(--w * 1px);
  overflow: hidden;
}
ul {
  display: flex;
  flex-wrap: nowrap;
   animation: move calc(var(--speed) * var(--s)) steps(var(--s)) infinite;
}
ul li {
  flex-shrink: 0;
  width: 100%;
  height: 100%;
  animation: liMove calc(var(--speed)) infinite;
}
@keyframes move {
  0% {
    transform: translate(0, 0);
  }
  100% {
    transform: translate(calc(var(--s) * var(--w) * -1px), 0);
  }
}
@keyframes liMove {
  0% {
    transform: translate(0, 0);
  }
  80%,
  100%  {
    transform: translate(calc(var(--w) * -1px), 0);
  }
}
```

In this way, we can easily convert it into a horizontal effect:

![](https://user-images.githubusercontent.com/8554143/169820749-5065394e-3cfe-4dcd-8852-416988b20eb6.gif)

For the complete code, you can click here：[CodePen Demo -- Horizontal Infinity Loop](https://codepen.io/Chokcoco/pen/JjpNBXY)

## Image Carousel? Not a problem!

OK, the above is just the text version of the carousel, what if it is a picture?

No problem, the method is the same. Based on the above code, we can easily modify it to get the carousel effect of the image version.

The code is the same, so it will not be listed, just look at the effect:

![](https://user-images.githubusercontent.com/8554143/169821330-21625c8c-d9b4-4ef3-9b72-f55e1e45fbbe.gif)

For the complete code, you can click here：[CodePen Demo -- Horizontal Image Infinity Loop](https://codepen.io/Chokcoco/pen/GRQvqgq)

Once you’ve mastered this technique, you can apply it to a lot of carousel effects that only require a simplified version.

To briefly summarize, very interesting techniques:

1. Use **frame-by-frame** animation to achieve an overall carousel loop effect
2. Use **tween animation** to achieve specific animation effects **from state A to state B**
3. **Frame-by-frame animation** with **tween animation** to form the effect of the overall carousel
4. By adding a set of header data to the end of the HTML structure, the connection of the overall animation is realized
5. Through the style tag of the HTML element, using CSS variables, fill in the actual number of DOM participating in the cycle, you can realize the connection between JavaScript and CSS

## Finally

OK, this is the end of this article, I hope this article will help you :)

More wonderful CSS technical articles are summarized in my [Github -- iCSS](https://github.com/chokcoco/iCSS) , which will be updated continuously. Welcome to click star to subscribe to the collection.