Did you know that you could create slides with HTML and CSS only? Let’s see how.
HTML
HTML structure consists of slides container and slides items.
<div class="slides">
<div class="slides__item">...</div>
<div class="slides__item">...</div>
</div>
CSS
Let’s start with CSS Variables. We will need the following:
--slides-font-size
, for setting the font size,--slides-height
, for setting the height of the slides items,--slides-inline
, for setting padding and scrollbar width,--slides-bg1
and--slides-bg2
, for slides items background colors, and--slides-color
, for slides items text color.
.slides {
--slides-font-size: 10vh;
--slides-height: 100vh;
--slides-inline: 10px;
--slides-bg1: hotpink;
--slides-bg2: dodgerblue;
--slides-color: white;
}
@supports (height: 100dvh) {
.slides {
--slides-height: 100dvh;
--slides-font-size: 10dvh;
}
}
I’ve decided to try the new dynamic dvh
units. Unfortunately, it isn’t globally supported yet, so I had to check if browsers support it.
Slides container
To simulate the slides effect, we will limit the container’s height to the viewport’s height by using 100vh
, or, in case dynamic units are supported, 100dvh
. I’ve used viewport units for font sizing, too.
.slides {
color: var(--slides-color);
font-family: cursive;
font-size: var(--slides-font-size);
line-height: 1;
max-height: var(--slides-height);
overflow-y: auto;
}
Slides items
Slides items are flexbox items with centered content with a minimum height of 100% of the viewport height. That means the item will consume the whole viewport, which emulates a single slide.
Centered content means that you must wrap the inner content in a div
if you have more than one child.
Every other slide has a different background color, distinguishing them from each other.
.slides__item {
display: flex;
align-items: center;
justify-content: center;
padding-inline: var(--slides-inline);
min-height: var(--slides-height);
position: relative;
&:nth-child(odd) {
background-color: var(--slides-bg1);
}
&:nth-child(even) {
background-color: var(--slides-bg2);
}
a {
color: inherit;
}
}
The slides effect
So far, we have a regular page that behaves normally. To enable the slides effect, we will use CSS Scroll Snap.
CSS Scroll Snap means that the regular scroll experience is enhanced to adjust the scrolling position to desired items. That “adjustment” effect is called snap.
- The
scroll-snap-type: y mandatory
declaration enables snapping on the vertical axis. - The
scroll-snap-align: start
declaration tells the browser to “adjust” the scroll position to the top of the container (in our case, the vertical axis). - The
scroll-snap-stop: always
declaration tells the browser to snap only one item at a time.
@supports (scroll-snap-type: y mandatory) {
.slides {
scroll-snap-type: y mandatory;
.slides__item {
scroll-snap-align: start;
scroll-snap-stop: always;
}
}
}
The whole block is placed inside the @supports (scroll-snap-type: y mandatory)
which enables snapping only when supported.
Reduced motion
I've tried to disable the smooth scrolling by taking advantage of the scroll-behavior
property, but you cannot do it.
Maybe there could be a value that unsets the scroll behavior. For example, scroll-behavior: none
.
Or, maybe there could be a snap-scroll-bahaviour
property that enables or disables scroll behavior.
Bonus: styled scrollbars
We could style scrollbars to make our slides feel more like an app. There are three properties that you could define:
- scrollbar background color,
- scrollbar foreground color, and
- the width of the scrollbar.
You must use prefixed selectors.
.slides {
scrollbar-color: var(--snap-bg1) var(--snap-bg2);
&::-webkit-scrollbar {
width: var(--snap-inline);
}
&::-webkit-scrollbar-thumb {
background-color: var(--snap-bg1);
}
&::-webkit-scrollbar-track {
background-color: var(--snap-bg2);
}
}
Conclusion
There you have it, CSS-only slides. What I love about this solution is that it is responsive and works well on almost every device.
I already made a few slides on my site using this solution. You can see them in the following links: