Drop the anchooor! Short story about hyperlinks, their styling and states, and why LVHA rule is important
Tags: css, html, webdev, frontend
Published: 2019-05-13 12:29:14

---
title: Drop the anchooor! Short story about hyperlinks, their styling and states, and why LVHA rule is important
published: true
tags: css, html, webdev, frontend,
cover_image: https://thepracticaldev.s3.amazonaws.com/i/blvgc2eomwcxgoca0cwl.png
---
#I am sure you know what anchors are!

They are links, or [hyperlinks](https://en.wikipedia.org/wiki/Hyperlink) 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 <link> 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:
```html
<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](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link). 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.

```html
<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.

```html
<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](https://mathiasbynens.github.io/rel-noopener/).

## Styling links - let's dive in!

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

![image of link with default styling](https://thepracticaldev.s3.amazonaws.com/i/e9m3z0o1xml8e48ytsa3.png)

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

![image of visited link with default styling](https://thepracticaldev.s3.amazonaws.com/i/exslw1wd7n43gwht2ryj.png)

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:

```css
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](https://thepracticaldev.s3.amazonaws.com/i/zpd4mbnpdgoaivcngk1t.png)

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](https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes) 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](https://www.w3.org/TR/2016/REC-html51-20161101/textlevel-semantics.html#the-a-element):

>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:

```html
<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:

```html
<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](https://developer.mozilla.org/en-US/docs/Web/CSS/Privacy_and_the_:visited_selector) 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:

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

...now the states:

```css
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](https://thepracticaldev.s3.amazonaws.com/i/mw303doqvp9pl3um7k62.png)
But what if we decide that only visited link should have background color..?

```css
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](https://thepracticaldev.s3.amazonaws.com/i/6l53yda34w6d2poffxn7.png)
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.

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

a:visited {
  color: yellow;
}
```
![visited link styled as unvisited version](https://thepracticaldev.s3.amazonaws.com/i/vgf6ai1jodxwuvi2p1hl.png)

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)*

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

a:link {
  color: purple;
}

a:visited {
  color: orange;
}
```

![border color borrowed from color property](https://thepracticaldev.s3.amazonaws.com/i/aeogpu2zys63o3yqkdh8.png)

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](https://developer.mozilla.org/en-US/docs/Web/CSS/:hover):


>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](https://css-tricks.com/specifics-on-css-specificity/)*) 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.

```css
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:

```css
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 <b>L</b>O<b>V</b>E-<b>HA</b>TE 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 :)