Когда display: none, а когда visibility: hidden?

Зависит от того, что вы пытаетесь сделать. Есть и другие варианты как спрятать блок и даже специальный атрибут.


Если вам приходится что-то прятать, то лучше всего это вообще убрать: сайт легче, код чище… ошибок меньше! Но если вам нужно, чтобы оно там пряталось до поры, а потом кому-то пригодилось — это другое дело. Здесь важно не ошибиться с выбором способа.


Самый простой и популярный — display: none, он работает как топор: элемент как будто вырубают из HTML. Его не видно на странице и соседние блоки про него ничего не знают. Просто нет и всё. Его даже скринридеры игоририруют и не читают содержимое — будьте аккуратнее с этим.


/* Вырубает */

.cut-down {
  display: none;
}

Что интересно, несмотря на полное вырубание элемента, браузеры всё равно загружают картинку из img с display: none. Если же картинка указана фоном, то Chrome и Edge её тоже загружают, а Firefox и Safari — нет. Ну, разные у них взгляды на оптимизацию загрузки, что поделать.


Другой способ — visibility: hidden, он работает как кольцо всевластья: элемент вроде здесь и соседние блоки его чувствуют, но его не видно. И чем это отличается от opacity: 0? Opacity просто делает элемент прозрачным (или полупрозрачным), а visibility: hidden ещё не даёт с ним взаимодействовать: навести, кликнуть, сфокусировать.


/* Прячет */

.one-ring {
  visibility: hidden;
}

/* Не сработает */

.one-ring:hover {
  visibility: visible;
}

У visibility: hidden есть другая приятная особенность: свойство наследуется, а значит ребёнок невидимого родителя может сменить видимость на visible. Такой трюк не пройдёт ни с display: none, ни с opacity: 0. С ним удобно делать всплывающие меню и подказки.


Иногда нужно, чтобы элемент не мешал дизайну, но при этом не прятался от скринридеров, оставаясь частью содержимого. Ну не нарисовал дизайнер здесь заголовка, а по логике документа он здесь нужен. Вот бы нам что-то вроде display: hidden или visibility: none! Это я только что придумал, в природе их не существует.


Недавно в черновике CSS Display третьего уровня появилось свойство box-suppress со значениями show, discard и hide. Оно отвязывает видимость блока от display — ведь с обратной стороны от none есть не только block, но и inline, flex, grid. Значение discard привычно вырубает элемент, а hide делает то самое волшебное комбо. Читайте подробнее у Рейчел Эндрю.


/* То, что нужно */

.combo {
  box-suppress:
    hide;
}

К сожалению, до box-suppress нам ещё долго ждать. Его не только ещё нет в браузерах, но уже в том черновике — недавно его перенесли в следующий уровень, чтобы закончить текущий вовремя. Так что придётся делать магию самим — следите за руками.


Есть такой паттерн «visually hidden» или «визуально спрятанный», чтобы прятать элементы из дизайна, но оставлять доступным их содержимое. Про другие нюансы со скринридерами читайте у Тима Райта. Как это работает: вы делаете универсальный служебный класс и добавляете его к элементам, которые нужно доступно спрятать. Обычно его так и называют: visually-hidden, через дефис.


<h2 class="
   visually-hidden">
    Важный
    за головок,
    которого нет
</h2>

Если посмотреть что внутри, то это обычный position: absolute плюс clip, который обрезает элемент до нуля. То есть он не влияет на соседей и становится невидимым. Все остальные свойства добавляют универсальности и кроссбраузерности, чтобы класс можно было не глядя шлёпнуть на любой элемент. Подробнее читайте в справке к ally.js Родни Рейма.


.visually-hidden {
  position: absolute;
  clip: rect(0 0 0 0);
  width: 1px;
  height: 1px;
  margin: -1px;
  …
}

А вы знали, что любому элементу можно добавить атрибут hidden и он пропадёт? Теперь знаете! В современных браузерах на этот атрибут повешен тот самый display: none, который вырубает элемент. Он бинарный как required или checked, так что его удобно выставлять через JavaScript. Только не забудьте добавить в стили [hidden] { display: none } для IE 10, Safari 5 и других старых браузеров.


<div hidden>
  Вырублен
</div>

// JS
div.hidden = true;

Это почти всё, что вам нужно знать про прятки в CSS. Попробуйте эти способы, они все хороши в разных ситуациях. Главное, не рубите с плеча и думайте о доступном содержимом.


Видеоверсия



Вопросы можно задавать здесь

Комментарии (10)


  1. kahi4
    03.11.2017 20:19
    +2

    Что это за серия вредных туториолов для начинающих на хабре? Вы собрались все свойства css рассказать, прикрепив ненужный видеофайл?


    Иногда нужно, чтобы элемент не мешал дизайну, но при этом не прятался от скринридеров, оставаясь частью содержимого.

    И влетел в бан в гугле и яндексе за это. Для доступности у html хватает аттрибутов, их и стоит использовать, а не заниматься дичью вроде top: -9999px (еще один способ, как и сделать текст такого же цвета как и фон, много их было).


    И не написано, что переключение display приводит к пересчету лайаута, а visibility нет. Причем переключение каждого display будет приводить к пересчету, так что стоит избегать изменений этого свойства в цикле и все такое, но это да, не для новичков.


    1. andreymal
      03.11.2017 21:38

      переключение каждого display будет приводить к пересчету, так что стоит избегать изменений этого свойства в цикле

      Я всегда думал, что пересчёты ленивые и производятся только по необходимости, а не сразу после изменения, это не так что ли?


      1. kahi4
        03.11.2017 22:56

        Покуда сразу следующей же строчкой после переключения стиля вы можете попытаться выяснить размер/что-то еще счисляемое, браузеру попросту нет вариантов делать иначе.


        Простой пример: jsfiddle. Если бы оно рассчитывалось только один раз отложено — в логе бы вывелось 7 одинаковых надписей. Однако есть вероятность, что современные браузеры достаточно умны, вызывают пересчет только если кто-то обращается к этим значениям, иначе по окончании выполнения скрипта, однако не стоит на это рассчитывать.


        1. andreymal
          03.11.2017 22:58

          Покуда сразу следующей же строчкой после переключения стиля вы можете попытаться выяснить размер/что-то еще счисляемое, браузеру попросту нет вариантов делать иначе.

          Это и есть необходимость. А если убрать offsetHeight?


          есть вероятность
          не стоит на это рассчитывать

          Ну то есть вы говорите о том, чего толком не знаете, понятно)


          1. kahi4
            03.11.2017 23:21

            Окей, я проверил. Есть набор свойств, таких как offsetHeight, которые требуют пересчета layout. Вот например список таких свойств. Только они не стандартизированы и получены для конкретного браузера, конкретной версии, неизвестно что там у себя внутри думает IE/Edge, не известно как это может измениться в будущем.


            Помимо этого, нужно убедиться, что никто не навесит dom-observable и чего-то подобного (onscroll не вызывается, проверил, впрочем не уверен что справедливо для всех условий).


            Хотите завязываться на неопределенное поведение? Пожалуйста. На моей практике когда речь идет о включении-выключении элементов до 1000 за раз — никаких трудностей не возникает, а когда речь идет об 50 000+ элементов — трудности возникают и приходится делать дополнительные шаги. Впрочем, задачи тоже разные бывают.


            P.S. Вот почитать подробнее о том, что вызывает пересчет layout при изменении каких свойст было бы по-интереснее, чем перески "css для чайников", конечно.


    1. AlexPershin
      04.11.2017 11:57

      Вы так пишете как будто бы Хабр место для элиты, вроде вас, и новичков тут нет.

      И влетел в бан в гугле и яндексе за это. Для доступности у html хватает аттрибутов, их и стоит использовать, а не заниматься дичью вроде top: -9999px (еще один способ, как и сделать текст такого же цвета как и фон, много их было).

      Гугл точно за это не банит. Тем более, что доступность уже становится обязательным требованием. В США всё к этому идёт и для коммерческих сайтов, а раз так, то очень скоро и до нас докатится, а почувствуют это профессионалы-аутсорсеры в первую очередь. Думаю, и для них такие туториалы начального уровня будут полезны (быстрой систематизацией).


      1. kahi4
        04.11.2017 17:24
        +1

        Гугл точно за это не банит.

        Оф. дока. СЕО штука такая, сложная, сложно говорить что-то наверняка с пруфами (вообще это чуть ли не уникальный случай, что удалось найти пруфы в чем-то официальном, а не только сакральные знания на каком-нибудь блоке сеошников), однако я встречал людей, которых банили за это. Это связано с черным (black hat) СЕО времер до 2012 года, когда это использовали для искуственного повышения в выдаче. С тех пор если visible: hidden и display: none в целом безобидные, то трюки с clipRect расцениваются как попытка обмануть поисковики.


        Повторюсь, для HTML существует целые разделы спецификации, нацеленные на решение доступности сайта. Один из них — wai-aria и использовать нужно их (по многим причинам).


        Вы так пишете как будто бы Хабр место для элиты, вроде вас, и новичков тут нет.

        Тогда вперед, давайте сюда еще по главам опубликуем весь учебник математики за 5 класс. И википедию всю переписать сюда. Грань, когда статья уместна на хабре, а когда нет — очень тонкая, но основы CSS — на мой взгляд уж точно ее переходят. Хабр для уникального опыта, уникальных знаний, чего-то, что сложно или даже порой невозможно найти в других источниках. А с visiblity и hidden новички в html/css могут познакомиться в миллионах других источников, предназначенных для этого. Впрочем, рейтинг статьи показывает, что я, похоже, не прав.


        Хм, может тоже пойти что-то такое публиковать? Чур я забил учебник Атанасяна по геометрии за 7-9 класс! Никогда не думал, что я тоже буду сидеть и говорить "хабр уже не торт".


        1. AlexPershin
          06.11.2017 11:50

          Отличная ссылка на документацию, в которой говорится прямо противоположное вашим выводам:

          When evaluating your site to see if it includes hidden text or links, look for anything that's not easily viewable by visitors of your site. Are any text or links there solely for search engines rather than visitors?

          However, not all hidden text is considered deceptive. For example, if your site includes technologies that search engines have difficulty accessing, like JavaScript, images, or Flash files, using descriptive text for these items can improve the accessibility of your site. Remember that many human visitors using screen readers, mobile browsers, browsers without plug-ins, and slow connections will not be able to view that content either and will benefit from the descriptive text as well. You can test your site’s accessibility by turning off JavaScript, Flash, and images in your browser, or by using a text-only browser such as Lynx. Some tips on making your site accessible include:


          Гугл сам говорит, что текст, спрятанный от пользователей, и предназначенный для поисковиков — это плохо. Но текст, предназначенный для пользователей с читалками (то есть в целях доступности) — это ок.

          Если лень вникать в английский текст, то вот прямой ответ на форуме поддержки вебмастеров productforums.google.com/forum/#!msg/webmasters/YJcZUhtMIE4/XkOEzVakBAAJ

          Такие статьи про азы на Хабре нужны не только для новичков, но и для опытных, которые в азах не разобрались в своё время, или разобрались в азах, но они поменялись.

          А что касается aria-атрибутов, то можно и без них обойтись в большинстве простых случаев, если использовать теги по назначению.


  1. ElianL
    04.11.2017 17:24

    И чем это отличается от opacity: 0? Opacity просто делает элемент прозрачным (или полупрозрачным), а visibility: hidden ещё не даёт с ним взаимодействовать: навести, кликнуть, сфокусировать.


    Так же что стоит заметить, что opacity создает новый контекст для расчета z-index. Плюс opactity можно анимировать


  1. switzergirl
    06.11.2017 16:14

    Использовал и то, и другое при верстке. Но со временем стал стараться обходить стороной такие штуки)