15 CSS Carousels
Collection of free HTML and pure CSS carousel code examples: responsive, horizontal and vertical. Update of December 2019 collection. 6 new items.
Related Articles
Table of Contents
Horizontal Carousels
Author
- Chris Neale
- July 6, 2020
Links
Made with
- HTML / CSS
About a code
CSS Variables 3D Carousel
Compatible browsers: Chrome, Edge, Firefox, Opera, Safari
Author
- Aybüke Ceylan
- June 13, 2020
Links
Made with
- HTML / CSS (SCSS)
About a code
Playlist Carousel — CSS Only
Compatible browsers: Chrome, Edge, Firefox, Opera, Safari
Author
- Christian Schaefer
- December 8, 2019
Links
Made with
- HTML / CSS
About a code
A CSS-only Carousel Slider
This carousel is created with HTML and CSS only.
Compatible browsers: Chrome, Edge, Firefox, Opera, Safari
Author
- TianyiLi
- December 6, 2019
Links
Made with
- HTML / CSS
About a code
Pure CSS Carousel
Animated pure CSS carousel.
Compatible browsers: Chrome, Edge, Firefox, Opera, Safari
Author
- Ronny Siikaluoma
- December 1, 2019
Links
Made with
- HTML / CSS (SCSS)
About a code
Carousel
Pure CSS carousel with thumbnails.
Compatible browsers: Chrome, Edge, Firefox, Opera, Safari
Author
- januaryofmine
- June 4, 2019
Links
Made with
- HTML / CSS (SCSS)
About a code
Responsive Sliding Carousel
Pure CSS, responsive sliding carousel.
Compatible browsers: Chrome, Edge, Firefox, Opera, Safari
Author
- William Goldsworthy
- March 26, 2019
Links
Made with
- HTML / CSS
About a code
CSS-Tricks Card Carousel
Compatible browsers: Chrome, Edge, Firefox, Opera, Safari

Author
- Gary Wesolowski
- April 13, 2018
Links
Made with
- HTML / CSS
About the code
Multidirectional Email Carousel
Carousel type build that scrolls over large background image using directional arrows. Unsupported environments will display a fallback static image.
Author
- Claudiu Lazar
- February 10, 2019
Links
Made with
- HTML / CSS
About a code
3D Carousel Rotating
Pure CSS 3D carousel which rotates.
Compatible browsers: Chrome, Edge, Firefox, Opera, Safari

Author
- Jack Oliver
- November 3, 2017
Links
Made with
- HTML
- CSS/SCSS
About the code
Infinite Autoplay Carousel
Useful for startup landing pages where you need to display brand partners and other cool logos or whatever.

Author
- Jhey
- May 24, 2016
Links
Made with
- HTML (Pug) / CSS (Stylus)
About the code
Pure CSS Carousels
Leveraging use of how elements behave in the DOM in combination with features of CSS makes implementing a pure CSS «carousel» relatively trivial.
Ant-карусель на CSS и Javascript
С появлением CSS3 появилась возможность совершать анимацию без использования JS-библиотек, таких, например, как jQuery. CSS3 свойство transition позволяет плавно изменять другие свойства элемента (width, height, margin, opacity и пр.), задав в качестве параметров время и закон трансформации. Предлагаю небольшую по размерам, но достаточно функциональную карусель на чистом Javascript. Небольшую, как муравей, что гораздо меньше чем сова. Но почти с такими же возможностями.
- показывать один или несколько элементов;
- элементы могут быть показаны в виде конечной или бесконечной ленты (в цикле);
- автопрокрутка элементов;
- навигация осуществляется стрелками, индикаторными точками или перелистыванием (для тактильных экранов);
- автоматически подстраивается под любую ширину экрана.
Здесь использованы элементы <ul><li>, но вместо них можно использовать <div > <div >, если вам это удобнее. Стрелки и индикаторные точки располагаются абсолютным позиционированием в соответствующих контейнерах. Для стрелок используются рисунки в виде треугольных скобок, которые, при желании, вы можете заменить своими рисунками или генерацией изображения псевдо-элементами :before и :after.
Создаём карусель с тремя видимыми элементами и шириной элемента 270 пикселей. Тогда максимальная ширина карусели 810 пикселей. Подключаем CSS-файл:
Располагаем элементы в контейнере ant-carousel-list, устанавливаем для него свойство display: flex и прижимаем все элементы к левому краю justify-content: flex-start. Свойство flex: 0 0 auto устанавливает flex-shrink в 0 (по умолчанию 1). Прокрутка элементов карусели осуществляется при помощи свойства transiton плавным изменением отступа margin-left от нуля до ширины элемента (в одну сторону) или от ширины элемента до нуля (в другую сторону). Для функции трансформации (прокрутки) используется значение ease.
Переходим к программе. В опциях программы можно настраивать:
- количество видимых элементов;
- просмотр элементов в виде ленты от первого до последнего или в бесконечном цикле (лента замыкается в кольцо);
- автоматическая или ручная прокрутка элементов;
- интервал автоматической прокрутки;
- скорость анимации;
- включение/отключение элементов навигации: стрелки, индикаторные точки, перелистывание прикосновением (для тактильных экранов).
Алгоритм прокрутки элементов отличается в зависимости от того, включена опция цикла или нет. Если включена, при прокрутке вправо (функция elemPrev) свойство margin-left всей линейки элементов this.crslList уменьшается от нуля до отрицательного значения, равного ширине элемента elemWidth. Одновременно последний элемент справа клонируется и вставляется перед первым элементом, после чего последний элемент удаляется. Линейке присваивается свойство ‘transition: margin ‘+ options.speed+’ms ease’, где options.speed – скорость анимации, ease – функция анимации. Теперь можно осуществлять прокрутку. Свойство margin-left плавно меняется от отрицательного значения до нуля, вся линейка плавно смещается вправо и элемент, который был последним, оказывается на первом месте. Спустя options.speed микросекунд линейке присваивается прежнее значение ’transition: none’.
Если нужно прокрутить n элементов одновременно, перестановка элементов осуществляется в цикле n раз, а расстояние margin-left увеличивается в n раз.
Прокрутка влево (функция elemNext) происходит в обратном порядке. Сначала линейке this.crslList присваивается свойство ‘transition: margin ‘+ options.speed+’ms ease’ и линейка плавно прокручивается влево (crslList.style.marginLeft = ‘-‘ + elemWidth + ‘px’). Далее спустя options.speed микросекунд первый элемент клонируется и вставляется в конец линейки, после чего первый элемент удаляется. Линейке возвращается значение ‘transition: none’. Если нужно прокрутить n элементов одновременно, перестановка элементов так же, как и в предыдущем случае, осуществляется в цикле n раз и расстояние margin-left увеличивается в n раз.
Если опция цикла выключена, то в этом случае перестановок элементов нет, а вся линейка элементов смещается как единое целое влево или вправо до своих крайних точек. Линейке элементов this.crslList свойство ‘transition: margin ‘+ options.speed+’ms ease’ присваивается ещё при инициализации карусели и больше не удаляется.
Вызов карусели производится по имени класса ant-carousel или по идентификатору. Во втором случае можно разместить несколько каруселей на одной странице. Файл index.html с каруселью может выглядеть так:
Чтобы разместить нескольких каруселей на одной странице нужно вызывать их по идентификатору. Разные карусели могут иметь разное количество элементов.
CSS Carousels
This article demonstrates how to create several CSS carousels for your webpage. Included are code walkthroughs and other carousel examples.
Carousels are essential to websites that rely on diagrams, products, text, and images because they can condense the content into smaller view areas. The smaller view areas reduce the need for a list of similar or relative items down a page. Additionally, a carousel can enhance the user experience of websites by making the site more interactive.
What Is a Carousel in CSS?
A CSS carousel is a container of HTML elements that allow users to navigate through different visual content, such as text, images, and videos. Usually, the active slide item is centered in the container, while previews of the previous and next items are shown on the sides. The navigation of the container is typically made up of buttons or arrows that control the direction of the next item (either backward or forward).

Carousel HTML Container Structure
The diagram above outlines the components that make up a simple carousel. These components are made of HTML elements, and let’s review each.
- Carousel Container – The container is the HTML element that holds all the other elements within the carousel. This can also be called the root element of the container.
- Hidden – The hidden sections are items such as images, text, or videos that are not in the container viewport or are previewed on each side. These items will slide into focus whenever the controls are used to navigate.
- Container Viewport – The container viewport shows the selected item in the carousel and most likely takes up the most room within this area.
- Focused Item – The focused item is the active item in the container viewport.
- Previous Preview – The previous preview on the left-hand side, in the viewport, is the item that will come into complete view when the carousel back controls are used.
- Next Preview – The next preview on the right-hand side, in the viewport, is the item that is next in sequence. This item will be the next focused item when the controls are used to move forward.
- Item – An item is each slide within the carousel, and they usually contain videos, images, text, captions, etc.
- Slider or Button Control – The slider or buttons control the various actions, such as back or forward, skipping to a slide, scrolling to the next, or any other actions that have been added.
Creating a Carousel With Arrows

Carousel With Arrows
This carousel is made up of three parts.
-
Radio Buttons – The radio buttons are hidden inputs that control which item in the track is shown to the user. By using radio buttons, we can pair it with a CSS general sibling combinator
- Arrows – The arrows are label elements programmatically attached to the radio buttons. Whenever a user clicks on an arrow, the corresponding input will be changed to a checked state, and the rest will be unchecked. Using the :checked pseudo-class selector, we can check the state of each radio.
- Container – The container is the track of the carousel. It contains all of the items. In the track container, the items are made into a horizontal row using the display: inline-flex and width: 33.33% properties. We can combine radio buttons, arrows, and the check state, to move an item along the track with a transform: translateX(value) . Once the transform is applied, it moves the specific slide into view.
In this example, we have created a feature to adapt to the device’s screen size. In the track, will we will create seven items. One item will be shown on mobile devices, two items on tablets, and three items on larger screens, such as desktops.
Now let’s create the needed HTML.
HTML
Next, we need to add the styles for the radio buttons, control arrows, items, and containers.
CSS
Some classes you may notice are the .item—mobile-in-1 .item—tablet-in-2 .item—desktop-in-3 on each slide item. As we talked about before, the layout for the items will be different depending on the device. These classes detect the screen size using a @media query. When the screen size matches the correct query size, the styles contained inside the query will be applied to the items in the track. The styles result in the responsive nature of the carousel. In addition to being responsive, the carousel also becomes swipeable, left or right, on smaller devices.

Responsive and Swipeable Carousel
Creating a Carousel for Movie Titles

Netflix Movie Title Carousel
The following example will demonstrate creating a carousel for movie titles using a Netflix theme. As we build the example, we use a couple of features to create a realistic effect for the movie title viewer. Let’s go over these features.
- Wrapper – The .carousel <div> element wrapper contains all the necessary elements to give the carousel its structure. It has a width with a value of calc(80% — 60px) and a left-right padding of 30px.
- Anchor Link – The <a> anchor link elements are the controls. They allow navigation to the different sets of movie titles. Each link has an id attribute corresponding to a section containing the same id. Since we set the value of the anchor link to an id, the carousel moves to that section whenever the forward or backward link control is clicked.
- Item – Each item in the carousel is the image of the movie title. The width of the items is set to 25% of the parent container width, which creates four titles in each section.
- Item Hover – On hovering a movie title, an animation is applied that adds a margin and a transform scale effect. The effect uses a transition property to ease the animation.
- Smooth Scrolling – When the titles change positions, we could call this scrolling, but it isn’t actual scrolling. The scrolling effect is a transform: translateX(n) property combined with a 0.75s transition ease. To get the correct translation length, we set each transform to multiples of 100 (100%, 200%, 300%). The transform tells the browser to shift the section 100% depending on if the value is right (positive) or left (negative).
Let’s begin creating the example.
HTML
Next, we need to add the styles.
CSS
Other Examples
Here is a collection of CSS carousel examples from across the web. Included are examples and code for reuse.
Carousels
Carousels provide a handy way to navigate a list of items. They differ from Lists as the items scroll to a focus point rather then a focus point moving over the items.
Imagine a long strip of cardboard with a sequence of pictures drawn on it. If you took a piece of paper and cut a small window in it, then moved the strip of cardboard behind the paper, you would see the pictures scroll by. This is essentially how the Carousel works.
In TAL Carousels, the ‘window’ is a div called the ‘Mask’. The strip of cardboard is a div within the Mask called the ‘Widget Strip’. The pictures drawn onto the cardboard are individual Widgets, or carousel ‘Items’. The items are contained within the Widget Strip and may be divs or other elements.

The above diagram shows how the various bits of the carousel fit together. The dotted area is hidden as it lies outside the mask.
Carousels can be arranged horizontally or vertically. Here is a vertical carousel

And here is a view of it’s structure in the DOM

Instantiating a carousel
The Carousel takes two parameters in its constructor, an id which will be used when constructing its constituent parts, and an orientation. Currently carousels can be vertical or horizontal, and these orientations are provided within a property of the Carousel class. If you do not explicitly provide an orientation the carousel will default to a vertical layout.
Adding items
Items can be added to the carousel using the standard container interface, for example
In contrast to the old horizontal carousel, the new carousel does not directly support data binding via its constructor. Instead you can use a Binder, which in turn calls appendChildWidget on the Carousel with each data bound widget.
When you create a carousel, you provide an id to the Carousel constructor. The id of the Mask and Widget Strip divs are derived from the one you provide. The mask has _CarouselMask appended and the Widget Strip has _WidgetStrip appended. In the example above ‘simpleVerticalHidingV2Carousel” was provided as the id. This gives each mask and strip a unique id within the document. In addition there are a number of css classes added to these elements:
- vertical — added to both the mask and strip in vertically oriented carousels
- horizontal — added to both the mask and strip in horizontally oriented carousels
- carouselmask — added to every mask in the document
- carouselwidgetstrip — added to every widget strip in the document
- carouselItem — added to every widget when it is added to a carousel
Some basic styling is required for a carousel to work correctly. These style properties are deliberately not set by default to allow for flexibility in creating style sheets.
The mask needs to have overflow set. In general you’ll want this hidden so the strip can flow outside its bounds without visible scroll bars. You might want to set it to something else if modifying animation behaviour or targetting a touch device. The mask needs to have a fixed length — this is width for a horizontal carousel and height for vertical carousel. This is so that the carousel can efficiently determine which widgets are outside the mask.
Widget Strip
The widget strip must have position set to relative to allow movement. Horizontal carousels need whitespace set to nowrap so that the items do not break onto multiple lines at the mask boundaries.
Items
For horizontal carousels, items need display set to inline-block, for vertical carousels items should have display set to block — this is so they are laid out correctly.
Below is some example css for generic carousels
And some additional, more specific css for the above example
The only essential part of this specific css is the height property, as this is a vertical carousel so the mask needs to have a fixed length.
Aligning
Movement of the carousel is performed by calling its method, alignToIndex. This method takes an integer as it’s first argument. This is the index within the carousel of the widget you want to move the carousel toward.
Two points are defined:
- The alignment point, a point along the mask element defined by a distance from the left or top of the mask (horizontal or vertical)
- The widget alignment point, a point along the widget being aligned, defined by a distance from the left or top of the widget.
The result of the alignment is to make the two points line up.

The alignment point along the mask can either be set in terms of pixels, or as a normalised value between 0 and 1, with 0 being the left or top edge and 1 being the right or bottom edge. Widget alignment points are always set using normalised 0 to 1 values.
As an example, if you wanted to focus the widget at index 4 so that it was centred in a carousel, you would call
If you wanted to align the right edge of the widget at index 3 to a point 300 pixels from the left edge of the mask, you would call
By default both alignment points are set to 0, i.e. the left or top edge of the widget you align will be moved to the left or top edge of the mask
Alignment events
Two events are fired:
- beforealign fired immediately before an alignment takes place
- afteralign fired when an alignment completes
both have two properties
- target — the carousel being aligned
- alignedIndex — the index of the item being aligned
Animation
The second argument of alignToIndex is an animation options object, which you can use to configure how each alignment animates, for example:
Would align to item 3 over the course of 500ms using a sine easing function. Note that by default animation is skipped, so the skipAnim property needs to be set false if you want animation.
If you wish to interrupt an animation, you must call carousel.completeAlignment(). This instantly moves the carousel to the end of an inflight alignment. If you attempt an alignment while one is already in progress and do not call completeAlignment, the new alignement will be queued to execute after the current alignment is complete.
If you are going to hide, destroy, or render a carousel invisible, you should first call completeAlignment. If you do not and are are using the CSS3 animation modifier, callbacks may not being cleared up resulting in a memory leak. You can call this safely if no animation is in progress, it just wont have any effect.
Aligning to the next or previous item
There are two additional helper methods, alignPrevious and alignNext to facilitate simple two-key navigation. These methods share behavior with alignToIndex. They use align points in the same way, can accept an animation options object and do not affect the active item.
Unlike alignToIndex, these methods take into account any widgets that have been disabled and will skip over them. Additionally, they will transition directly from the last to the first element (or vice versa) when using the wrapping strip (see below).
In general it’s easiest to use alignToIndex when initialising a carousel and alignPrevious / alignNext when navigating.
Items which change size during an alignment
The default widget strip measures the size of its elements when working out where to align. If elements change size during an alignment, this can result in the carousel aligning to the wrong place.
To cater for this situation, the carousel has a method setWidgetLengths. setWidgetLengths takes either a single number which will be used as the length for all widgets, or an array if providing individual lengths for each item. Lengths are in pixels. In addition, the appendChildWidget and insertChildWidget methods take an optional length as their second parameter if it is easier to provide lengths as each item is added.
In general it’s a good idea to provide lengths if they’re known in advance as it can improve performance (reading values from the DOM can result in unneccesary re-layouts)
Setting the active widget
Unlike the legacy horizontal carousel, alignment and the active widget are not tied together.
This can make layout easier, for example if the first item you can see is always flush with the left edge of the carousel but the active item should always be the third visible item, you can ask for this directly rather then having to calculate any offsets.
The methods for setting the item are:
- setActiveIndex — sets the widget at the supplied index active
- setActiveWidget — sets the widget provided active
Both will either succeed or do nothing (if the index / widget don’t exist in the carousel, or are disabled) You can also query the next or previous valid index using
- nextIndex
- previousIndex
Similarly to alignment, two events are produced during a change of active widget
- beforeselecteditemchange
- selecteditemchange
Carousels as lists
As setting a widget active and aligning to it are no longer linked, you can use a carousel as a list by only using the activeIndex methods, never performing an alignment.
Navigating with key presses
Other TAL widgets handle key presses internally, however this can cause problems when compositing multiple widgets into a larger structure with complex focus management. For this reason, the carousel does not directly consume key events, but to provide the same functionality, two simple key handler classes are provided which consume key and carousel events and provide some default interaction:
- AlignFirstHandler — On a key press will perform the alignment animation before the change in active item
- ActivateFirstHandler — On a key press will the change in active item before the alignment animation
To use the key handlers, you must instantiate them and then attach them to a carousel. They automatically use the UP/DOWN or LEFT/RIGHT keys for navigation, depending on the orientation of the carousel.
These Keyhandler classes listen for keypress events and call the carousel’s alignement methods. They also listen for alignment events and call the carousel’s activation methods.
The only difference between the AlignFirstHandler and ActivateFirstHandler is which alignment event they perform the activation change on.
The AlignFirstHandler listens to afteralign before calling setActiveChildIndex and the ActivateFirstHandler listens to beforealign.
In practice you will need to provide your own event handling for anything other then the most basic UI, but the key handlers provide a simple example of using an external controller to facilitate interaction with a Carousel.
Widget strips and navigators
By default the carousel behaves like the cardboard strip in the intro. All the items are always drawn on the strip and when you get to one end you can’t go any further.
In some situations, this may not be desired. To enable varied behaviour, there are alternative WidgetStrip and Navigator classes.
Broadly the widget strip represents the cardboard and the navigator is something that keeps track of what is active and what can be made active in the future.
The Widget Strip and navigator can be changed via setWidgetStrip and setNavigator. Both methods take a constructor function, not an instance (The Carousel instantiates them for you)
Wrapping carousels
You may want a carousel which behaves as though the strip was a loop with the start and end joined, allowing infinite navigation in each direction.
Creating a wrapping carousel is easy, you simply instantiate as usual then pass in the alternative navigator and widget strip classes. Strips are in antie/widgets/carousel/strips and navigators in antie/widgets/carousel/navigators
The way the wrapping strip works is to add copies of the elements at each end of the strip so that visually, it appears to wrap.
To ensure the carousel is always in a valid state, these clones are created each time an item is added or removed. On a slow device, when adding many items in a batch, this can be slow.
The carousel has a method autoCalculate(false) which can be used to disable this behaviour, and a method recalculate(), which can be used to manually force clone creation.
Culling carousels
On some devices adding a lot to the DOM up front can take a lot of time. Others do not optimise paints for elements hidden by an overflow.
In these cases, rather then having all items permanently on the strip, it may be desirable to take items in and out as they come into view.
There are currently two alternative widget strips that behave in this way. Both only generate and attach DOM elements when they are required by an alignment.
- CullingStrip — Takes items out of the DOM when they go out of view
- HidingStrip — Sets elements to visibility: hidden and opacity: 0 when they go out of view.
If using these strips it is compulsory to set widget lengths before performing an alignment. It may also be necessary to set the ‘Mask length’ (the size of the mask opening). Normally this length is measured from the DOM, but if the DOM is not ready when the first carousel alignment is made, then no items will be displayed unless the mask length has been explicitly set beforehand.
As you can only have one strip at a time in any given carousel, it is not currently possible to have carousel that both wraps and culls.
Navigators
There are currently two navigators
- BookenededNavigator (default) — Suitable for finite carousels where you cannot activate the index after the last or before the first
- WrappingNavigator — Suitable for wrapping carousels where navigation should wrap from the start to the end and vice versa.
Carousels in components
It can be easy to make mistakes when integrating a carousel with a TAL component, especially when using data binding, as some operations (alignment, for instance) make no sense until after a carousel is built and ready.
Included in the talexample project is a fairly complex example of a carousel component — it shows how to data bind, allows for configurable widget strips and supports custom aligment points via a config object passed in at component show.
Take a look at carouselcomponent.js and experiment by modifying _getCarouselConfig() in simple.js to alter the arguments passed to the carousel component.
TAL is an Open Source BBC project from TV Platforms in Salford
All code and documentation is licensed under Apache License v2.0
Documentation built using Jekyll, Bootstrap, Pygments, and gh3. Hosted on GitHub pages.