# :contains() and numeric attribute selectors like [data-price>100]

> Select elements by their text with :contains() and compare attributes as numbers with [data-stock<5] or [data-price>=100]. Live updates, works in :has().

Source: https://csspp.dev/docs/content-selectors/


Native CSS can match an attribute's exact text, but it can't compare numbers or look at an element's text content. css-pp adds both, and they stay up to date as the page changes.

## :contains() — select by text {#contains}

`:contains("text")` matches elements whose text content includes the string:

```css
.badge:contains("Sold out") { background: #fee2e2; color: #991b1b; }
```

Add `i` before the closing parenthesis for a case-insensitive match, the same way native attribute selectors work:

```css
.status:contains("error" i) { color: #dc2626; }
```

Quotes are optional, but use them when the text contains commas, colons or parentheses: `:contains("Price: $5, today")`.

Like jQuery's selector of the same name, `:contains()` looks at all the text inside an element, including its descendants. Qualify it with a class or tag, as in `.badge:contains(...)`, so it doesn't also match every ancestor up to `<body>`.

### Style the parent by its text

Combine `:contains()` with `:has()` to style a container based on text further down:

```css
/* dim a whole product card when its badge says sold out */
.product:has(.badge:contains("sold out" i)) { opacity: .5; }

/* flag table rows whose status cell says "Overdue" */
tr:has(td.status:contains("Overdue")) { background: #fff7ed; }
```

## Numeric attribute comparisons

Compare an attribute's value as a number with `<`, `<=`, `>` or `>=`:

```css
.product[data-stock<5]     { outline: 2px solid #f59e0b; }
.price[data-amount>=100]   { font-weight: 700; }
.rating[data-score>4.5]    { color: #16a34a; }
.temp[data-celsius<0]      { color: #2563eb; }
```

Decimals and negative numbers work. Spaces around the operator are allowed: `[data-stock < 5]`. An element whose attribute is missing or not a number never matches.

The equality operators you already know (`=`, `^=`, `$=`, `*=`) stay native. css-pp only handles the comparisons CSS lacks.

```css
/* show the low-stock badge inside any card with fewer than 5 left */
.card .low-stock { display: none; }
.card:has([data-stock<5]) .low-stock { display: inline-block; }
```

## Live updates

Both selectors re-evaluate automatically when text changes, attributes change, or elements are added, for example by a framework, an AJAX call or a `setAttribute()`. You don't need to call anything.

```js
// the card above updates on its own
document.querySelector('[data-stock]').setAttribute('data-stock', '3');
```

## How it works

Each distinct condition gets its own attribute. `[data-stock<5]` becomes `[data-css-cmp-0]` and `:contains("sold out" i)` becomes `[data-css-contains-1]`, both with the same specificity as a class. css-pp tests only the elements the rest of the selector can match. A `MutationObserver` triggers a re-check when the page changes, throttled to at most one pass every 100 ms during bursts.
