Skip to main content

Attribute selectors are OP

Summary: Attribute selectors are often only used on form elements as it makes it easy to select checkboxes, radio buttons and text fields. That's a great use case, but there is so much more that they can do!

Kevin Powell

This post was based on this YouTube Short

There are all sorts of selectors in CSS.

Of course, we have the classics:

/* element selector */
nav {
  ...;
}

/* class selector */
.navigation {
  ...;
}

/* id selector */
#primary-nav {
  ...;
}

And from there, you can add in combinators.

/* select all links that are a descendant of nav */
nav a {
  ...;
}

/* select all `li` that are direct descendants of `ul`
   that are direct descendants of `.navigation` */
.navigation > ul > li {
  ...;
}

But there is one selector that gets very little love even though it might be one of the most powerful ones out there, the attribute selector.

The attribute selector allows us to select an element based on an any attribute it might have by using square brackets, and including the attribute in there.

You can simply include an attribute’s name, and that will work, or you can go for an attribute and value to narrow down.

/* select any element with a class
   regardless of what that class is */
[class] {
  ...;
}

/* select any element with a type="text" */
[type="text"] {
  ...;
}

We see these most commonly within input elements, since we have several of them (text, email, radio, checkbox, etc.).

The real power here comes when you throw in some these seemingly random characters though | ~ * $ i.

Using |=

[class|="button"] matches exactly button OR button-, which can be pretty handy!

There is a downside to using |= though, in that the class list must start with button here, so this would not match <button class="accent-button"> or <a class="another-class button">.

See the Pen |= with attribute selector by Kevin (@kevinpowell) on CodePen.

Using ^= and $=

^= matches the start of an attribute, even if it’s only a few characters from a string, and $= is the opposite, matching the end instead.

For example, a[href^="https"] will match links that start with https, so we can assume these are external links and maybe add an external link.

a[href^="https"]::after {
  content: url("icon-external.svg");
}

In a similar vien, we can use a[href$=".pdf"] to select links that are to PDF files and add a PDF icon after these to let people know they’re downloading something.

a[href$=".pdf"]::after {
  content: url("icon-pdf.svg");
}

See the Pen styling external links and pdf links by Kevin (@kevinpowell) on CodePen.

Using i

And if you have some monster on your team who likes all caps, or if you have inconsistent file extensions for some reason (like the second PDF in the codepen above), you can use i to make selectors case insensitive as well.

/* only matches files that have lowercase .pdf extension */
a[href$=".pdf"]::after {
  content: url("icon-pdf.svg");
}

/* matches file extensions of .pdf or .PDF */
a[href$=".pdf" i]::after {
  content: url("icon-pdf.svg");
}

These are just some simple examples, there are many other useful and creative use cases for attribute selectors.

Link copied to clipboard