В предыдущей главе мы рассмотрели, как можно модифицировать содержимое DOM, используя JavaScript. Однако HTML-элементы также отличаются и внешностью, а именно стилем. Когда дело доходит до стилизации содержимого, наиболее распространены создание правила стиля и нацеливание его селектора на элемент(ы). Выглядит правило стиля так:
batman {
width: 100px;
height: 100px;
background-color: #333;
}
Сам же элемент, на который будет действовать это правило, может выглядеть так:
На любой веб-странице мы повсюду встречаем от нескольких до многих правил стиля, красиво перемежающиеся друг с другом, стилизуя все, что мы видим. Тем не менее это не единственный подход, который можно использовать для стилизации содержимого с помощью CSS. Это бы не был HTML, если бы в нем ни присутствовало несколько способов решения одной задачи.
Без учета встроенных стилей другой подход для CSS-стилизации элементов заключается в использовании JavaScript. Мы можем использовать JS, чтобы устанавливать стиль элемента напрямую, а также чтобы добавлять или удалять значения класса элементов, которые будут определять применение тех или иных правил стиля.
В этой главе мы изучим оба этих подхода.
Поехали!
Зачем устанавливать стили с помощью JavaScript?
Для начала будет нелишним пояснить, откуда вообще возникает желание использовать JavaScript для воздействия на стиль элемента. В обыденных случаях, когда мы используем правила стиля или встроенные стили для определения внешнего вида элемента, стилизация подключается после загрузки страницы. Это прекрасно, и именно так нам в большинстве случаев и нужно.
Однако существует множество ситуаций, когда содержимое становится более интерактивным, и нам уже нужно, чтобы стили загружались динамически на основе пользовательского ввода, фонового выполнения кода и по другим причинам. В подобных сценариях CSS-модель, использующая правила стиля или встроенные стили, уже не сгодится. Несмотря на то что псевдоселекторы вроде hover предоставляют некоторую поддержку, мы по-прежнему ограничены в возможностях.
В данном случае полноценным решением будет использование JavaScript. Он позволит нам не только стилизовать элемент, с которым мы взаимодействуем, но и, что еще важнее, стилизовать элементы по всей странице. Такая свобода действий имеет огромный потенциал и выходит далеко за рамки ограниченных возможностей CSS, позволяющих стилизовать содержимое только внутри себя или в непосредственной близости.
Два подхода стилизации
Из начала главы мы знаем, что есть два способа изменять стиль элемента с помощью JavaScript. Первый — это установка свойства CSS непосредственно в элементе. Второй — добавление или удаление значений класса из элемента, что может приводить к применению или игнорированию определенных правил стиля. Рассмотрим оба случая подробнее.
Установка стиля напрямую
Каждый HTML-элемент, к которому вы обращаетесь через JavaScript, имеет объект style. Этот объект позволяет определять свойство CSS и устанавливать его значение. Например, вот как будет выглядеть установка фонового цвета HTML-элемента со значением id — superman:
let myElement = document.querySelector("#superman");
myElement.style.backgroundColor = "#D93600";
Чтобы воздействовать на несколько элементов, вы можете сделать следующее:
let myElements = document.querySelectorAll(".bar");
for (let i = 0; i < myElements.length; i++) {
myElements[i].style.opacity = 0;
}
Коротко говоря, для прямой стилизации элементов с помощью JavaScript первым шагом будет обращение к элементу. При этом будет очень удобно использовать знакомый нам метод querySelector. Вторым шагом будет нахождение интересующего вас свойства CSS и указание для него значения. Помните, что многие значения в CSS являются строками. Также помните, что многим значениям для распознания требуются единицы измерения вроде px, em или аналогичные.
И последнее. Некоторые свойства CSS требуют, чтобы более сложные значения предоставлялись в виде текста, сопровождаемого значением, которое нужно вам самим. Одно из наиболее популярных свойств в этом списке — это свойство преобразования. В качестве подхода для установки сложного значения можно использовать старую добрую конкатенацию:
myElement.style.transform = "translate3d(" + xPos +", " + yPos + "px, 0)";
Но такой вариант быстро надоест, поскольку отслеживание расстановки кавычек и прочие действия весьма утомительны и могут вызвать множество ошибок. Другое решение уже не так сложно и подразумевает использование синтаксиса шаблонного литерала:
myElement.style.transform = `translate3d(${xPos}px, ${yPos}px, 0)`;
Обратите внимание, что этот подход позволяет вам по-прежнему применять пользовательские значения, избегая при этом всей сложности конкатенации строк.
Вынужденное изменение имен некоторых свойств CSS
JavaScript очень требователен к содержанию допустимого имени свойства. Большинство имен в CSS будут одобрены JS, поэтому вы можете использовать их в изначальном виде. Тем не менее кое-что стоит помнить.
Чтобы указать в JavaScript свойство CSS, содержащее тире, просто удалите это тире. Например, background-color станет backgroundColor, а border-radius будет borderRadius и т. д.
Кроме того, некоторые слова в JavaScript зарезервированы и не могут быть использованы как есть. Один из примеров свойств CSS, подпадающих под эту категорию, является float. В CSS это свойство макета. В JavaScript же оно обозначает нечто иное. Чтобы использовать свойство, чье имя зарезервировано, используйте для него префикс css, то есть напишите не float, а cssfloat.
Добавление и удаление классов с помощью JavaScript
Второй подход подразумевает добавление и удаление значений классов, которые, в свою очередь, определяют, какие правила стиля будут применены. Предположим, у нас есть следующее правило стиля:
disableMenu
{ display: none;
}
В HTML у нас есть меню, чей id — dropDown:
- One
- Two
- Three
- Four
- Five
- Six
Теперь если мы захотим применить стиль. disableMenu к этому элементу, то нам всего лишь понадобится добавить disableMenu в качестве значения class к элементу dropDown:
- One
- Two
- Three
- Four
- Five
- Six
Одним из вариантов сделать это будет установление свойства className элемента. Этот подход мы уже видели ранее. Проблема же с className в том, что мы становимся ответственны за поддержание текущего списка применяемых значений классов. Помимо этого, сам этот список возвращается в виде строки. Если у нас есть несколько значений классов, которые мы хотим добавить, удалить или просто включать и выключать, то понадобится проделать множество трюков со строками, что спровоцирует появление ошибок.
Эти неудобства может сгладить гораздо более приятный API, который делает добавление и удаление значений классов из элемента до смешного легким. Этот новый API известен как classList. Он предоставляет набор методов, которые упрощают работу со значениями классов:
• add;
• remove;
• toggle;
• contains.
Назначение этих методов угадывается из их имен, но все же давайте их изучим внимательнее.
Добавление значений классов
Чтобы добавить значение класса элементу, получите ссылку на этот элемент и вызовите для него метод add через classList:
let divElement = document.querySelector("#myDiv");
divElement.classList.add("bar");
divElement.classList.add("foo");
divElement.classList.add("zorb");
divElement.classList.add("baz");
console.log(divElement.classList);
После выполнения этого кода элемент div будет иметь следующие значения класса: bar, foo, zorb, baz. API classList берет на себя добавление пробелов между значениями классов. Если же мы укажем недопустимое значение класса, API classList будет ругаться и добавлять его не станет. Если мы прикажем методу add добавить класс, уже существующий в элементе, то код по-прежнему будет выполняться, но повторяющееся значение класса добавлено не будет.
Удаление значений классов
Для удаления значения класса мы можем вызвать метод remove также через classList:
let divElement = document.querySelector("#myDiv");
divElement.classList.remove("foo");
console.log(divElement.classList);
После выполнения этого кода значение класса foo будет удалено и останутся только bar, baz и zorb. Несложно, правда?
Переключение значений класса
Для многих сценариев стилизации применяется стандартный рабочий процесс. Во-первых, мы проверяем, существует ли значение класса в элементе. Если да, мы удаляем его из элемента. Если же нет, то мы, наоборот, его добавляем. Чтобы упростить этот тривиальный шаблон переключения, API classList предоставляет метод toggle:
let divElement = document.querySelector("#myDiv");
divElement.classList.toggle("foo"); // удаляет foo
divElement.classList.toggle("foo"); // добавляет foo
divElement.classList.toggle("foo"); // удаляет foo
console.log(divElement.classList);
Метод toggle при каждом вызове добавляет указанное значение класса в элемент или удаляет его. В нашем случае класс foo при первом вызове метода toggle удаляется. Во второй раз класс foo, наоборот, добавляется. В третий раз снова удаляется. Думаю, суть вы уловили.
Проверка наличия значения класса
Последним рассмотрим метод contains:
let divElement = document.querySelector("#myDiv");
if (divElement.classList.contains("bar") == true) {
// делает что-нибудь
}
Этот метод проверяет, существует ли указанное значение класса в элементе. Если да, то возвращается true, если нет — false.
Углубление
Как вы видите, API classList предоставляет почти все, что нужно для удобного добавления, удаления или проверки значений классов в элементе. Ключевое слово «почти». О том немногом, что этот API все же не предлагает по умолчанию, можно почитать в моей статьеhttp://bit.ly/kClassList, рассказывающей о многих других возможностях classList.
КОРОТКО О ГЛАВНОМ
Итак, теперь у вас есть два отличных основанных на JavaScript подхода для стилизации элементов. Если есть возможность модифицировать CSS, рекомендую стилизовать элементы посредством добавления и удаления классов. Причина связана с тем, что такой подход существенно упрощает обслуживание кода. Гораздо легче добавлять или удалять свойства стилей из правила стиля в CSS, чем добавлять и удалять строки кода JavaScript.
Остались вопросы? Дружелюбные форумчане ответят вам. Обращайтесь на https://forum.kirupa.com!