Testing HTML With Modern CSS

Heydon Pickering unleashes the power that CSS gives us with selectors and custom properties to create handy tests to make sure your markup is up to scratch.


I won’t dilute Heydon’s article by trying to summarise it, but if you’re similar to me by thinking “there’s gotta be something more powerful that :has() can do for us”, then Heydon has some answers to that.

Take this rule for example.

label:not(:has(:is(input,output,textarea,select))):not([for]) {
  outline: var(--error-outline);
  --error-unassociated-label: 'The <label> neither uses the `for` attribute nor wraps an applicable form element'
}

This rule determines if a <label> has a form child element or has a for attribute. If not, the <label> shouldn’t be there. We couldn’t do this level of selecting pre-:has() and using this capability to test that your HTML markup is in good shape is genius. This context is a fantastic use of CSS Custom Properties too.

Heydon might well have found me a use for Cascade Layers too, which I honestly thought would never happen…

Check it out