CSS Accessibility HTML Accessibility

Short note on content-visibility: hidden

content-visibility is a new property defined in the draft CSS Containment Module Level 2 specification. It has been implemented in Chrome 85, you can read about its glory in content-visibility: the new CSS property that boosts your rendering performance

What I am interested in is how it is exposed to screen readers and other assistive technology that make use of the content information represented in the browser accessibility tree. Firstly some explanation of what it is as defined in the spec.

CSS content-visibility property

The content-visibility property controls whether or not an element renders its contents at all, along with forcing a strong set of containments, allowing user agents to potentially omit large swathes of layout and rendering work until it becomes needed.


The element skips its contents.

The skipped contents must not be accessible to user-agent features, such as find-in-page, tab-order navigation, etc., nor be selectable or focusable.

Note: This is similar to giving the contents display: none.

content-visibility: hidden lays powerful restrictions onto an element, and so should be used with caution. It also enables some very useful scenarios, often improving on existing techniques.

Quick and dirty test content-visibility: hidden

See the Pen
content visability tests
by steve faulkner (@stevef)
on CodePen.

Testing the effect of content-visibility: hidden using a screen reader such as JAWS or NVDA and Chrome 85 turns up some interesting results.

When the property is applied to an img or p element:

img, p {content-visibility: hidden}

The content is visually hidden, but in both JAWS and NVDA the hidden <img> is announced but the content of the <p> element is not. This has to do with how the img and the p element content are represented in the browser accessibility tree: The img is exposed in the accessibility tree with the alt text as the accessible name. The content of the p element is not present in the accessibility tree

When the property is applied to a button:

button {content-visibility: hidden}
  • the button is still rendered but its child text is not.
  • While the button is not included in the focus order, it can be activated using the mouse.
  • It is announced, including the hidden text label and can be activated using the keyboard by screen readers.
  • If the same button is the child of a div that has content-visibility: hidden it is visibly hidden, and also hidden from screen readers i.e. it is absent from the accessibility tree.

Not supposed to be visible to screen readers

From reading the spec section on Using content-visibility: hidden, it states that when hidden the content should not be available to screen readers. Currently this is only partially true.

They’re also not visible to screen readers


Its an early implementation and a draft spec, so bugs in the implementation are expected, but if the property is supposed to be similar to display:none then no content with the property set should be available to screen readers. This may mean it is removed from the accessibility tree or a flag is set to indicate it is not meant to be rendered aurally.

5 replies on “Short note on content-visibility: hidden”

Nope, working-as-intended, tho using it this way isn’t use-as-intended. As the name says, it controls the visibility of the element’s *contents*, not the element itself.

It’s meant to be put on containers, like tweets or posts, so you can throw a whole bunch of them into the DOM without having to pay a ton of rendering/layout costs (just the cost of the pretending-to-be-empty containers themselves), and thus avoid difficult/fiddly/bad-for-screenreaders virtual-scrolling techniques. The container itself is still laid out and rendered, so if you guess/control the sizing of the container correctly, you *also* get an accurate scrollbar for the container *it* is in! (Plus you can render placeholders while it’s being hidden, like a background image.)

Using it directly on a (mostly) leaf element, like a button, isn’t going to be useful.

Leave a Reply

Your email address will not be published. Required fields are marked *