CSS hints
CSS performance hints in use: content-visibility, contain, will-change.
At a glance the headline numbers for CSS hints
CSS performance hints in use: content-visibility, contain, will-change.
12.5% of sites use CSS containment. content-visibility sits at 11.3%.
The CSS hints mix who uses what, and how fast each group loads
CSS hints. On the fleet: 32.9% will change, 28.8% aspect ratio, 14.5% scroll driven. 100.0% of sites use at least one will_change.
Why this matters for the Core Web Vitals, and where to start fixing it
These CSS properties limit how far a change can spread. contain declares a subtree self-contained, so a change inside it does not force layout outside it. content-visibility goes further and skips rendering offscreen sections until the visitor approaches them. will-change moves an animated element onto its own layer, so animating it does not repaint the rest of the page.
They attack the DOM problem directly: a big tree hurts because every change can touch all of it, and containment makes updates local. That is exactly what INP needs. will-change is the one to ration. Every promoted layer costs memory, and a blanket will-change makes performance worse, not better.
Chrome field data from 189,915 sites, representing millions of real page loads. How we measured.
Live queries (2) — admin only
SELECT 1 AS ok FROM site_metric_bags LIMIT 0;
WITH flat AS (
SELECT b.cat, b.n, b.size, s.crux."all".lcp AS cwv_val
FROM site_metric_bags b
JOIN sites s ON s.origin = b.origin
WHERE b.path = 'css_hints.used'
AND b.cat IS NOT NULL
),
totals AS (
SELECT cat,
SUM(n) AS fleet_n,
SUM(size) AS fleet_size,
COUNT(*) FILTER (WHERE n IS NOT NULL) AS sample,
COUNT(*) FILTER (WHERE n > 0) AS with_any,
quantile_disc(n, 0.95) AS p95,
COUNT(*) AS n_rows
FROM flat
GROUP BY cat
),
widths AS (
SELECT *,
GREATEST(1, CAST(round(COALESCE(p95, 0)) AS INTEGER)) AS cap,
LEAST(GREATEST(1, CAST(round(COALESCE(p95, 0)) AS INTEGER)), 12 - 1) AS regular_buckets
FROM totals
),
widths2 AS (
SELECT *,
GREATEST(1, CAST(ceil(cap * 1.0 / regular_buckets) AS INTEGER)) AS width
FROM widths
),
binned AS (
SELECT f.cat, f.cwv_val, w.fleet_n, w.fleet_size, w.sample, w.with_any, w.width, w.regular_buckets,
CASE WHEN f.n IS NULL THEN NULL
ELSE LEAST(CAST(FLOOR(f.n * 1.0 / w.width) AS INTEGER), w.regular_buckets)
END AS bucket_idx
FROM flat f
JOIN widths2 w ON f.cat = w.cat
)
SELECT cat, fleet_n, fleet_size, sample, with_any, width, regular_buckets,
bucket_idx,
COUNT(*) AS n,
quantile_disc(cwv_val, 0.5) AS median,
COUNT(*) FILTER (WHERE cwv_val IS NOT NULL) AS total_cwv,
COUNT(*) FILTER (WHERE cwv_val IS NOT NULL AND cwv_val <= 2500) AS good
FROM binned
WHERE bucket_idx IS NOT NULL
GROUP BY cat, fleet_n, fleet_size, sample, with_any, width, regular_buckets, bucket_idx
ORDER BY cat, bucket_idx;