Currently the most common way to identify the current link is adding a class to the anchor or its parent:
<li class="active"><a href="/">Home</a></li>
This technique has a couple of drawbacks:
- Adding the class is often delegated to server languages and it means an extra work just for presentation.
- Even though there is a convention around the
active
class name, it's a stupid selector and doesn't seem to be semantically correct.
I tried the following with no success:
- I looked for something like the
:target
pseudo-class, so the selector could be: a:current
, unfortunately it doesn't exist yet.
- I thought the
rel
attribute was a good candidate, but I couldn't find any that fit.
Adding and attibute to the nav
that sets the current link, but we need to add id
s to every link, and CSS will become verbose
<style>
[data-active^="home"] a[id^="home"]{ color:red; }
</style>
<nav data-active="home-link"><ul>
<li><a id="home-link">Home</a>
...
Is there a different way to select current links that is semantically correct?
The purpose of selecting with CSS the current or active link is to give the user a clue about the section or document is currently viewing. As @BoltClock pointed out the active
class is semantically meaningless and the question is if there is a semantically meaningful way to select the link that belongs to the section or document the user is visting?
I looked for something like the :target
pseudo-class, so the selector could be: a:current
, unfortunately it doesn't exist yet.
Indeed, no such selector exists yet, so what you have is already your best bet. The following pseudo-classes sound like they might be what you're looking for, but they mean different things:
:active
matches an element that is being designated by the cursor; usually this means an element that is being clicked.
:target
matches an element whose ID matches the URL hash fragment, which means it only works for hash fragments and not the URL path itself.
:current
appears in Selectors 4, but it means something quite different entirely: it matches the chronologically current element. Since HTML itself doesn't have a concept of a timeline, :current
will match nothing (although I can imagine captioning or AT tools making full use of it in an HTML document).
That said, there is in fact a pseudo-class being proposed in Selectors 4 that targets the current document, only it's called :local-link
:
a:local-link { color: red; }
Of course, no implementations actually exist yet, so you're stuck with using a class name for the foreseeable future.
As helion3 has pointed out, the reason class names are used is because they're the easiest solution that exists today, and is tried, tested and true tradition dating back decades. Keep in mind that even HTML does not have "current-document" semantics beyond URL fragments, so you're really not going to be able to go any further than a class name or a custom data attribute with a hardcoded value.
I don't disagree with that article you've linked to either, but given there isn't in fact a "semantically correct" approach to this since no pseudo-class exists with the proper semantics, again you're basically stuck with this. If it makes you feel better, note that class names aren't really semantically incorrect in this case, rather they are semantically meaningless, i.e. they have no influence whatsoever on the meaning of the context they are in, or the document as a whole.
current is a concept that CSS doesn't have because CSS isn't involved with route handling. We use the active/current/at class names because it's the easiest way.
Javascript can easily set/remove classes based on routing, as can server-side languages.
Also, navigation structures are different and in your example, it's not the anchor that's active, but the li
. That should be left to developers to establish based on the needs of the styles.