While all 3 properties make an element’s box seem invisible, there are crucial differences between them:
Property | Painted | In layout | Stacking context | Pointer events | Keyboard events |
---|---|---|---|---|---|
opacity: 0; |
No | Yes | New | Yes | Yes |
visibility: hidden; |
No | Yes | Varies | No | No |
display: none; |
No | No | Varies | No | No |
- The “Painted” column indicates if the browser will paint the element’s background (e.g.
background-image
),#text
content, and so on.- An element cannot be painted without also participating in the page’s layout, of course.
- This is No for all 3 properties and values, as the browser won’t need to paint the element’s box as it’s invisible.
- The “In layout” column indicates if the browser will compute the layout and dimensions of the element – along with any of its descendants not excluded from layout.
- This is only No for
display: none;
, as withopacity: 0;
andvisibility: hidden;
the browser will still determine the size of the element so it can correctly layout other elements relative to the current element (e.g. if you havespan.hidden { visibility: hidden; display: inline; }
).
- This is only No for
- The “Stacking context” column indicates that any use of
opacity
(exceptopacity: 1.0;
) will create a new stacking-context, which complicates use of theposition
property. - The “Pointer events” column indicates if the element will respond to user-interaction from a pointing device, such as a mouse, touch-screen, stylus, etc.
- e.g. with
visibility: hidden;
then the:hover
state won’t work, and clicking the same element won’t apply:focus
or:active
either. - Additionally, the DOM won’t raise any pointer events you’d handle in JavaScript (e.g.
visibility: hidden;
won’t raisemouseclick
,touchstart
, etc – note that theclick
event can still be raised by certain elements, like<button>
if invoked by the user using a non-pointer input method, such as with keyboard or voice (accessible) navigation means.- You can use
pointer-events: none;
to block pointer events, but this won’t block keyboard and other non-pointer input and so should not be used to disable an element because the user can still use the keyboard to interact with it (especially<button>
,<input />
,<select>
, and<textarea>
).
- You can use
- e.g. with
- The “Keyboard events” column indicates if the element can be interacted-with using keyboard navigation (and possibly other navigation means).
- This includes smart-device (smartphones’ and tablets’) browsers’ “Prev/Next Field” buttons for navigating
<form>
elements (as this usestabindex
). - Unlike how pointer-events can be disabled in CSS using
pointer-events: none;
, there is no CSS property to disable keyboard interaction.
- This includes smart-device (smartphones’ and tablets’) browsers’ “Prev/Next Field” buttons for navigating
This table shows a more complete comparison between the main values of those 3 properties:
Property | Painted | In layout | Stacking context | Pointer events | Keyboard events | Animatable |
---|---|---|---|---|---|---|
Opacity | ||||||
opacity: 0; |
No | Yes | New | Yes | Yes | Yes |
opacity: 0.1; |
Yes | Yes | New | Yes | Yes | Yes |
opacity: 0.9; |
Yes | Yes | New | Yes | Yes | Yes |
opacity: 1; |
Yes | Yes | Varies | Yes | Yes | Yes |
Visibility | ||||||
visibility: hidden; |
No | Yes | Varies | No | No | Yes, with caveats |
visibility: visible; |
Yes | Yes | Varies | Yes | Yes | Yes, with caveats |
Display | ||||||
display: none; |
No | No | Varies | No | No | No |
display: contents; |
Text and children only | Text and children only | Varies | Yes | Yes | No |
Other | ||||||
pointer-events: none; |
N/A | N/A | N/A | No | Yes | No |
-
The “Animatable” column indicates if that property can be used with a CSS transition (
transition:
) or CSS animation (@keyframes
).- Crucially, the
display:
property cannot be animated, which is why we can’t use a@keyframes
timeline to completely hide an element after the animation is complete.- But curiously, we can animate the
visibility:
property despite being non-continuous, albeit with caveats.
- But curiously, we can animate the
- Crucially, the
-
Also, don’t get confused by the similarly-named
backface-visibility
andcontent-visibility
properties.backface-visibility
is only applicable to 3Dtransform
operations.content-visibility
is an optimization to speed-up page rendering during initial page-load, but requires CSS Containment first, which is out-of-scope for this QA.