CSS Tutorial
CSS Attribute Selectors
Attribute selectors let you style elements based on the presence or value of an HTML attribute, without needing a class or id. They are perfect for styling form inputs by type, links by protocol, or elements whose attributes you cannot easily change. This guide covers every attribute selector operator with runnable examples.
What are Attribute Selectors?
An attribute selector matches elements by their attributes. You write the attribute name (and optionally a value) inside square brackets. For example, [target] matches any element with a target attribute, and [target="_blank"] matches only those whose target is exactly _blank.
a[target] { color: red; } /* has a target attribute */
a[target="_blank"] { color: green; } /* target equals _blank */
input[type="text"] { border: 1px solid; }The Operators
Beyond exact matching, several operators match parts of a value. This is what makes attribute selectors so flexible.
| Selector | Matches when the attribute value... |
|---|---|
| [attr] | exists at all (any value) |
| [attr="val"] | is exactly val |
| [attr~="val"] | is a space-separated list containing the word val |
| [attr|="val"] | is exactly val or starts with val followed by a hyphen |
| [attr^="val"] | starts with val |
| [attr$="val"] | ends with val |
| [attr*="val"] | contains val anywhere |
Live Example: Matching by Value
This example styles links three different ways based on their href. Notice how ^= targets external https links, $= targets PDF files, and *= matches any link containing the word docs.
<!DOCTYPE html>
<html>
<head>
<style>
body { font-family: system-ui, sans-serif; padding: 20px; line-height: 2; }
a { text-decoration: none; }
a[href^="https"] { color: #16a34a; font-weight: bold; }
a[href$=".pdf"]::after { content: " (PDF)"; color: #dc2626; font-size: 12px; }
a[href*="docs"] { background: #fef9c3; padding: 2px 6px; border-radius: 4px; }
</style>
</head>
<body>
<p><a href="https://example.com">Secure link (starts with https)</a></p>
<p><a href="/files/guide.pdf">Download the guide (ends with .pdf)</a></p>
<p><a href="/docs/intro">Read the docs (contains "docs")</a></p>
</body>
</html>Styling Form Inputs by Type
A very common use is styling inputs based on their type attribute, since all text-like inputs share the input tag. Here text, email, and password fields get one style while a submit button gets another.
<!DOCTYPE html>
<html>
<head>
<style>
body { font-family: system-ui, sans-serif; padding: 20px; }
input[type="text"], input[type="email"], input[type="password"] {
display: block; width: 240px; margin-bottom: 12px; padding: 10px;
border: 1px solid #cbd5e1; border-radius: 6px;
}
input[type="submit"] {
background: #0f766e; color: #fff; border: none; padding: 10px 20px;
border-radius: 6px; cursor: pointer;
}
</style>
</head>
<body>
<form>
<input type="text" placeholder="Full name">
<input type="email" placeholder="Email">
<input type="password" placeholder="Password">
<input type="submit" value="Sign up">
</form>
</body>
</html>The ~= operator is handy for class-like space-separated attributes, and |= was designed for language codes: [lang|="en"] matches lang="en" and lang="en-US" but not lang="english".
Case-Insensitive Matching
Add an i flag before the closing bracket to match values regardless of case. This is useful for file extensions or user-entered values that may vary in capitalization.
/* Matches .PDF, .Pdf, .pdf, etc. */
a[href$=".pdf" i] { color: crimson; }An empty value like [attr*=""] is invalid and will not match anything. Also remember that attribute selectors are case-sensitive for attribute names in HTML but the values follow the document type rules unless you add the i flag.
Key points
- Attribute selectors target elements by attribute using square-bracket syntax.
- [attr] checks existence; [attr="val"] checks an exact value.
- ^= matches the start, $= the end, and *= any substring of the value.
- ~= matches a whole word in a space-separated list; |= matches a value or a hyphen prefix.
- Add an i flag for case-insensitive value matching.
