Как разделить CSS и Javascript
vladimir вс, 02/17/2013 - 17:16 Javascript
jQuery, Prototype, Node.js, Backbone.js, Mustache и тысячи других javascript-библиотек появились благодаря невероятной популярности языка javascript. Он стал настолько популярным, что мы его используем даже в тех ситуациях, где другое решение в долгосрочной перспективе стало бы лучшим вариантом.
Даже если мы храним CSS, Javascript и HTML в разных файлах, концепция постепенного улучшения (progressive enhancement) становится всё равно завязанной на каждым jQuery плагине, который мы используем и каждой новой технике, появившейся в сети. Происходит так потому, что Javascript настолько мощен, что позволяет создавать связи, как с документами HTML (создавать структуру документа), так и с CSS (вносить разную информацию). В этой статье я не буду выбирать какую библиотеку лучше использовать, bootstrap или boilerplate, я хочу лишь дать объективную оценку происходящей ситуации на сегодня и как её улучшить.
Храните CSS и Javascript отдельно
CSS можно подключить к HTML множеством различных способов с помощью селекторов. C помощью идентификаторов, классов и атрибутов вы можете получить доступ к стилю любого элемента. Также это можно сделать с помощью Javascript, такой способ отличается лишь синтаксисом и правилами. Так как через Javascript легко получить доступ, как к HTML так и к CSS, принцип progressive enhancement служит напоминанием построения правильной модели. При разработке проекта важно не смешивать код HTML и CSS с кодом Javascript.
По мере создания приложений на Javascript c интерактивными элементами, становится всё сложнее не объединять HTML и Javscript, а также хранить отдельно CSS. Конечно, в некоторых случаях стилевые инъекции могут вводиться в Javascript, как, например, ситуация с drag and drop интерфейсом, где информация о положении курсора должна все время обновляться.
Правильнее всю необходимую информацию, содержащую CSS, вынести в общую папку со стилями и присвоить нужные классы, чтобы в дальнейшем их можно было повторно использовать. Этот подход гораздо более гибкий, чем постоянно вводить CSS в Javascript и он аналогичен модели разделения кода HTML и CSS. Мы всегда следуем такой модели, при работе с HTML и CSS кодом, но как только на поле появляется Javascript, по какой-то причине, модель начинает разваливаться. Это стоит иметь ввиду и следить за появлением таких ситуаций.
Многие front-end разработчики гордятся тем, что у них чистый HTML код. С таким кодом легко и приятно работать. Конечно хорошо иметь чистый, семантичный HTML, но что может быть хорошего в том, если HTML будет генерироваться со встроенными стилями и не семантичной разметкой? Под сгенерированным HTML я имею ввиду код, который получается после завершения работы всех участков кода Javascript. Если первым шагом к построению правильной модели progressive enhancement является не использование стилевых атрибутов в HTML, то вторым шагом является написание Javascript кода, который не будет вводить атрибут стиля в HTML.
Очистите ваш HTML код
Я думаю все согласятся с тем, что слепо использовать технологии это плохая идея. Как раз в случае с jQuery мы находимся в той точке, где начинается бездумное использование различных функций и кода, не вполне понимая, что происходит под капотом. Например, рассмотрим скрытие элемента по тому принципу, как работает метод hide( ) в jQuery. Основываясь на принципах прогрессивного улучшения, такой код является некорректным:
Такой код неправильный, так как считывающие устройства не будут отображать такой элемент, а также в этом случае элемент содержит в себе презентационную информацию, которая должна храниться в CSS. При использовании метода jQuery hide( ) возникнет именно такая ситуация, будет установлен атрибут display: none. В реализации такой способ очень прост, но для доступности он некорректен. Он также нарушает принципы прогрессивного улучшения, так как вводится стилевой атрибут. Метод hide( ) используется часто в построениях табов (tabs) для скрытия контента. Результатом является отсутствие информации в считывающих устройствах. Решить все эти проблемы можно перемещением стиля в CSS и ссылаться на него через класс:
.hide { display: none; }
$('.content-area').addClass('hide');
Скрыть контент без использования jQuery можно и таким способом:
.hide { position: absolute; top: -9999px; left: -9999px; } .remove { display: none; }
Хотя приведённый выше код осуществляет одинаковый результат – контент удаляется, с точки зрения доступности эти записи работают совершенно по-разному. Код содержится в CSS, всё чисто и правильно. Использование таких вспомогательных классов поможет не только уменьшить Javascript код, но и имеет место в применении в объектно-ориентированном CSS (OOCSS). Этот подход обеспечивает многократное использование классов в тех случаях, где это необходимо, а также создаёт более целостный подход к front-end разработке. Лично я вижу больше пользы в таком подходе, хотя некоторые разработчики с этим не согласны.
web и front-end
С помощью вышеописанного метода мы создали связь между CSS и Javascript. Создание баланса и чистоты в front-end коде очень важно и контролировать этот участок очень тяжело в отличии от back-end участка. Если браузер пользователя старый и медленный, вы не можете сами его обновить (если конечно пользователь не использует Chrome, который сам обновляется), все что вы можете сделать это подготовиться к худшему и лучшему сценарию.
Некоторые утверждали, что стиль использования CSS классов через Javascript не очень удобен для команды разработчиков, так как CSS, как правило, уже готов к использованию к тому времени, когда Javascript еще грузится. В результате чего могут возникнуть ошибки с использованием тех или иных классов. Решить все эти проблемы просто! Достаточно заранее договориться об использовании нужных классов в Javascript.
Использование CSS с Javascript Fallbacks
Использование CSS объектов для Javascript может выйти далеко за рамки простого скрытия и отображения контента, но и в эффектах transitions, animations и transforms, которые часто делаются с помощью Javascript анимаций. Имея это ввиду, давайте рассмотрим общую модель взаимодействия эффекта fading out для контейнера DIV при событии click( ). При этом мы будем иметь ввиду fallbacks, то есть откаты для старых браузеров, которые не поддерживают эффект transition, который мы будем использовать.
Для этого примера будем использовать jQuery и Modernizr:
И CSS:
#cube { height: 200px; width: 200px; background: orange; -webkit-transition: opacity linear .5s; -moz-transition: opacity linear .5s; -o-transition: opacity linear .5s; transition: opacity linear .5s; } .fade-out { opacity: 0; }
Перед тем, как добавить Javascript, давайте рассмотрим то, что у нас должно произойти:
- Используем Modernizr для проверки поддержки CSS Transition
- Если поддержка есть: настраиваем событие для кнопки добавлением класса fade-out к #cube. Добавить еще один обработчик события, чтобы узнать, когда переход завершён и удалить #cube из DOM
- Если поддержки нет: настроить jQuery метод animate( ) для #cube. Выполнить callback для удаления #cube из DOM
В ходе этого процесса введем событие transitionend, которое будет выполняться в конце перехода CSS transition. Также введём событие animationend, которое будет выполняться в конце перехода animation.
Определяем переменные в javascript:
(function () { // set up your variables var elem = document.getElementById('cube'), button = document.getElementById('do-it'), transitionTimingFunction = 'linear', transitionDuration = 500, transitionend; // настроим переменные с учетом вендорных префиксов if ($.browser.webkit) { transitionend = 'webkitTransitionEnd'; // safari & chrome } else if ($.browser.mozilla) { transitionend = 'transitionend'; // firefox } else if ($.browser.opera) { transitionend = 'oTransitionEnd'; // opera } else { transitionend = 'transitionend'; // дефолтное значение } //... остальной код будет здесь })(); // функция вызова на месте заканчивается тут
Вы могли заметить, что наше событие transitionend зависит от вендорного префикса, для этого мы осуществили проверку браузера.
На следующем этапе мы будем использовать Modernizr для проверки поддержки свойства transition. А также добавим слушатели событий для каждого конкретного случая (все это будет обёрнуто функцией приведенной выше).
// определяем css transition поддержку с Modernizr if(Modernizr.csstransitions) { // добавляем классы при событии click $(button).on('click', function () { $(elem).addClass('fade-out'); }); // имитируем вызов callback функции с event listener elem.addEventListener(transitionend, function () { theCallbackFunction(elem); }, false); } else { // настраиваем normal click/ animate listener для не поддерживающих браузеров $(button).on('click', function () { $(elem).animate({ 'opacity' : '0' }, transitionDuration, transitionTimingFunction, function () { theCallbackFunction(elem); }); }); // конец события click } // конец проверки
Наконец, нам надо определить общие функции между двумя действиями, которые выполняются после перехода или анимации. Для этой цели мы назовем эту функцию theCallbackFunction( ) (хотя технически это не функция обратного вызова). Она будет удалять элемент из DOM и создавать сообщение в консоли, давая понять что отработала.
// определяем callback function, которая сработает после transition/animation function theCallbackFunction (elem) { 'use strict'; // удаляем элемент из DOM $(elem).remove(); // выводим сообщение в консоли о завершении работы функции console.log('the transition is complete'); }
В браузерах, включая IE7, это должно работать одинаково (включая мобильные браузеры). Этот пример полностью выводит CSS из Javascript , в чём и была наша основная цель.
Источник
- Войдите, чтобы оставлять комментарии