Use the :lang pseudo-class over the lang attribute selector for language-specific styles
The content of HTML documents can be in many different languages.
To specify the primary language of a document, we use the lang
attribute on the root element.
<html lang="en">
We can also use the lang
attribute within the page to demarcate specific elements or sections that are in a different language to the document’s primary language.
<html lang="en">
<head></head>
<body>
<section lang="fr">
<p>Comment dites-vous "Bonjour" en Espanol?</p>
</section>
</body>
</html>
If we wanted to style these sections of the page differently, we could use the [lang]
attribute selector to select all elements, or children of elements, with the specific language attribute.
[lang="fr"] p {
background-color: #002295;
color: #fff;
}
The [lang]
attribute selector doesn’t know the element’s language #
The problem with having language-specific styles based on the [lang]
attribute selector is that the selector isn’t actually aware of the language of the element. It’s just like any other “dumb” attribute selector.
This can become a problem if we have a document with multiple, nested elements of different languages. Let’s take this section below. The section has a French lang
attribute but, within the section, we have a quote in Spanish.
<section lang="fr">
<p>Comment dites-vous "Bonjour" en Espanol?</p>
<blockquote lang="es">
<p>Hola!</p>
</blockquote>
</section>
In our CSS, we may have simply styled all elements with a particular lang
attribute and its descendants.
[lang="es"] p {
background-color: yellow;
color: #000;
}
[lang="fr"] p {
background-color: blue;
color: #fff;
}
CSS has no concept of prioritising closer parents, so it doesn’t matter that the Spanish lang
attribute is closer to the block quote paragraph element than the French one. Both of these styles are equally applicable. Because the style of the French language happened to be declared later in the CSS file, it prevails, even though, looking at the markup, we would have wanted the Spanish style to be used.
The :lang
pseudo-class #
The :lang
pseudo-class provides a solution to the limitations of styling the lang
attribute in two ways:
- It uses the actual language of the element selected
- It can be applied to any element and is not directly based on the
lang
attribute
:lang
and the "content language" #
The :lang
pseudo-class is used to select an element based on its content language. The content language of an element is determined by a combination of three things:
- Any
lang
attributes - Meta tags, e.g.
<meta http-equiv="content-language" content="en">
- HTTP headers, e.g.
Content-language: en
This means that the :lang
pseudo-class can be used even in cases where no lang
attribute is specified.
:lang
and nesting #
Being a pseudo-class, :lang
is best used on specific elements rather than on children.
Using the same example as above, we can switch to using the :lang()
attribute to select the paragraph elements. But instead of selecting the child paragraph elements of the specified languages, we can select the paragraph elements that are themselves of the specified language.
p:lang(es) {
background-color: yellow;
color: #000;
}
p:lang(fr) {
background-color: blue;
color: #fff;
}
Even though there is no lang
attribute on the paragraph elements themselves, we are still able to use the pseudo-class because the content language of the paragraph is inherited from its parent.
As we can see, the correct colours are applied to each paragraph.