At work I’m sometimes surprised when I discover a CSS feature that enables me to use some clever trick. Some of these features are brand new and still not widely supported (hello, polyfills!), others are pretty old but not commonly known.
Also, if you’re anything like me and prefer digging for “pure CSS” solutions rather than coding in JavaScript, you may find here a couple of hints that will make your life (as a developer) easier.
- Dynamically generating counters using only CSS
- Internal links and pure CSS lightboxes
- JavaScript-less sticky menus
- Accessing the HTML attributes’ values using CSS
- The
currentColor
property - CSS feature queries
Dynamically generating counters using only CSS
Assume we have a collection of items represented by HTML elements. We want them to be ordered and displayed with proper numbers. First thing that comes to mind is to mark them up as ordered list (ol
), and the browser will do the job for us.
- Tidy the room
- Buy groceries
- Write blogpost
So far, so good. We have semantic HTML and proper presentation. But what if we want to display the list with nested numbers? Or want to change the default look of numbers to fit into our designs? Oh yes, it’s possible to do it by hand, but
- it’s tedious,
- won’t work if the content is generated dynamically.
It’s possible to manipulate our HTML with JavaScript, but we are lazy developers, aren’t we? We want to use some pure CSS solution, which will be simpler and more performant. Say “hello” to CSS counters, which allow you to dynamically add order numbers to your lists and generated content.
CSS counters are, in essence, variables maintained by CSS whose values may be incremented by CSS rules to track how many times they’re used. This lets you adjust the appearance of content based on its placement in the document.
– MDN
To start generating numbers with CSS counters we need to know how to do the following:
- initialize the counter,
- increment the counter.
We initialize the counter for a parent element, which will contain our list of elements. It can be done with a counter-reset
property.
We need to provide a name for our counter to identify it. It works like a variable name, which we set as a counter-reset
property value.
Then we can increment our counter using counter-increment
property:
Alright, so we’re all set. Now we need to replace the default numbers of the ordered list and make them more stylish. It’s possible with the use of pseudoelements and content
property.
We can successfuly use counters not only for lists, but also for document sections (marking chapters with numbers, like in the codepen below) and other types of elements.
Browser support
In fact CSS counters exist for a pretty long time in the spec, so the browser support is awesome.
Chrome | Firefox | Safari | Internet Explorer/Edge | Opera |
---|---|---|---|---|
Any | Any | Any | 8+ | Any |
Resources and further reading
- Pure CSS games with
counter-increment
by Una Kravets - MDN article about using CSS counters
- About CSS counters and generated content on Smashing Magazine
- More practical examples of CSS counters usage
Internal links and pure CSS lightboxes
With HTML, it’s possible to link not only to external resources, but also to certain sections of a document. Such links are called the anchor links.
They are defined by a reference to an element’s id
attribute. We can enhance the experience of such kind of navigation using only CSS. There is a :target
pseudoclass, which can be used to select and style internal links in the document.
The example above is very simple and not very surprising. If you are waiting for something that will blow your mind or just make you think “oh, why I’ve been doing that using JavaScript for all these years” – there is indeed one clever trick involving :target
pseudoclass.
We can create simple lightboxes without a single line of JavaScript. Here is the markup for our elements:
We need to create a link to an existing section in our document. Clicking on this link should cause the lightbox to appear and apart from that we should also be able to close it. The magic here belongs to CSS.
Our lightbox should be initially hidden. We can apply display: none
to the .lightbox
element, but to make the effect more visually appealing we can enhance it with CSS transforms.
It’s also very important to apply position: fixed
to remove our lightbox from the document flow to make it look and behave exactly like a lightbox.
The lightbox’s id
value should be the same as the href
attribute value of the link. Then the following lines of CSS are responsible for opening the lightbox:
Browser support
Chrome | Firefox | Safari | Internet Explorer/Edge | Opera |
---|---|---|---|---|
Any | 3.5+ | 3.2+ | 7+ | 10.1+ |
Resources and further reading
- Article on MDN documenting the
:target
pseudoclass - Using The CSS
:target
Selector To Create JavaScript-less UI Effects by Sara Soueidan - A simple image gallery using only CSS and the
:target
selector by Christian Heilmann
JavaScript-less sticky menus
Sticky navigation menus are quite popular in contemporary web design. Creating a fixed menu and changing its position
when scrolling the document is feasible with a couple of lines of JavaScript. But if there is such demand for a certain design pattern implementation, shouldn’t it land in CSS specification soon?
In fact, there is a possibility to create a sticky menu with just a single line of CSS. Unfortunately, for now it only exists as an experimental feature (you can find the draft in the spec).
Turn the “experimental” flag in your browser and fasten your seatbelts!
Browser support
In Chrome and Firefox the feature works only after turning on the “experimental” flag.
Chrome | Firefox | Safari | Internet Explorer/Edge | Opera |
---|---|---|---|---|
No support | 32+ | 6.1+ | No support | No support |
Resources and further reading
Accessing the HTML attributes' values using CSS
Apart from CSS counters there are various ways to fill the generated content. One of them is accessing the value of HTML attributes using the attr()
function.
We can use this feature for creating links accessible in print media.
The result then should look like below:
Ire Aderinokun on her blog bitsofco.de described a clever trick with the use of the attr()
feature. It proves that styling broken images is possible.
Browser support
Chrome | Firefox | Safari | Internet Explorer/Edge | Opera |
---|---|---|---|---|
2+ | Any | 3.1+ | 8+ | 9+ |
The currentColor
property
Before CSS variables (custom properties) will become widely supported, we can alredy use a value with a variable-like feel. It’s called currentColor
and its usage is limited to properties that accept color as a value.
In the example above the element’s font color will be applied to both to border
and box-shadow
.
I prepared a small example of menu with a couple of items to show how currentColor
can help us write more reusable code. In the example the menu-item
’s left border and icon should change the color on hover and the color of each item should be different.
As we can see, there is no need to separately define colors for the icon and the border for each of the menu items.
Resources and further reading
- Short explanation on CSS-Tricks
- Cascading SVG Fill Color on CSS-Tricks
- Extending the Color Cascade with the CSS
currentColor
Variable by Sara Soueidan - Keeping CSS short with
currentColor
Browser support
Chrome | Firefox | Safari | Internet Explorer | Opera |
---|---|---|---|---|
Any | Any | 4+ | 9+ | Any |
CSS Feature queries
A Modernizr for CSS features? An automated “Can I Use?” in your stylesheets? You’re welcome!
Apart from querying for a certain type of media using @media
at-rule it’s also possible to query for CSS features. The rule @supports
can be used for testing if browser supports a certain feature and then apply nested CSS rules if the condition is met. For example:
Feature queries can help us to tackle uneven browser support and progressively enhance our websites.
Resources and further reading
Browser support
Unfortunately, the browser support isn’t too good for feature queries (they still aren’t supported in MS Edge).
Chrome | Firefox | Safari | Internet Explorer/Edge | Opera |
---|---|---|---|---|
28+ | 22+ | 9+ | No support | 12.1+ |