DEV Community

Cover image for Drop the anchooor! Short story about hyperlinks, their styling and states, and why LVHA rule is important
Barbara Szott
Barbara Szott

Posted on

Drop the anchooor! Short story about hyperlinks, their styling and states, and why LVHA rule is important

I am sure you know what anchors are!

They are links, or hyperlinks to be more exact. They are Internet's basic construction material - they make the Internet information highway. We can travel through them and teleport to a different part of Web in a blink. We all know what they are. Right? Right. But just to be 100% clear - in HTML <link> and <a> tags are something different.

The <link> element

I'm not going to write a lot about it. According to W3C:

The <link> tag defines a link between a document and an external resource and is used to link to external style sheets.

Also:

The element is an empty element, it contains attributes only.
This element goes only in the head section, but it can appear any number of times.

In HTML the <link> tag has no end tag. Default styling in all browsers is display: none. Most commonly you will see something like this in head section of HTML document:

<head>
    <link rel="stylesheet" href="styles.css">
</head>

If you want to learn more about <link> I encourage you to visit for example MDN Documentation. But for now - let's get back to business.

The <a> element

This is the main character of this story. Famous anchor element, that creates a hyperlink to other websites, files, e-mail addresses or just to other location within the same page. As opposed to the <link> it does need ending tag. It can have a whole bunch of attributes - the most widely known is href. Without it our anchor won't lead us anywhere.

<p>Check out my <a href="http://twitter.com/BarbaraSzott">Twitter</a></p>

The other very often used attribute is target - default value is _self, which means "load content here, in the same browsing context as the current one"; other commonly used value is _blank - "load content in the new browsing context", which usually means a new tab in the browser. I'm gonna stop here for a second to remind you about rel="noopener". You should consider adding this attribute while using target="_blank", especially for untrusted sources. Why?

Mostly for safety reasons - if rel="noopener" is used we avoid exploitation of window.opener API. Thanks to that when new window is created after clicking a link, potentially malicious code running on the new window won't access previous window through window.opener attribute.

<a href="http://someoneswebsite.com" target="_blank" rel="noopener">Some website</a>

Ufff, that part was difficult! If you are interested read more about noopener here.

Styling links - let's dive in!

Take a look at how simple link with default styling looks like:

image of link with default styling

Well, it is blue and underlined. Purple, if visited:

image of visited link with default styling

Nonetheless, typically this is not the appearance we want. Luckily for us - styling links is as easy as styling any other element. We can change color, add background color, borders, change font etc. Take a look at what is happening after changing some simple CSS for our <a> element:

a {
  padding: 15px;
  background-color: #00acee;
  border: solid 1px #008abe;
  border-radius: 15px;
  color: white;
  text-decoration: none; /* remove underline */
}

...and the result:

styled link

Nothing too fancy. We can play around with it however we want. The fun begins with introduction of link states, and there are (basically) four of them.

Link states

:link

:link state is CSS pseudo-class that basically means "unvisited". It matches every unvisited element with href attribute (so not only <a>).

But why use this pseudo-class, why can't I just style my anchor element? It's gonna apply either way, so what's the purpose of this state..?

There might be situations when you just want some general styling for anchor elements and special ones for unvisited links with, lets say, different classes (so different styling). On top of that - :link attribute only matches elements with href attribute. According to W3C spec:

If the a element has no href attribute, then the element represents a placeholder for where a link might otherwise have been placed, if it had been relevant, consisting of just the element’s contents.

So it's seems valid to use anchors without href. Besides, in the galaxy far, far away, before HTML5 was introduced, anchors could have had name attribute and no href attribute for on-site navigation. So we could do something like this:

<a href="#aboutUs">Click here to know us better!</a>
<!-- some code... -->
<a name="aboutUs"></a>
<div>Something about us</div>

Now this technique is considered obsolete and should not be used - we can simply use IDs to do the same thing:

<a href="#aboutUs">Click here to know us better!</a>
<!-- some code... -->
<section id="aboutUs">Something about us</section>

:visited

This state is self-explanatory - it selects links that already have been visited by current browser. We can add some styles for :visited to help users tell the difference between links they have or haven't clicked. Sounds simple - there is a catch though. It's again about security - listen carefully what MDN says about it:

Before about 2010, the CSS :visited selector allowed websites to uncover a user's browsing history and figure out what sites the user had visited. This was done through window.getComputedStyle and other techniques. This process was quick to execute, and made it possible not only to determine where the user had been on the web, but could also be used to guess a lot of information about the user's identity.

I've got goose bumps. For Pete's sake, it's just a link's state we want to style, and all of the sudden there is this issue. Fortunately it's been few years and now browsers take a good care of us. Nowadays the window.getComputedStyle method (and similar functions, like document.querySelector) will always return values adequate for unvisited links or page. End of topic, you won't get any styles with these method for :visited links.

So what about styling? Can we do what we want? Not exactly - we have limited options here, and they include: color, background-color, border-color, outline-color and the color parts of the fill and stroke attributes. What's more - you can only change these styles if the link already has these properties set for its unvisited version. Let's see how it works...

For simplicity I'm going to separate general a styles from its states' styles:

a {
  padding: 15px;
  border-radius: 15px;
  text-decoration: none;
}

...now the states:

a:link {
  color: purple;
  background-color: yellow;
}

a:visited {
  color: yellow;
  background-color: purple;
}

Everything works just fine - unvisited link is purple with yellow background and visited is yellow with purple background, just as we wanted it to be.
styled visited and unvisited link
But what if we decide that only visited link should have background color..?

a:link {
  color: purple;
}

a:visited {
  color: yellow;
  background-color: purple;
}

You guessed right - it's not gonna work.
visited link not styled cause unvisited version doesn't contain property
Color will be different, but background-color won't apply because unvisited version of that link doesn't have that property. If you gonna do opposite thing styles from :link will apply to unvisited link as well.

a:link {
  color: purple;
  background-color: orange;
}

a:visited {
  color: yellow;
}

visited link styled as unvisited version

What I've also found interesting here - if you don't specify border color it's gonna be borrowed from color property. (This applies to other elements as well)

a {
  /* some styles... */
  border: 2px solid;
}

a:link {
  color: purple;
}

a:visited {
  color: orange;
}

border color borrowed from color property

No matter how you style your unvisited and visited links, have always in mind that they should be easily distinguished from each other.

:hover

:hover is used to select elements when you mouse over them. It can be used not only on links but on all elements. It's important to remember that it might not work properly on touchscreens though. According to MDN:

The :hover pseudo-class is problematic on touchscreens. Depending on the browser, the :hover pseudo-class might never match, match only for a moment after touching an element, or continue to match even after the user has stopped touching and until the user touches another element. Web developers should make sure that content is accessible on devices with limited or non-existent hovering capabilities.

:active

This pseudo-class represents element that was activated (usually by the click). Link (or anything else, cause any element can have :active pseudo-class) is active only for a fraction of a second, but if we change appearance of this state we will give visual feedback that element was indeed clicked.

LVHA rule

Now is a good time to remind you about very important aspect of our beloved CSS - specificity. (If your are not familiar with that topic - there is nice article about it on CSS Tricks) Every selector has one. If two selectors apply to the same element, the one with higher specificity wins, and if you add two declarations that points at the same element in your stylesheet with the same weight - the CSS will choose the latter. This is how the cascade works.

a {...}         /* specificity = 1 */
a:link {...}    /* specificity = 1,1 */
a:visited {...} /* specificity = 1,1 */
a:hover {...}   /* specificity = 1,1 */
a:active {...}  /* specificity = 1,1 */

That's why order is important, especially for :hover and :active pseudo-classes. The other thing that you can see here - selector with pseudo-class has higher specificity, so styles from a:link might override these from a.

If you want you can style differently :hover for a visited link - just have in mind higher specificity:

a:visited:hover {...} /* specificity = 1,2 */

1.:link will be overridden by any subsequent link-related pseudo-class
2.:hover must come after :link and :visited
3.:active must go as a last one (otherwise it will be always overridden)

LVHA stands for:

  • L - :link
  • V - :visited
  • H - :hover
  • A - :active

It's also easy to remember as a LOVE-HATE rule. Using this order is considered best practice.

Summary

  • target="_blank" should always go with rel="noopener'
  • Visited and unvisited links should be easily distinguished - please remember not only about aesthetics but also (mostly) about readability, especially for users with impaired vision
  • :visited pseudo-class have limited styling (color, background-color, border-color, outline-color and the color parts of the fill and stroke attributes)
  • Styles for :visited will only apply if unvisited version of that link also have them
  • The :hover pseudo-class can be problematic on touchscreens
  • Styling :active state gives user visual feedback that something really was clicked
  • LOVE-HATE rule

I hope you had fun reading this article - I sure did writing it. It is my first tech-post - hope to see some feedback from you! Cheers :)

Top comments (1)

Collapse
 
yannisl profile image
yannisl

Use the LoVe Fears HAte if you want to remember to reset the focus state.