Introduced with the CSS Level 2 Specification, attribute selectors make it possible to style elements based on the presence of an attribute, such as [controls] for a media player, or [disabled] for a form field.
You can also use attribute selectors to match elements based on the presence of an attribute and its value. For example, to style submit buttons, you might use the following CSS:
[type=submit] {
background: seagreen;
border: 0;
border-radius: 1000px;
color: #fff;
font-size: 18pt;
padding: 10px 20px;
}
There are also several attribute selectors for partially matching attribute values, as well as substrings. Being able to target partially matching attribute values is one of my favorite features of CSS selectors. When used thoughtfully, they can reduce the number of rules and declarations you need to write. We’ll look at them shortly. Most of the attribute selectors we’ll cover are old hat. I’ve included them, however, for context and completeness.
1. Matching Space-separated Attribute Values
Although we can select elements based on an attribute value, as discussed above, a selector such as [rel=external] won’t match <a href=”/” rel=”external citation”> , because the rel value isn’t exactly external . Instead, we need to use a selector that can accommodate space-separated values, which takes the form of [att~=val] .
The space-separated attribute value selector matches elements with the attribute ( att) and a list of values, one of which is val . This can be any attribute that accepts space-separated values, including class or data-* .
Space-separated lists of attributes are admittedly uncommon. They’re sometimes used with the rel attribute and microformats to describe relationships between people and documents. As an example, we might mark up external links like so:
<nav>
<a href=”http://bob.example.com/” rel=”external friend”>Bob</a>
<a href=”http://maria.example.com/” rel=”external acquaintance”>María</a>
<a href=”http://ifeoma.example.com/” rel=”external colleague”>Ifeoma</a>
</nav>
We can then use this presence-based attribute selector to match links that contain friend as one of its attribute values:
[rel~=friend] {
font-size: 2em;
background: #eee;
padding: 4px;
text-decoration: none;
border-bottom: 3px solid #ccc;
}
[rel~=friend]:link, [rel~=friend]:visited {
color: #34444C;
}
[rel~=friend]:hover{
background: #ffeb3b;
border-color: #ffc107;
}
The result of this is shown in the image below.
2. Matching Hyphenated Attribute Values
One of the more interesting tasks we can do with attribute selectors is to use [attr l=val] to match the first part of an attribute value before the first hyphen. For example, [Lang l=en] would match an element like <p Lang=”en-us”> .
The main purpose of this selector is for working with languages and language codes, such as en-US and es-MX .
Let’s say we have some markup like this:
<p lang=”fr-FR”><q>Tout le monde</q></p>
<p><q>All the world</q>, or <q>Everyone</q></p>
We can italicize our French text and add language-appropriate angle quotes (« and ») to either side of it:
[lang|=”fr”] {
font-style: italic;
}
[lang|=”fr”] q:before{
content: ‘\00AB’; /* Left angle quote */
}
[lang|=”fr”] q:after{
content: ‘\00BB’; /* Right angle quote */
}
What’s cool about this selector is that it works even if there’s no hyphen. So the styles above would also apply to <p Lang=”fr”> . And we can further limit the scope of these selectors by adding an element selector, such as p[Lang l=”fr”] .
This selector isn’t limited to language codes. We can use it with any hyphenated attribute value. Consider the following markup:
<article class=”promo”>
<h3>U.S. Meets Climate Goals 5 Years Early</h3>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing ….</p>
</article>
<article class=”promo-entertainment”>
<h3>Prince-Bythewood, Duvernay Among Nominees At Oscars</h3>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing ….</p>
</article>
<article class=”promo-sports”>
<h3>New York Knicks win NBA title</h3>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing ….</p>
</article>
<article class=”promo-business”>
<h3>GrubDash to Hire 3,000 Drivers, Offer Benefits</h3>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing ….</p>
</article>
These are all article promos or teasers. They share some of the same visual characteristics and behavior, along with classes prefixed with promo . Here, too, we can use the hyphenated attribute selector to match these class names:
class|=”promo”] {
border-top: 5px solid #4caf50;
color: #555;
line-height: 1.3;
padding-top: .5em;
}
[class|=”promo”] h3 {
color: #000;
font-size: 1.2em;
margin:0;
}
[class|=”promo”] p {
margin: 0 0 1em;
}
Follow this up with specific border colors for each section type, and you’ll achieve something along the lines of the layout pictured below.
We can also use this selector with ID names. For example, [id l=gLobaL] would match #gLobal-footer , #gLobal-menu , and so on.
3. Matching Attribute Values by Substring
We can also select elements when the attribute values match a particular substring using [att*=val] , [att$=val] and [att*=val] .
The ^= selector matches a substring at the beginning of an attribute value. For example, think about links using tel: (non-standard) or maiLto: . Since they behave differently from other hyperlinks, it makes sense to style them differently just as a hint to the user. Take a “Call this business” link:
<a href=”tel:+14045555555″>Call this business</a>
We can select this and other tel: links by using [href*=”tel:”] . Let’s add some declarations:
[href^=”tel:”] {
background: #2196f3 url(../../images/phone-icon.svg) 10px center /
→ 20px auto no-repeat;
border-radius: 100px;
padding: .5em 1em .5em 2em;
}
You can see the result in the image below.
The $= selector matches a substring at the end of an attribute value. If, for example, we wanted to give a special color to PDF file links, we could use a[href$=”.pdf”] :
a[href$=”.pdf”] {
color: #e91e63;
}
This selector would also be handy for matching elements whose attribute values end with the same suffix. For example, you could match both <aside cLass=”sports-sidebar”> and <aside cLass=”arts-sidebar”> with [cLass$=sidebar] .
The *= selector matches a substring in any position within the attribute value. Using the selector [cLass*=sidebar] , we could select an element with a class of sports-sidebar-a , along with elements with the classes sports-sidebar and arts-sidebar .
4. Matching Attribute Values by Case
CSS is, for the most part, a case-insensitive language. Both color: tomato and color: tomato do the same thing. Both p {…} and P {…} will style paragraphs in HTML, whether the HTML uses <p> or <P> . The same applies with attribute names, where [href] and [href] will both match href=”…” and HREF=”…” .
However, the same doesn’t apply to attribute values. Letter case matters with these. In the following markup, the ID attribute for our <div> tag mixes uppercase and lowercase letters:
<div id=”MixedCaseIDExample”>
The identifier for this tag mixes uppercase and lowercase letters.
</div>
To style the <div> , we might use its ID selector—that is, #MixedCaseIDExampLe . But we’d have to use it exactly as it appears in the HTML. Using #mixedcaseidexampLe , for example, wouldn’t cut it.
But there is an alternative. We could instead use case-insensitive attribute matching. It’s a feature defined by the Selectors Level 4 specification.
Case-insensitive attribute matching uses the i flag to indicate that these styles should be applied to any case combination:
[id=mixedcaseidexample i] {
color: blue;
}
Now our selector will match the ID attribute whether its value is mixedcaseidexampLe , MixedCaselDExampLe , or mIxEdCaSeldExAmPLE .
In some cases, you may want to enforce case-sensitive value matching. To enforce case- sensitive matching, use the s flag:
[id=”mixedcaseidexample” s] {
color: orange;
}
The s flag matches #mixedcaseidexampLe , but not #MixedCaseIDExampLe or #mIxEdCaSeIdExAmPLE .
Source: Brown Tiffany B (2021), CSS , SitePoint; 3rd edition.