Detailed explanation
The main difference between `display: none` and `visibility: hidden` is whether the hidden element still participates in layout. With `display: none`, the element generates no layout box, so it takes up no space and surrounding content is laid out as if it were absent. With `visibility: hidden`, the element keeps its layout box, including its dimensions and margins, but is not painted. This leaves an empty area where the element would normally appear.
For example, consider two block-level divs followed by a paragraph. If the first div uses `display: none`, it contributes no height to the page. If the second uses `visibility: hidden`, its layout space remains, so the paragraph appears after that reserved space. Neither property removes an element from the DOM: JavaScript can still select it, update its content, or change its styles. Saying that `display: none` removes the element from the page is therefore less precise than saying it suppresses its layout boxes.
An important correction to the supplied short answer is that both properties normally exclude the hidden content from the accessibility tree; `visibility: hidden` does not generally preserve it there. Hidden elements themselves cannot receive keyboard focus or be clicked through ordinary pointer interaction. Descendant behaviour differs, however: a child can override inherited `visibility: hidden` with `visibility: visible` and become visible and interactive. A child of a `display: none` ancestor cannot make itself appear by setting its own display value, because the ancestor suppresses the entire subtree's boxes.
Use `display: none` when content should disappear without reserving space, such as an inactive panel. Use `visibility: hidden` when hiding content should preserve its place and avoid shifting neighbouring elements. Changing display can require layout recalculation because boxes are added or removed; changing visibility usually leaves geometry unchanged. Interviewers typically expect you to explain the spacing difference first, then distinguish DOM presence, accessibility, and descendant behaviour without treating the two properties as interchangeable.
Key points to remember
- `display: none` generates no layout box and reserves no space.
- `visibility: hidden` hides painting while preserving layout space.
- Both keep the element in the DOM and available to JavaScript.
- Both normally exclude hidden content from the accessibility tree and prevent the hidden element from receiving focus.
- A descendant can override hidden visibility, but cannot override an ancestor's `display: none`.
Common mistakes candidates make
- Claiming that `display: none` deletes the element from the DOM.
- Saying that `visibility: hidden` generally keeps content accessible to screen readers.
- Assuming a child can become visible inside a `display: none` parent by setting `display: block`.
Likely follow-up questions
How is `opacity: 0` different from these properties?
`opacity: 0` makes an element transparent while preserving its layout space. Unlike the other two properties, it normally remains in the accessibility tree and can still receive clicks and keyboard focus.
Can a child be visible when its parent uses `visibility: hidden`?
Yes, the child can explicitly set `visibility: visible` to override the inherited value. That visible descendant can also be interactive and exposed to assistive technology.
How should you reveal an element hidden with `display: none`?
Remove the hiding class or override the declaration so the intended display value applies again. Do not automatically use `display: block`, because the element may need `flex`, `grid`, or another display value.
Interview tip: Start with “no space versus reserved space,” illustrate it with two stacked elements, and then mention that both remain in the DOM but are normally hidden from assistive technology.
