Attribute Selectors
Attribute selectors reach elements by what their tags say, such as every checkbox, the song that's playing now, every link to a PDF or every link that leaves your site, with no class added.
Apprentice · CSS · Updated
After this lesson you can
- Write an attribute selector that matches by an attribute's presence or exact value
- Match part of an attribute's value with ^=, $= and *=, such as links to PDFs or to other sites
Key takeaways
- Square brackets select by attribute.
[href]reaches every element that has an href, and[type="checkbox"]every element whose type is exactly checkbox. ^=is read "starts with",$="ends with" and*="contains". They match part of an attribute's value.a[href$=".pdf"]reaches links to PDF files, anda[href^="https://"]reaches links that go to another site.- Put the value in quotes. An attribute selector counts as much as a class in specificity.
A site's links sit side by side: one opens a page on the same site, one downloads a 4 MB PDF, one sends the reader off to someone else's site. A careful site marks the difference, so nobody waits for a download they didn't expect or loses their place. Nobody wants to add a class to every link by hand, and on a blog or a store the links are written by people who've never heard of your classes. The links already say where they go, in their href. Attribute selectors let CSS read it.
What a tag already tells you
An attribute is the extra information in an opening tag, written as a name, an equals sign and a value in quotes: type="checkbox", href="road-trip-mix-lyrics.pdf". Here are two songs and the footer from the Road Trip Mix page:
<li aria-current="true">
<strong>Mile Marker 88</strong>
<span>Coyote Radio</span>
<span>4:05</span>
<input type="checkbox" aria-label="Like Mile Marker 88">
</li>
<li data-rating="explicit">
<strong>Gas Station Coffee</strong>
<span>Lucky Static</span>
<span>2:58</span>
<abbr title="Explicit lyrics">E</abbr>
<input type="checkbox" aria-label="Like Gas Station Coffee">
</li>
<footer>
<p><a href="road-trip-mix-lyrics.pdf">Lyrics for every song (PDF)</a></p>
<p><a href="https://example.com/road-trip-mix">Share this mix</a></p>
</footer>
Three attributes here are new:
aria-current="true"tells a screen reader "this is the current one": the song that's playing now.data-rating="explicit"is a data attribute. Any attribute whose name starts withdata-is one a site makes up for its own use, and the browser leaves it alone. This page uses it to mark songs with explicit lyrics.<abbr>marks an abbreviation, and itstitlesays what the letters stand for.
[name]: has the attribute
Square brackets around an attribute's name make an attribute selector. [href] reaches every element that has an href, whatever its value. Put a type in front to narrow it: a[href] is "a link that has an href".
input[type="checkbox"] {
width: 1.25rem;
height: 1.25rem;
}
li[aria-current="true"] {
background-color: #fff3c4;
}
With an equals sign and a value, the attribute must have exactly that value. The first rule sizes every checkbox and leaves any text box on the page alone. The second picks out the one song that's playing now.
Quotes, capitals and specificity
- Put the value in quotes.
[type=checkbox]works too, but a value with a dot, a space or a slash (.pdf,https://) only works in quotes, so quoting every value saves you from guessing. - Values match exactly, capitals included.
[data-rating="Explicit"]doesn't matchdata-rating="explicit". Putibefore the closing bracket to ignore capitals:[data-rating="explicit" i]. - An attribute selector scores like a class. In the specificity columns from Specificity: Scoring a Selector,
li[aria-current="true"]is (0, 1, 1), the same asli.playingwould be.
^= $= *= : part of a value
Sometimes you know only part of the value: how a link starts, or how it ends. Three operators match part of it:
| Operator | Read | Matches when the value… | Example |
|---|---|---|---|
^= |
"starts with" | starts with the text | a[href^="https://"]: links to another site |
$= |
"ends with" | ends with the text | a[href$=".pdf"]: links to a PDF |
*= |
"contains" | has the text anywhere in it | a[href*="lyrics"]: links with lyrics in the address |
(^ is the caret, above the 6 on most keyboards, and $ is the dollar sign.) Here they mark the footer's two links:
a[href$=".pdf"] {
font-weight: bold;
}
a[href^="https://"] {
font-style: italic;
}
The lyrics link ends in .pdf, so it's bold; the share link starts with https://, so it's italic. A new PDF link added next month is bold the moment it appears, with no class and no change to the CSS. The next lesson but one, Pseudo-Elements: ::before, ::after and ::marker, puts a small "↗" after outside links, which is how many sites mark them.
Try it. In your road-trip.html, add the footer and the two rules. Then add a third link of your own, such as <a href="setlist.pdf">Setlist (PDF)</a>, save, and watch it turn bold. Change the .pdf rule's $= to ^= and save: why does nothing match now?
Reaching the right things without classes
Attribute selectors fit wherever the HTML already says what something is:
- Form fields by type:
input[type="email"],input[type="checkbox"], a[required]field. - Links by where they go: files (
$=".pdf",$=".zip"), outside sites (^="https://"), email links (^="mailto:"). - States other tools set:
[aria-current="page"]for the current page in a menu,[aria-expanded="true"]for an open menu. Styling the attribute keeps what screen readers hear and what everyone sees in step.
Check yourself
2 questions to try on the lesson page.
So what
The HTML already says a lot about every element. Attribute selectors let your CSS read it, so the page stays styled correctly as people add links, songs and form fields you never saw.