В чём разница между display: none, visibility: hidden и opacity: 0?
display:none удаляет элемент из потока (не занимает место, недоступен); visibility:hidden скрывает, но место остаётся (дочерние могут быть видимы); opacity:0 только прозрачность — элемент кликабелен и занимает место.
display: none, visibility: hidden и opacity: 0 — в чём разница
Все три способа делают элемент визуально невидимым, но работают на принципиально разных уровнях рендеринга и имеют разные побочные эффекты.
display: none — полное удаление из потока
Элемент полностью исключается из документного потока. Он не занимает место, не участвует в layout, браузер не генерирует для него box. Дочерние элементы также становятся недоступны. Изменение display вызывает reflow всей страницы.
.hidden {
display: none;
}
- Место не занимает — соседние элементы сдвигаются
- Недоступно для скринридеров (ARIA: не в accessibility tree)
- Не получает фокус (Tab-навигация пропускает)
- Не анимируется напрямую через CSS transitions (нельзя плавно показать/скрыть)
- Вызывает reflow при изменении
visibility: hidden — скрыт, но место занимает
Элемент невидим, но остаётся в потоке документа и занимает своё место в layout. Дочерние элементы можно сделать видимыми через visibility: visible — это уникальное свойство, не характерное для двух других подходов.
.invisible {
visibility: hidden;
}
.invisible .child-that-shows {
visibility: visible; /* дочерний видим, родитель скрыт */
}
- Место сохраняется — «дыра» в layout
- Недоступно для скринридеров
- Не кликабельно, не получает фокус
- Можно анимировать (transition работает дискретно — нет промежуточных значений)
- Вызывает repaint, но не reflow
opacity: 0 — прозрачный, но полностью в DOM
Элемент полностью прозрачен, но физически присутствует — занимает место, доступен для взаимодействия (клики, фокус), виден скринридерам. Анимируется плавно через transitions и GPU-ускоренные трансформации.
.transparent {
opacity: 0;
}
/* Плавное появление/скрытие */
.fade {
opacity: 1;
transition: opacity 0.3s ease;
}
.fade.hidden {
opacity: 0;
pointer-events: none; /* отключить клики вручную */
}
- Место сохраняется
- Кликабельно! Нужно добавлять
pointer-events: noneотдельно - Доступно для скринридеров (читается как видимое)
- Плавно анимируется, обычно GPU-ускоренно
- Не вызывает reflow
Сравнительная таблица
/*
Свойство | display:none | visibility:hidden | opacity:0
Занимает место | Нет | Да | Да
Кликабельно | Нет | Нет | Да
Скринридер | Нет | Нет | Да
CSS transition | Нет | Дискретно | Плавно
Reflow | Да | Нет | Нет
Дочерние Override | Нет | Да | Нет
*/
Практический пример: модальное окно с анимацией
.modal-overlay {
/* Комбинируем visibility + opacity для анимированного показа */
visibility: hidden;
opacity: 0;
transition: opacity 0.25s ease, visibility 0.25s;
}
.modal-overlay.is-open {
visibility: visible;
opacity: 1;
}
Это классический паттерн: visibility: hidden убирает элемент из tab-order и accessibility tree когда скрыт, а opacity обеспечивает плавный transition. Одного opacity: 0 недостаточно — элемент остался бы кликабельным.
Подводные камни
- opacity: 0 + pointer-events: скрытый через
opacity: 0элемент ловит клики — невидимая кнопка блокирует интерактивность под ней. Всегда добавляйтеpointer-events: none. - Доступность и opacity: скринридеры читают элементы с
opacity: 0как видимые. Для реально скрытого контента нуженaria-hidden="true"илиdisplay: none. - display:none не анимируется: нельзя написать
transition: display 0.3s— это не работает. Для анимации скрытия/показа нужны хаки (height: 0,visibility+opacityили Web Animations API). - visibility: hidden и дочерние элементы: то, что
visibility: visibleна дочернем элементе делает его видимым, может быть неожиданным и приводит к «дырам» в скрытых секциях. - Reflow при display: частое переключение
display: none / blockвызывает reflow — дорогостоящую операцию. При частых изменениях предпочитайтеvisibilityилиopacity. - stacking context у opacity:
opacity < 1создаёт новый stacking context, что влияет наz-indexдочерних элементов. - SEO: поисковые роботы могут игнорировать контент, скрытый через
display: none;visibility: hiddenиopacity: 0обрабатываются иначе у разных краулеров.
Common mistakes
- Смешивать «
display: none,visibility: hiddenиopacity: 0» с похожим механизмом без критерия выбора. - Игнорировать риск: неверно оценить границы применения темы «
display: none,visibility: hiddenиopacity: 0» и получить хрупкое решение. - Показывать только синтаксис и не объяснять поведение в runtime или сборке.
What the interviewer is testing
- Объясняет отличия скрытия элемента в layout, hit-testing и accessibility.
- Показывает на примере, как работает:
display: noneудаляет элемент из layout,visibility: hiddenоставляет место, аopacity: 0делает элемент прозрачным, но он может оставаться интерактивным без дополнительных правил. - Называет production-нюанс и граничный случай для темы «
display: none,visibility: hiddenиopacity: 0».