Скрытие и открытие элементов на странице Javascript'ом - вещь довольно обыденная, казалось бы. Но и тут есть пара маниакальных тонкостей, о которых мало кто вспоминает.
Хочу поделиться своим опытом реализации "доступных немигающих динамических скрытых блоков через раннее внедрение в CSS проверки на Javascript".
С этим самым скрытием есть такая проблема: если элементы на странице изначально скрыты (CSS'ом), то для браузера без Javascript'а этот контент становится недоступен. Тут же напрашиваются два варианта решения проблемы:
-
"Ну и кто сейчас работает без JS?" В общем-то, точка зрения понятна, но во-первых, есть такие юзеры, а во-вторых, я обычно люблю делать вещи хорошо, если есть возможность. Поэтому этот вариант отпадает.
-
Оставить элементы по умолчанию открытыми, а потом уже самим Javascript'ом скрыть. Таким образом, у людей без JS все будет видно, а у остальных - все будет работать, как задумано.
Но вот этот второй вариант содержит подвох, который заключается в этом слове "потом". На практике "потом" означает событие 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
Здорово!
Действительно очень изящно. Уже прикрутил на своём сайте.
Любопытный подход. Спасибо. Возьму на заметку.
Иван, был бы очень признателен, думаю не я один, если бы вы выложили небольшой пример для иллюстрации вашего подхода. Спасибо.
Как-то не подумал, что он понадобится :-).
Но вот, пожалуйста: http://softwaremaniacs.org/blog/wp-content/js-hidden/
Изящно, и красиво, а еще можно было бы чтоб не зависеть от места вставки, сделать функцией, на определение наличия body с небольшой задержкой, ну и потом уже добавлять ему js...
А я как дурак хотел сделать именно через OnLoad. Хорошо, что гугл вывел на вашу статью!
Спасибо, это решение намного лучше!
Спасибо предыдущему комментатору за комментарий, я увидел его в РСС, и прочёл про этот замечательный метод :)
Работают, значит, комментарии :-). Хорошо :-)
Действительно, очень изящное и красивое решение!
Сразу видно, что его придумал человек с ПРАВИЛЬНЫМ программистским мышлением, а не верстальщик-гуманитарий :)
Вот только возникла проблема. Если скрыта таким образом строка внутри table([tr id="back"][td]Тест[/td][/tr]), то
document.getElementById("back").style.display="" работать ну никак не хочет. А если прописать style="display:none;" насильно внутри tr, то все работает нормально.
Что это может быть?
Сложно сказать... По теории, должно работать и для tr тоже. Если в каком-то браузере не работает, то скорее всего это баг, и надо искать обходные пути.
А как сделать чтобы при повторном нажатии на кнопку снова скрывать текст
Нужно кнопке присвоить какой-нибудь id. Тогда код кнопки будет выглядеть примерно так: