Use an attribute selector when the element you need is identified by an HTML attribute rather than by a class or ID. Put the attribute name in square brackets: [disabled] matches every element that has a disabled attribute, while input[type="email"] matches only email inputs. Add a type selector, combine multiple attribute tests, and choose an operator that fits the value you actually need to match.
This guide explains presence, exact, token, language-prefix, prefix, suffix and substring matching; case rules; practical patterns; debugging; and a way to capture the resulting page without configuring a browser.
Attribute-selector syntax at a glance
An attribute selector is a name, optionally followed by a matching operator and value, enclosed in square brackets. It can stand alone or follow a type selector such as a, input or [data-state]. The selector tests the represented attribute value; it does not infer an element’s intended role.
| Selector form | Matches | Example |
|---|---|---|
[attr] |
The attribute exists, including an empty value | a[title] |
[attr="value"] |
The complete value is exactly equal | input[type="email"] |
[attr~="value"] |
One whitespace-separated word equals the value | a[rel~="nofollow"] |
[attr|="value"] |
The value is exact, or starts with that value followed by a hyphen | [lang|="en"] |
[attr^="value"] |
The value starts with the string | a[href^="#"] |
[attr$="value"] |
The value ends with the string | a[href$=".org"] |
[attr*="value"] |
The value contains the string anywhere | a[href*="example"] |
Quote values when they contain spaces or characters that need string syntax. Whitespace between the attribute name, operator and value is optional, but consistent formatting improves readability.
Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Clear out junk files and repair common Windows errorsFree Scan →#1 Best Overall
Match an attribute’s presence
Use brackets without an operator
[attr] asks only whether the attribute is present. It does not require a nonempty value, so both <button disabled> and <button disabled=""> match button[disabled].
/* Any link carrying a title attribute */
a[title] {
text-decoration: underline;
}
/* Any element with a data-testid, regardless of its value */
[data-testid] {
outline: 1px dashed gray;
}
Presence is useful for boolean attributes such as disabled, required and hidden, and for locating hooks such as data-testid. It is different from checking whether an attribute’s text is a particular value.
Match an exact attribute value
Use = for the whole string
[attr="value"] succeeds only when the complete attribute value equals the quoted string. For example:
input[type="email"] {
border-color: teal;
}
button[data-state="open"] {
background: lightgreen;
}
An exact selector will not match data-state="open busy" or type="email address". Use it when additional words or characters should disqualify the element.
Recommended Free Tools
Rank #2
Choose the operator that matches your data
Whitespace-separated tokens: ~=
Use [attr~="value"] when an attribute contains a space-separated list and you need one token. a[rel~="nofollow"] matches rel="external nofollow", but not rel="nofollowed". This is the safer way to test one class-like word in a multi-token attribute.
/* Finds a token, not merely a substring */
a[rel~="nofollow"] {
color: #955;
}
Language-style prefixes: |=
[attr|="value"] matches the exact value or that value immediately followed by a hyphen. Thus [lang|="en"] matches lang="en" and lang="en-US", but not lang="english" or lang="en_GB". It is designed for language subtags, not general substring searches.
Starts with: ^=
[attr^="value"] matches values beginning with the supplied string. A common pattern selects fragment links:
a[href^="#"] {
scroll-behavior: smooth;
}
It also works for protocol or path filtering, such as a[href^="https://"]. Remember that it tests the literal attribute value; it does not resolve relative URLs.
Ends with: $=
[attr$="value"] tests the final characters. For example, a[href$=".org"] finds links whose written href ends in .org. Query strings or trailing slashes can prevent a match, so use this form only when the ending is stable.
Contains anywhere: *=
[attr*="value"] finds a substring at any position:
a[href*="example"] {
color: purple;
}
This is the broadest and most error-prone operator. It can match incidental text (for example, notexample.com), so prefer exact, token, prefix or suffix tests when your data has a clearer shape.
Combine selectors to narrow the result
Join a type and an attribute
[href] can match non-link elements that carry an href attribute. Prefixing it with a limits the result to anchors: a[href]. This makes intent clearer and avoids styling unrelated markup.
Require several attributes on one element
Concatenate bracket conditions with no combinator. Every condition must match the same element:
Rank #4
/* Secure .org links only */
a[href^="https://"][href$=".org"] {
color: green;
}
/* A visible, open dialog hook */
[role="dialog"][aria-hidden="false"] {
display: block;
}
These conditions are an AND relationship. A comma creates separate alternatives (an OR-style selector list), while a space would mean a descendant relationship and change the target entirely.
Control case sensitivity explicitly
Case behavior depends on the document language and the attribute’s semantics. HTML attribute names are case-insensitive. Some defined enumerated HTML values are also matched without regard to case, while values of class, id and data-* are case-sensitive by default.
For ASCII characters, append i for an ASCII case-insensitive comparison or s to request case-sensitive matching:
/* Matches .ORG, .org and other ASCII case variants */
a[href$=".ORG" i] {
font-weight: bold;
}
/* Requires the exact lowercase token */
[data-mode="dark" s] {
color: white;
}
Support for modifiers can vary in older user agents. If a target browser does not support a modifier, the selector will not match; verify the environments you support before making it essential to the design. The MDN attribute-selector reference records current syntax and compatibility notes.
Best Value
Common mistakes and safer fixes
- Testing a token with
=:[class="button"]requires the entire class attribute to be exactlybutton. Use[class~="button"]when other classes may appear. - Using
|=as a general contains test: it means exact-or-hyphen-prefix, not arbitrary substring. Use*=only when incidental matches are acceptable. - Assuming presence means a useful value:
[data-note]also matchesdata-note="". Add an exact or nonempty-value convention in your markup when that distinction matters. - Forgetting URL details: a suffix selector may miss
https://site.org/orhttps://site.org?a=1. Normalize URLs or select on a more stable attribute. - Overly broad substring matches:
[href*="admin"]can select unrelated domains and paths. Combine it witha, a protocol prefix, or a more specific path. - Expecting semantics or validation: CSS matches the represented attribute text. It does not confirm that
role,typeor a custom data value is appropriate for the element.
Debug an attribute selector in the browser
- Inspect the element and copy the attribute exactly as it appears in the DOM. Check for whitespace, case, query strings and trailing slashes.
- In DevTools’ Elements panel, press
Ctrl+F(Windows/Linux) orCommand+F(macOS), then search for the selector, such asa[href^="#"]. - In the Console, run
document.querySelectorAll('a[rel~="nofollow"]'). A result length of zero means the selector did not match the current DOM. - Temporarily add a visible rule such as
outline: 3px solid redto determine whether the selector matches but is losing a cascade or specificity conflict. - If dynamically generated markup is involved, run the query after the component renders. CSS selectors cannot match an attribute that has not yet been added.
Browser support and standards
Attribute selectors are broadly available across modern browsers; MDN describes the feature as well established across many devices and browser versions, with broad availability since July 2015. Individual details, particularly case-modifier behavior, can vary. Consult the MDN learning guide and the W3C Selectors Level 4 specification when targeting older or specialized user agents.
Or skip the browser setup
If you need a clean image of a page showing these selectors, ScreenshotNeo provides a one-request screenshot API and an MCP server for AI agents. It accepts cookie and consent banners before capture and removes more than 60 known consent platforms, newsletter popups and chat widgets; each step can be disabled. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed, and response headers identify the page verdict and billing status.
Capture with cURL
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Capture with Python
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
Capture with Node.js
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
See the complete parameter list and response details in the ScreenshotNeo documentation. Features include full-page and element capture, device presets, retina scale, PDF output, custom CSS and JavaScript, click and wait conditions, request blocking, headers, cookies, geolocation, signed links, asynchronous webhooks, bulk capture and a usage API. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000. Sign up for the free plan.
Frequently Asked Questions
Can an attribute selector target a data attribute?
Yes. Use the literal name, for example [data-testid="checkout"] or [data-role~="tab"]. Data-attribute values are case-sensitive by default.
PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchCan I select an element when an attribute is empty?
Use the presence form, such as [title], if empty and nonempty values should both match. An exact empty-string test, [title=""], restricts the result to an explicitly empty value.
Do attribute selectors work in JavaScript?
Yes. The same selector grammar can be passed to querySelector and querySelectorAll, provided the selector is valid for the current document.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




