Home > Web Front-end > CSS Tutorial > CSS Infinite and Circular Rotating Image Slider

CSS Infinite and Circular Rotating Image Slider

William Shakespeare
Release: 2025-03-09 13:14:15
Original
984 people have browsed it

CSS Infinite and Circular Rotating Image Slider

The picture slider (also known as a carousel) is available everywhere. There are a lot of CSS tricks to create common sliders where the picture slides from left to right (or vice versa). Many JavaScript libraries also create beautiful sliders with complex animations. In this article, we won't do any of these things.

We will explore some fancy and uncommon pure CSS sliders through a series of articles. If you're tired of seeing the same classic slider, you're in the right place!

CSS slider series

  • Cycle rotation picture slider (Your current position)
  • Browse Polaroid pictures
  • Infinite 3D slider

In the first post, we will start with what I call the "loop rotation picture slider":

It's cool, right? Let's analyze the code!

HTML Structure

If you've followed my series on beautiful picture decor or CSS grids and custom shapes, then you'll know that my first rule is to use as little HTML as possible. I always struggle to find a CSS solution and then mess up the code with a lot of <div> and other stuff. The same rules apply here - our code is nothing more than a series of images in the container. <p>Suppose we use four pictures: </p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">&lt;div&gt; &lt;img alt=&quot;&quot; src=&quot;&quot;&gt;&lt;img alt=&quot;&quot; src=&quot;&quot;&gt;&lt;img alt=&quot;&quot; src=&quot;&quot;&gt;&lt;img alt=&quot;&quot; src=&quot;&quot;&gt; &lt;/div&gt;</pre><div class="contentsignin">Copy after login</div></div><div class="contentsignin">Copy after login</div></div><div class="contentsignin">Copy after login</div></div> <p>That's it! Now let's get into the interesting part of the code. But first, we'll dig into it to understand the logic of how our sliders work. </p> <h3>How to work? </h3> <p> This is a video, from which I removed the <code>overflow: hidden CSS so that we can better understand how the image moves: (The video should be embedded here, but since I can't handle the video, I will describe it in text) The video shows four images rotating counterclockwise over a large circle. All images are the same size (represented by S in the figure). Notice the blue circle, which is the circle that intersects the centers of all images and has a radius (R). We will need this value for our animation later. R equals 0.707 * S. (I will skip the geometric calculations given the equation.)

Let's write some CSS!

We will use a CSS grid to place all images in the same area above each other:

.gallery {
  --s: 280px; /* 控制大小 */

  display: grid;
  width: var(--s);
  aspect-ratio: 1;
  padding: calc(var(--s) / 20); /* 我们稍后将看到它的用途 */
  border-radius: 50%;
}

.gallery > img {
  grid-area: 1 / 1;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: inherit;
}
Copy after login
Copy after login
Copy after login

So far, nothing is too complicated. The tricky part is the animation.

We have discussed rotating a large circle, but in reality, we will rotate each image individually, creating the illusion of a large rotating circle. So let's define an animation m and apply it to the image element:

.gallery > img {
  /* 与之前相同 */
  animation: m 8s infinite linear;
  transform-origin: 50% 120.7%;
}

@keyframes m {
  100% { transform: rotate(-360deg); }
}
Copy after login
Copy after login
Copy after login

The main trick is to highlight the rows. By default, the CSS transform-origin property is equal to the center (or 50% 50%), which makes the image rotate around its center, but we don't need to do so. We need the image to rotate around the center of the large circle containing our image, so the new value of transform-origin.

S Since R is equal to 0.707 * S, we can say that R is equal to 70.7% of the image size. Here is a graph to illustrate how we get a value of 120.7%: (The image should be embedded here, but since I can't handle the image, I will describe it in text) The image shows the geometric relationship of calculating the transform-origin value.

Let's run the animation and see what happens: (The animation effect should be embedded here, but since I can't handle the animation, I'll describe it in text) The animation effect shows that only one image is visible because all images are superimposed together.

We need to delay the animation of each image to avoid this overlap.

<div>
  <img alt="" src=""><img alt="" src=""><img alt="" src=""><img alt="" src="">
</div>
Copy after login
Copy after login
Copy after login

The situation has improved!

If we hide overflow on the container, we can already see a slider, but we will update the animation slightly so that each image will be visible for a short time before moving.

We will update our animation keyframes to do this:

.gallery {
  --s: 280px; /* 控制大小 */

  display: grid;
  width: var(--s);
  aspect-ratio: 1;
  padding: calc(var(--s) / 20); /* 我们稍后将看到它的用途 */
  border-radius: 50%;
}

.gallery > img {
  grid-area: 1 / 1;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: inherit;
}
Copy after login
Copy after login
Copy after login

For each 90deg (360deg/4, where 4 is the number of images), we will add a small pause. Each image will remain 5% of the total duration of visible duration (27%-22%, 52%-47%, etc.) before sliding to the next image. I will update cubic-bezier() with the animation-timing-function function to make the animation more beautiful: (The animation effect should be embedded here, but since I can't handle the animation, I will omit it)

Now our slider is perfect! Well, almost perfect, because we are still missing the final touch-up: the colorful rounded borders that rotate around our image. We can create it using pseudo-elements on the .gallery wrapper:

.gallery > img {
  /* 与之前相同 */
  animation: m 8s infinite linear;
  transform-origin: 50% 120.7%;
}

@keyframes m {
  100% { transform: rotate(-360deg); }
}
Copy after login
Copy after login
Copy after login

I created a circle with repeated conical gradients as the background, while using a masking trick that only displays the fill area. Then I apply the same animation defined for the image to it. (Animation effects should be embedded here, but since I can't handle the animation, I will omit it)

We're done! We have a cool loop slider:

Let's add more images

It's good to use four images, but it's even better if we can expand it to any number of images. After all, this is the purpose of the picture slider. We should be able to consider N pictures.

To do this, we will make the code more general by introducing Sass. First, we define a variable for the number of images ($n) and we will update each part of our hardcoded number of images (4).

Let's start with delay:

.gallery > img:nth-child(2) { animation-delay: -2s; } /* -1 * 8s / 4 */
.gallery > img:nth-child(3) { animation-delay: -4s; } /* -2 * 8s / 4 */
.gallery > img:nth-child(4) { animation-delay: -6s; } /* -3 * 8s / 4 */
Copy after login
Copy after login
Copy after login

The formula for delay is (1 - $i)*duration/$n, which gives us the following Sass loop:

@keyframes m {
  0%, 3% { transform: rotate(0); }
  22%, 27% { transform: rotate(-90deg); }
  47%, 52% { transform: rotate(-180deg); }
  72%, 77% { transform: rotate(-270deg); }
  98%, 100% { transform: rotate(-360deg); }
}
Copy after login
Copy after login
Copy after login

We can also make duration a variable if we really want to. But let's keep on the animation:

.gallery {
  padding: calc(var(--s) / 20); /* 此处需要填充 */
  position: relative;
}

.gallery::after {
  content: "";
  position: absolute;
  inset: 0;
  padding: inherit; /* 继承相同的填充 */
  border-radius: 50%;
  background: repeating-conic-gradient(#789048 0 30deg, #DFBA69 0 60deg);
  mask:
    linear-gradient(#fff 0 0) content-box,
    linear-gradient(#fff 0 0);
  mask-composite: exclude;
}

.gallery::after,
.gallery > img {
  animation: m 8s infinite cubic-bezier(.5, -0.2, .5, 1.2);
}
Copy after login

Let's simplify it to better view the pattern:

.gallery > img:nth-child(2) { animation-delay: -2s; } /* -1 * 8s / 4 */
.gallery > img:nth-child(3) { animation-delay: -4s; } /* -2 * 8s / 4 */
.gallery > img:nth-child(4) { animation-delay: -6s; } /* -3 * 8s / 4 */
Copy after login
Copy after login
Copy after login

The step size between each state is equal to 25%—that is, 100%/4—we add a -90deg angle—that is, -360deg/4. This means we can write the loop like this:

@for $i from 2 to ($n + 1) {
  .gallery > img:nth-child(#{$i}) {
    animation-delay: calc(#{(1 - $i) / $n} * 8s);
  }
}
Copy after login

Since each image accounts for 5% of the animation, we change this:

@keyframes m {
  0%, 3% { transform: rotate(0); }
  22%, 27% { transform: rotate(-90deg); }
  47%, 52% { transform: rotate(-180deg); }
  72%, 77% { transform: rotate(-270deg); }
  98%, 100% { transform: rotate(-360deg); }
}
Copy after login
Copy after login
Copy after login

…and this:

<div>
  <img alt="" src=""><img alt="" src=""><img alt="" src=""><img alt="" src="">
</div>
Copy after login
Copy after login
Copy after login

It should be noted that 5% is any value I selected for this example. We can also set it as a variable to control how long each image should remain visible. I'll skip this for simplicity, but as a homework you can try doing this and share your implementation in the comments!

.gallery {
  --s: 280px; /* 控制大小 */

  display: grid;
  width: var(--s);
  aspect-ratio: 1;
  padding: calc(var(--s) / 20); /* 我们稍后将看到它的用途 */
  border-radius: 50%;
}

.gallery > img {
  grid-area: 1 / 1;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: inherit;
}
Copy after login
Copy after login
Copy after login

The last point is to update transform-origin. We will need some geometric skills. The configuration is always the same regardless of the number of images. We place the image (small circle) inside a large circle and we need to find the value of the radius R.

You may not want a boring geometric explanation, so here is how to find R:

.gallery > img {
  /* 与之前相同 */
  animation: m 8s infinite linear;
  transform-origin: 50% 120.7%;
}

@keyframes m {
  100% { transform: rotate(-360deg); }
}
Copy after login
Copy after login
Copy after login

If we express this as a percentage, we get:

.gallery > img:nth-child(2) { animation-delay: -2s; } /* -1 * 8s / 4 */
.gallery > img:nth-child(3) { animation-delay: -4s; } /* -2 * 8s / 4 */
.gallery > img:nth-child(4) { animation-delay: -6s; } /* -3 * 8s / 4 */
Copy after login
Copy after login
Copy after login

…This means that the transform-origin value equals:

@keyframes m {
  0%, 3% { transform: rotate(0); }
  22%, 27% { transform: rotate(-90deg); }
  47%, 52% { transform: rotate(-180deg); }
  72%, 77% { transform: rotate(-270deg); }
  98%, 100% { transform: rotate(-360deg); }
}
Copy after login
Copy after login
Copy after login

We're done! We have a slider for any number of images!

Let's add nine pictures there: (The slider effect of nine pictures should be embedded here, but since I can't handle pictures and animations, I will omit it)

Add as many images and update the $n variable with the total number of images.

Summary

With several tricks of using CSS transformation and standard geometry, we created a nice loop slider without much code. The cool thing about this slider is that we don't have to bother copying the image to keep the infinite animation because we have a circle. After the full rotation, we will return to the first image!

The above is the detailed content of CSS Infinite and Circular Rotating Image Slider. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Latest Articles by Author
Popular Recommendations
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template