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),#textcontent, 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 thepositionproperty. - 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:hoverstate won’t work, and clicking the same element won’t apply:focusor:activeeither. - 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 theclickevent 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@keyframestimeline 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-visibilityandcontent-visibilityproperties.backface-visibilityis only applicable to 3Dtransformoperations.content-visibilityis an optimization to speed-up page rendering during initial page-load, but requires CSS Containment first, which is out-of-scope for this QA.