Скрытие и открытие элементов на странице Javascript'ом - вещь довольно обыденная, казалось бы. Но и тут есть пара маниакальных тонкостей, о которых мало кто вспоминает.

Хочу поделиться своим опытом реализации "доступных немигающих динамических скрытых блоков через раннее внедрение в CSS проверки на Javascript".

С этим самым скрытием есть такая проблема: если элементы на странице изначально скрыты (CSS'ом), то для браузера без Javascript'а этот контент становится недоступен. Тут же напрашиваются два варианта решения проблемы:

Но вот этот второй вариант содержит подвох, который заключается в этом слове "потом". На практике "потом" означает событие OnLoad, в котором все эти скрытия и производятся. И при достаточно немаленькой страничке и достаточно рваном коннекте становится заметен гадкий визуальный эффект: на страницу грузится тонна мусора, а потом в какой-то момент это скачком исчезает. Yikes!

Чтобы это обойти, в принципе можно вставлять вызов функции сворачивания в код страницы после каждого объекта, который надо свернуть. В итоге, при достаточно неединичном количестве таких блоков мы получаем кучу:

<div id="....">.....</div>
<script type="text/javascript">document.getElementById('....').style.display='None';</script>

... раскиданных по всему коду. Yikes!

Так вот, если вам это не нравится так же, как и мне, вот вариант, к которому я в итоге пришел.

Обычно я стараюсь выносить Javascript во внешние файлы: так с ним удобней работать. И обычно в процессе работы над проектом так или иначе появляется .js-файлик, в котором лежат общие для всех файлов функции. И обычно он подключается в самом начале файла, но после открывающего <body> (позже объясню, почему так). Такая же ситуация и с CSS-файлами: обычно есть главный общий файл, который присутствует на всех страницах.

В главный js-файлик я вставляю такую простую строчку:

document.body.className+=' js';

Таким образом, к body в самом начале загрузки страницы добавляется класс 'js'. И его теперь можно использовать в CSS'е, где он работает как признак "Javascript включен", потому что если нет Javascript'а, то он и не назначится.

Теперь должно быть понятно, почему скрипт вставляется после тега, а не на пару строчек раньше: парой строчек раньше еще никакого body у документа не существует, и вы получите ошибку.

Дальше для всех элементов, которые хочется иметь скрытыми, дописывается class="hidden". Если там класс уже есть, то hidden можно дописать через пробел: классов может быть сколько угодно. А в главный CSS пишется простое правило скрытия элементов:

.js .hidden {
  Display:None;
}

Это правило сработает для любого элемента с классом hidden, находящегося внутри элемента с классом js. Как раз наша ситуация! А поскольку CSS соврменные браузеры применяют к элементам как только они считываются, то это скрытие будет работать мгновенно, без всяких перемигиваний, так как класс js для body мы проставили в самом начале загрузки страницы, а hidden стоит прямо на элементах.

Впоследствие эти элементы вы можете скрывать-открывать любыми методами, которые вам нравятся.

Теперь осталось объяснить невообразимое название, которым я в начале статьи "наградил" этот подход:

доступные
без javascript'а все остается нескрытым и доступным
немигающие
отсутствует эффект задержки и последующего мгновенного скрытия, какой бывает при использовании OnLoad
динамические скрытые блоки
о них, собственно, и речь
раннее внедрение в CSS проверки на Javascript
механизм прописывания для body CSS'ного класса Javascript'ом специально для определения факта его работы

Надеюсь, окажется полезным!

Комментарии: 14

  1. Адищев Евгений

    Здорово!
    Действительно очень изящно. Уже прикрутил на своём сайте.

  2. Александр Шугард

    Любопытный подход. Спасибо. Возьму на заметку.

  3. [...] Изящное динамическое скрытие элементов с помощью CSS. Собственно, это стоит почитать. [...]

  4. Денис Брюхов

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

  5. Иван Сагалаев

    Как-то не подумал, что он понадобится :-).

    Но вот, пожалуйста: http://softwaremaniacs.org/blog/wp-content/js-hidden/

  6. Nab

    Изящно, и красиво, а еще можно было бы чтоб не зависеть от места вставки, сделать функцией, на определение наличия body с небольшой задержкой, ну и потом уже добавлять ему js...

  7. consolamentor.livejournal.com

    А я как дурак хотел сделать именно через OnLoad. Хорошо, что гугл вывел на вашу статью!

    Спасибо, это решение намного лучше!

  8. Муркт

    Спасибо предыдущему комментатору за комментарий, я увидел его в РСС, и прочёл про этот замечательный метод :)

  9. Иван Сагалаев

    Работают, значит, комментарии :-). Хорошо :-)

  10. irium

    Действительно, очень изящное и красивое решение!

    Сразу видно, что его придумал человек с ПРАВИЛЬНЫМ программистским мышлением, а не верстальщик-гуманитарий :)

  11. Дмитрий

    Вот только возникла проблема. Если скрыта таким образом строка внутри table([tr id="back"][td]Тест[/td][/tr]), то
    document.getElementById("back").style.display="" работать ну никак не хочет. А если прописать style="display:none;" насильно внутри tr, то все работает нормально.

    Что это может быть?

  12. Иван Сагалаев

    Сложно сказать... По теории, должно работать и для tr тоже. Если в каком-то браузере не работает, то скорее всего это баг, и надо искать обходные пути.

  13. lama

    А как сделать чтобы при повторном нажатии на кнопку снова скрывать текст

  14. Infis

    Нужно кнопке присвоить какой-нибудь id. Тогда код кнопки будет выглядеть примерно так:

Добавить комментарий