В чем разница между CSS-свойствами visibility:hidden и display:none? Оба этих правила делают элементы невидимыми, но являются ли они по-настоящему синонимичными или у них есть различные поведения и эффекты на компоновку и рендеринг веб-страниц?
Основное различие между visibility:hidden и display:none в CSS заключается в том, как они обрабатывают пространство макета и рендеринг. visibility:hidden делает элемент невидимым, сохраняя его позицию и пространство в документе, в то время как display:none полностью удаляет элемент из макета, влияя на позиционирование окружающих элементов. Эти свойства оказывают различное влияние на доступность, производительность и взаимодействие с пользователем, что делает их принципиально разными решениями для скрытия контента.
Содержание
- Основные различия объяснены
- Поведение макета и рендеринга
- Влияние на доступность и скринридеры
- Рекомендации по производительности
- Различия во взаимодействии с JavaScript
- Практические рекомендации по использованию
- Распространенные случаи использования
Основные различия объяснены
Основное различие между visibility:hidden и display:none заключается в том, как они обрабатывают пространство элемента и рендеринг в потоке документа. Когда вы применяете visibility:hidden к элементу, элемент становится невидимым, но продолжает занимать то же пространство, которое он занимал бы, если бы был видимым [источник]. Браузер по-прежнему рендерит элемент в макете, что функционально похоже на установку opacity:0 - контент скрыт, но структурное пространство остается целым.
Напротив, display:none полностью удаляет элемент из потока документа. Браузер рендерит страницу так, как будто элемент вообще не существует [источник]. Это означает, что соседние элементы перемещаются, чтобы заполнить пространство, которое занимал бы скрытый элемент, что принципиально меняет макет страницы. Элемент фактически перестает существовать с точки зрения расчетов макета, интервалов и позиционирования.
Ключевое отличие: Представьте себе
visibility:hiddenкак невидимость элемента при сохранении его “места”, в то время какdisplay:none— как будто элемент никогда не существовал.
Поведение макета и рендеринга
Сохранение пространства против удаления
Наиболее значимое практическое различие заключается в том, как эти свойства обрабатывают пространство макета. При использовании visibility:hidden элемент сохраняет свои размеры и позицию в макете, что означает, что другие элементы не сдвинутся, чтобы занять его пространство [источник]. Это особенно важно, когда вы хотите временно скрыть контент, не нарушая окружающий макет.
При использовании display:none элемент полностью удаляется из дерева рендеринга. Это вызывает перерисовку документа, так как другие элементы адаптируются, чтобы заполнить доступное пространство [источник]. Макет пересчитывается так, как будто элемент никогда не существовал, что может быть полезно для полного удаления элементов из визуальной иерархии, но также может вызывать неожиданные сдвиги в макете.
Поведение дочерних элементов
Другое важное отличие заключается в том, как эти свойства влияют на дочерние элементы. При использовании visibility:hidden дочерние элементы наследуют свойство visibility, если оно не переопределено явно. Это означает, что вы можете установить родительский элемент в visibility:hidden, в то время как определенные дочерние элементы останутся видимыми, установив их индивидуальную видимость в visible [источник].
При использовании display:none все дерево элементов (включая всех потомков) удаляется из рендеринга. Нет возможности выборочно отображать дочерние элементы контейнера display:none — они все исчезают вместе с родителем.
/* Visibility позволяет выборочную видимость дочерних элементов */
.parent {
visibility: hidden;
}
.parent .child {
visibility: visible; /* Этот дочерний элемент останется видимым */
}
/* Display полностью удаляет все */
.parent {
display: none;
}
.parent .child {
visibility: visible; /* Этот дочерний элемент все равно будет скрыт */
}
Влияние на доступность и скринридеры
Поведение скринридеров
Оба свойства visibility:hidden и display:none в общем случае скрывают контент от скринридеров, но они делают это через разные механизмы в дереве доступности. Согласно [WebAIM], оба свойства удаляют элементы из дерева доступности, делая их недоступными для вспомогательных технологий [источник].
Однако существуют нюансы в поведении. Как объясняет [Marcy Sutton], скринридеры используют дерево доступности, которое содержит только то, что отображается на экране, и на него влияют CSS display:none и aria-hidden:true [источник]. Это означает, что оба свойства эффективно скрывают контент от скринридеров, хотя они достигают этого через разные внутренние механизмы браузера.
Интерактивные элементы и фокус
display:none оказывает более значительное влияние на взаимодействие с пользователем. Элементы с display:none полностью удаляются из порядка табуляции и не могут получать фокус с клавиатуры [источник]. Это делает их полностью недоступными для пользователей клавиатуры.
При использовании visibility:hidden элементы все еще присутствуют в DOM и могут потенциально получать фокус, хотя они остаются визуально невидимыми. Это создает запутанный опыт, когда пользователи могут взаимодействовать с чем-то, что не видят, что обычно нежелательно для доступности [источник].
Рекомендации по производительности
Производительность рендеринга
Различия в производительности между этими свойствами становятся заметны на сложных страницах и при частом переключении. Элементы с display:none полностью исключаются из процесса рендеринга, что может привести к лучшей производительности при скрытии больших объемов контента [источник]. Браузеру не нужно рассчитывать стили или выполнять вычисления макета для этих элементов.
Элементы с visibility:hidden все еще являются частью конвейера рендеринга. Браузер по-прежнему должен обрабатывать их стили и рассчитывать их позиции, даже если они невидимы. Это может быть менее эффективно для сложных элементов, особенно при анимации или частом переключении видимости.
Перерисовки и пересчеты макета
display:none запускает полный пересчет макета (reflow) при применении, так как элемент удаляется из потока документа. Это может вызвать значительное влияние на производительность на страницах с множеством элементов или сложными макетами [источник].
visibility:hidden обычно запускает только перерисовку (repaint), поскольку позиция и размер элемента остаются неизменными. Это делает его более эффективным для ситуаций, когда нужно часто переключать видимость без вызова пересчетов макета.
Как отмечает одно [обсуждение на Reddit], “в случаях, когда элемент с множеством дочерних элементов скрывается с помощью display, это может дать лучшую производительность, чем с visibility, потому что движок рендеринга вообще не беспокоится о перерисовке и заботе об этих элементах” [источник].
Различия во взаимодействии с JavaScript
Манипуляции с DOM
Оба свойства по-разному влияют на JavaScript. Элементы с display:none все еще доступны через методы DOM, такие как querySelector(), и могут манипулироваться с помощью JavaScript [источник]. Однако попытка взаимодействия с этими элементами (например, фокусировка кнопок) может вызвать неожиданное поведение.
При использовании visibility:hidden элементы остаются полностью интерактивными через JavaScript. Вы все еще можете прикреплять обработчики событий, манипулировать их свойствами и выполнять другие операции с DOM. Однако, как отмечает одно [обсуждение на Stack Overflow], “visibility: hidden работает безупречно, в то время как display: none заставляет кликабельные кнопки слегка подпрыгивать при нажатии, как будто он пытается показать скрытую кнопку на долю секунды” [источник].
Динамические изменения состояния
Изменения состояния, управляемые JavaScript, выявляют интересные поведенческие различия. Когда контент изначально устанавливается в display:none при загрузке страницы, скринридеры обычно не читают его. Однако, если JavaScript изменяет состояние с видимого на display:none, некоторые скринридеры могут не распознать это изменение и продолжат читать контент [источник].
Это создает потенциальную проблему доступности, когда контент может быть объявлен скринридерами, хотя он визуально скрыт. В этом отношении visibility:hidden ведет себя более последовательно, хотя оба свойства могут иметь неожиданные взаимодействия со скринридерами при динамическом изменении.
Практические рекомендации по использованию
Когда использовать visibility:hidden
Выбирайте visibility:hidden, когда:
- Вам нужно временно скрыть контент, не влияя на макет
- Вы хотите создать плавные переходы для анимаций показа/скрытия
- Вы работаете с формами и нужно сохранить состояние при скрытии элементов
- Вам нужно скрыть контент, но сохранить фокус для навигации с клавиатуры (в определенных случаях)
Когда использовать display:none
Выбирайте display:none, когда:
- Вам нужно полностью удалить элементы из потока документа
- Вы создаете адаптивные макеты, где контент должен быть полностью скрыт на определенных viewport
- Вы хотите оптимизировать производительность, исключив сложные элементы из рендеринга
- Вы создаете вкладки или аккордеоны, где контент должен быть полностью удален из доступности при скрытии
Лучшие практики
Для доступного скрытия, когда контент должен оставаться доступным для скринридеров, рассмотрите использование класса визуально скрытого элемента, например:
.visually-hidden {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
Этот подход сохраняет контент в дереве доступности, скрывая его визуально, что обеспечивает лучшую доступность, чем использование только visibility:hidden или display:none [источник].
Распространенные случаи использования
Применение visibility:hidden
- Постепенное раскрытие: Показ всплывающих подсказок или справочного текста при наведении
- Валидация форм: Временное скрытие сообщений об ошибках при сохранении макета формы
- Галереи изображений: Скрытие неактивных слайдов при сохранении структуры карусели
- Стили для печати: Удаление определенных элементов, которые не должны отображаться при печати, при сохранении структуры документа
Применение display:none
- Адаптивная навигация: Скрытие пунктов меню на мобильных устройствах и замена на гамбургер-меню
- Интерфейсы с вкладками: Полное удаление неактивного содержимого вкладок для улучшения производительности
- Условный контент: Удаление элементов на основе предпочтений пользователя или возможностей устройства
- Оптимизация производительности: Исключение тяжелых компонентов из рендеринга, когда они не нужны
Понимание этих тонких, но важных различий между visibility:hidden и display:none позволяет разработчикам принимать обоснованные решения о том, какое свойство использовать в разных сценариях, обеспечивая оптимальный макет, доступность и производительность для веб-приложений.
Заключение
Различия между visibility:hidden и display:none выходят далеко за рамки простого переключения видимости. Эти свойства принципиально изменяют то, как элементы взаимодействуют с потоком документа, по-разному влияют на доступность и имеют различные последствия для производительности. visibility:hidden сохраняет пространство макета и поддерживает присутствие элемента в DOM, в то время как display:none полностью удаляет элементы из рендеринга и расчетов макета. При выборе между ними учитывайте не только визуальное appearance, но и требования доступности, потребности в производительности и то, как должны вести себя дочерние элементы. Для большинства современных веб-разработок понимание этих тонких различий является ключевым для создания доступных, производительных и поддерживаемых пользовательских интерфейсов.
Источники
- FreeCodeCamp - CSS display:none и visibility:hidden – В чем разница?
- Stack Overflow - В чем разница между visibility:hidden и display:none?
- Tutorial Republic - Разница между CSS Display и Visibility
- HubSpot Blog - CSS Visibility: Все, что вам нужно знать
- Bomberbot - CSS display:none против visibility:hidden: Всеобъемлющее руководство
- Medium - Разница между “display: none” vs “visibility: hidden” vs “opacity: 0” в CSS
- W3Schools - CSS The display Property
- Code Entity - Скрытие элемента с помощью CSS: Display vs Visibility vs Opacity
- DZone - CSS Hide and Seek: display:none vs visibility:hidden
- DEV Community - Display: None vs Visibility: Hidden
- WebAIM - CSS in Action - Невидимый контент только для пользователей скринридеров
- Scott O’Hara - Inclusively Hidden
- Nomensa - Как улучшить веб-доступность, скрывая элементы
- Bitsofcode - Свойство visibility - это не только о видимости
- Zell Liew - Новый (и простой) способ скрыть контент доступно