Originally posted on the Lexoral blog
This post has been updated. Expand for more details.
This post was updated 2022-03-04 based on discussions on Hacker News.
- Warned about potential performance issues of complicated svg-based animations
- If your accessibility settings indicate you prefer less motion on the page, the first example is now hidden by default with an explanation, rather than simply not animating
- Sticky positioning example fixed to work on Safari -
overflowmust be set to a value other than
- Indicated that checkbox-based dark mode is not a replacement for the CSS media query, and should be used in tandem
- Added more discussion around progressive enhancement, and reinforced that these examples are not production-ready
You can also see the full commit history for this post.
Along the way, I discovered just how much CSS has to offer, and I'd love to share some of that with you today. I know a lot of people are a bit scared of CSS, and see it as black magic, so I won't be showing you anything too complicated. Instead, I'm just going to focus on simple techniques and overlooked features - things you could easily incorporate into your own sites.
1. Animating SVGs
You probably know that you can animate HTML elements with CSS.
However, did you know that you can also animate SVGs, in exactly the same way?
One of my favourite techniques is setting the
stroke-dasharray property to a high value, then animating
That results in the path being 'drawn' over time, or a line moving along a path, like in this animation of some fireworks:
For another, more advanced example of how you can create animated diagrams with CSS, check out our landing page! The How it Works section contains a detailed animation. If you want to copy from it, Lexoral is open-source on GitHub.
Creating an animation like that is certainly more complicated than a simple video, and very detailed animations can cause hard-to-debug performance issues. However, there's plenty of reasons to prefer an animated SVG:
- Negligible bandwidth use
- Better device compatibility
- Perfect quality at any resolution
- Responsive & Scalable
- Can be checked in to VCS
If you want to learn more about CSS animations, I can recommend starting with the MDN guide. To create the SVGs, either use a visual editor like Inkscape, or a more dev-oriented tool like this one. Often it's easier to just write the SVG markup by hand, in which case MDN has a great reference page.
You want a side navigation bar that hides when it's not in use.
Put away that script file, we've got CSS for this.
transform to move it off-screen by default, then override that when the user hovers over the element.
Importantly, we should also show the menu when you use the
Tab key to select one of the links in the menu - an important step towards keeping our site accessible:
This example is just clever use of pseudo-classes in CSS. You probably skipped that link, but go back and click it. Even if you think you know everything about CSS, click it and read down that list pseudo-classes. Look how many there are. Think about how you could use them.
It's too easy to see
:hover and assume it's just for styling hyperlinks.
We've just seen it used to create a sidebar, but here's 9 more ways you could use it:
- Dropdown menus
- Showing Video Thumbnails
- Scaling up an image preview
- Showing a preview of the link destination like on Wikipedia
- Highlighting the important parts of a complex interface
- Styling the hovered row in a table
- Previewing what will happen if you click a button
- Making the 'Reject Cookies' button move out of the way when people try to click it
That last one was a joke. Please don't do that. I'm serious. I refuse to take responsibility if you do that. Please.
A few of those ideas would need a delay before the hover effect activated - it would be quite hard to use Wikipedia if a popup obscured half the screen every time you moused over a link.
transition-delay property first.
3. Sticky Positioning
Some of you are confused why I'm mentioning such a basic feature.
If that's you, skip to the next section.
Notice how when you scroll down, the blue square is always in exactly the same position. It's easy to tell when someone has tried to DIY their sticky positioning, because the element always lags one frame behind when scrolling. The faster you scroll down, the higher up the screen it would be. Then, when you stop scrolling, it jumps to the correct position.
Sticky positioning is a combination of
It's mostly used for navigation menus that should follow you as you scroll down the page.
It's used on this page too, if you are viewing it on a large landscape screen.
The panel to the right with my face on it uses
sticky positioning, meaning I'm always staring at you as you read my blogs.
To use sticky positioning, first you need to set
position: sticky and provide distances for some (usually only one) of
When the element is scrolled past that position on the screen, it swaps to
fixed positioning, and starts following you.
If you scroll back, it returns to its original position and stays there.
They don't follow you forever though - a sticky element will never move outside of its containing element.
It's a little difficult to wrap your head around, but I'd recommend reading through the MDN article on the position attribute.
position all the time, so I think it's worth having a good understanding of all the possible values and what they do.
4. Accordion Menus
Accordion Menus are commonly used for FAQs, where you have a list of headers and each one can be expanded to show the content inside.
This is another case of me telling you about a fairly basic feature of HTML+CSS, but
It's not always a good idea to use accordion menus due to them having a lot of usability issues.
<details> element is super useful when you want to hide some content from the user, especially if it's very long and most users won't want to read it.
For example, I used one just above here to hide the source code for the example.
If you're not sure whether to use a details element, try reading the NHS service manual for it. They've done way more usability testing than you ever will, and have some decent guidelines for when it's appropriate to use.
One downside of a pure-CSS approach here is that
It's possible to animate the box opening using
transition, as long as you know the height of the box when open.
5. Dark Mode
There's 2 components to this.
First, you should be using the
prefers-color-scheme media query.
This allows you to automatically display a light-mode or dark-mode version of the site, based on the user's preferences.
However, the best way to make your website accessible is to give the user choice.
Maybe they like dark mode usually, but on your website they would prefer light mode.
We can make use of
:checked - a CSS selector that only matches checked checkboxes.
You might be able to see where this is going:
This is actually a more general technique, which works any time you want to let the user toggle between two different versions of an element, or two different styles. For example, I used it in my last blog post to toggle between different versions of a code snippet.
The trick is to combine the
:checked pseudo-class with the
~ sibling combinator.
A CSS rule like
p ~ a applies to all
<a> elements that have a
<p> element sibling before them in the HTML document.
The actual rule used is
#checkboxId:checked ~ .body - which applies some styles to the body class only when the checkbox is checked.
Since the affected element must be a subsequent sibling, we can't put the dark mode checkbox inside the body element.
Instead, we put it before the body element, then use
position: absolute to position it inside.
It's daunting to learn the ins-and-outs of HTML/CSS. It can be frustrating when you know exactly what you want it to do but can't figure out how to tell the computer. However, it's easier now than ever before to make websites look great. CSS has had 20 years worth of development, and is full of new features to make life easier. If you want some further reading, check out:
- CSS Functions (transform, min, max, calc, gradients)
Some of the things I've mentioned are reasonably new, meaning that if you need to support Internet Explorer, these techniques probably aren't for you.
position: sticky and
:focus-within aren't supported in any version of IE.
Hopefully you can forget that Internet Explorer ever existed, in which case everything I've used here has close to 100% support in browsers!
Despite that, it's still best to embrace progressive enhancement. You should assume that your users will be using the most barebones browser imaginable, and make your site work as well as possible. Then, assume they're using a slightly better browser, and add things that make it work even better for those people.
Anyway, I think I've shown how powerful of a tool CSS can be when you really stretch yourself. The point of this post was never for you to just copy my example code, though you should feel free to do so. Instead, it's to give you some pointers towards the more useful parts of the language, and encourage you to explore what the more basic parts of web dev have on offer.
Send me a message if you make something cool!