CSS attribute selectors let you target an element based on an HTML attribute it has — and not just whether the attribute exists, but what its value is, or even just part of its value. They're especially useful for styling things like links, form inputs, and custom data attributes without needing to add extra classes purely for styling hooks.

Basic Attribute Presence and Exact Match

/* Any element that has a "disabled" attribute, regardless of its value */
[disabled] {
  opacity: 0.5;
  cursor: not-allowed;
}

/* Only inputs where type is exactly "checkbox" */
input[type="checkbox"] {
  width: 18px;
  height: 18px;
}

[disabled] matches any element carrying that attribute at all, no matter what it's set to — even disabled="" or disabled="disabled" both match. [type="checkbox"] is stricter: the attribute's value must match exactly.

Starts-With, Ends-With, and Contains

Three more operators let you match part of an attribute's value instead of the whole thing:

/* href starts with "https://" */
a[href^="https://"] { color: green; }

/* href ends with ".pdf" */
a[href$=".pdf"] { color: crimson; }

/* href contains "simple2code.com" anywhere */
a[href*="simple2code.com"] { font-weight: bold; }

^= means "starts with," $= means "ends with," and *= means "contains anywhere in the string." They're easy to mix up, so a trick that helps: ^ is the caret used for exponents and points at the beginning of a line in regex, $ is the classic end-of-line regex anchor, and * just means "anything, anywhere" like a wildcard.

Practical Example: Styling External Links

A genuinely common use case is visually marking links that lead away from your own site, so users know before they click. You can do this with zero JavaScript and no extra classes in your HTML.

<p>
  Check out our <a href="/about">about page</a>, or read
  more on <a href="https://developer.mozilla.org/docs">MDN</a>.
</p>
/* Links starting with http that do NOT point at our own domain */
a[href^="http"]:not([href*="simple2code.com"])::after {
  content: " \2197";  /* a small arrow character */
  font-size: 0.8em;
}

This appends a small arrow after any link whose href starts with http (meaning it's a full external URL, not a relative internal one) and doesn't contain your own domain — giving external links a tiny visual indicator automatically, for every link on the page, forever, even ones added later. This combines an attribute selector with :not() and a pseudo-element to inject the arrow, showing how these smaller selector tools compose into something genuinely useful.

Attribute selectors can also be made case-insensitive by adding an i flag before the closing bracket, e.g. [href$=".PDF" i], which is worth knowing when matching user-generated or inconsistently-cased attribute values.