Стили и классы - itgirlschool/wiki GitHub Wiki
Как правило, существует два способа задания стилей для элемента:
Создать класс в CSS и использовать его:
<div class="...">Писать стили непосредственно в атрибуте style:
<div style="...">JavaScript может менять и классы, и свойство style.
Классы – всегда предпочтительный вариант по сравнению со style. Мы должны манипулировать свойством style только в том случае, если классы «не могут справиться». Например, использование style является приемлемым, если мы вычисляем координаты элемента динамически и хотим установить их из JavaScript:
let top = /* сложные расчёты */;
let left = /* сложные расчёты */;
elem.style.left = left; // например, '123px', значение вычисляется во время работы скрипта
elem.style.top = top; // например, '456px'В других случаях, например, чтобы сделать текст красным, добавить значок фона – описываем это в CSS и добавляем класс (JavaScript может это сделать). Это более гибкое и лёгкое в поддержке решение.
Изменение класса является одним из наиболее часто используемых действий в скриптах. Когда-то давно в JavaScript существовало ограничение: зарезервированное слово типа "class" не могло быть свойством объекта. Это ограничение сейчас отсутствует, но в то время было невозможно иметь свойство elem.class. Поэтому для классов было введено схожее свойство "className": elem.className соответствует атрибуту "class".
Например:
<body class="main page">
<script>
alert(document.body.className); // main page
</script>
</body>Если мы присваиваем что-то elem.className, то это заменяет всю строку с классами. Иногда это то, что нам нужно, но часто мы хотим добавить/удалить один класс. Для этого есть другое свойство: elem.classList. elem.classList – это специальный объект с методами для добавления/удаления одного класса.
Например:
<body class="main page">
<script>
// добавление класса
document.body.classList.add('article');
alert(document.body.className); // main page article
</script>
</body>Так что мы можем работать как со строкой полного класса, используя className, так и с отдельными классами, используя classList. Выбираем тот вариант, который нам удобнее.
Методы classList:
elem.classList.add("class"); // добавить класс.
elem.classList.remove("class"); // удалить класс.
elem.classList.toggle("class"); // добавить класс, если его нет, иначе удалить.
elem.classList.contains("class"); // проверка наличия класса, возвращает true/false.Кроме того, classList является перебираемым, поэтому можно перечислить все классы при помощи for..of:
<body class="main page">
<script>
for (let name of document.body.classList) {
alert(name); // main, затем page
}
</script>
</body>Свойство elem.style – это объект, который соответствует тому, что написано в атрибуте "style". Установка стиля elem.style.width="100px" работает так же, как наличие в атрибуте style строки width:100px. Для свойства из нескольких слов используется camelCase:
// background-color => elem.style.backgroundColor
// z-index => elem.style.zIndex
// border-left-width => elem.style.borderLeftWidthНапример:
document.body.style.backgroundColor = prompt('background color?', 'green');Свойства с префиксом
Стили с браузерным префиксом, например, -moz-border-radius, -webkit-border-radius преобразуются по тому же принципу: дефис означает заглавную букву.
Например:
button.style.MozBorderRadius = '5px';
button.style.WebkitBorderRadius = '5px';Иногда нам нужно добавить свойство стиля, а потом, позже, убрать его. Например, чтобы скрыть элемент, мы можем задать
elem.style.display = "none".Затем мы можем удалить свойство style.display, чтобы вернуться к первоначальному состоянию. Вместо delete elem.style.display мы должны присвоить ему пустую строку:
// если мы запустим этот код, <body> "мигнёт"
document.body.style.display = "none"; // скрыть
setTimeout(() => document.body.style.display = "", 1000); // возврат к нормальному состояниюЕсли мы установим в style.display пустую строку, то браузер применит CSS-классы и встроенные стили, как если бы такого свойства style.display вообще не было.
Обычно мы используем style.* для присвоения индивидуальных свойств стиля. Нельзя установить список стилей как, например, div.style="color: red; width: 100px", потому что div.style – это объект, и он доступен только для чтения. Для задания нескольких стилей в одной строке используется специальное свойство style.cssText:
<div id="div">Button</div>
<script>
// можем даже устанавливать специальные флаги для стилей, например, "important"
div.style.cssText=`color: red !important;
background-color: yellow;
width: 100px;
text-align: center;
`;
alert(div.style.cssText);
</script>Это свойство редко используется, потому что такое присваивание удаляет все существующие стили: оно не добавляет, а заменяет их. Можно ненароком удалить что-то нужное. Но его можно использовать, к примеру, для новых элементов, когда мы точно знаем, что не удалим существующий стиль.
То же самое можно сделать установкой атрибута:
div.setAttribute('style', 'color: red; width: 100px;')Итак, изменить стиль очень просто. Но как его прочитать? Например, мы хотим знать размер, отступы, цвет элемента. Как это сделать? Свойство style оперирует только значением атрибута "style", без учёта CSS-каскада. Поэтому, используя elem.style, мы не можем прочитать ничего, что приходит из классов CSS. Например, здесь style не может видеть отступы:
<head>
<style> body { color: red; margin: 5px } </style>
</head>
<body>
Красный текст
<script>
alert(document.body.style.color); // пусто
alert(document.body.style.marginTop); // пусто
</script>
</body>Но что, если нам нужно, скажем, увеличить отступ на 20px? Для начала нужно его текущее значение получить. Для этого есть метод: getComputedStyle.
Синтаксис:
getComputedStyle(element, [pseudo])element
Элемент, значения для которого нужно получить
pseudo
Указывается, если нужен стиль псевдоэлемента, например ::before. Пустая строка или отсутствие аргумента означают сам элемент. Результат вызова – объект со стилями, похожий на elem.style, но с учётом всех CSS-классов.
Например:
<head>
<style> body { color: red; margin: 5px } </style>
</head>
<body>
<script>
let computedStyle = getComputedStyle(document.body);
// сейчас мы можем прочитать отступ и цвет
alert( computedStyle.marginTop ); // 5px
alert( computedStyle.color ); // rgb(255, 0, 0)
</script>
</body>getComputedStyle требует полное свойство!
Для правильного получения значения нужно указать точное свойство. Например: paddingLeft, marginTop, borderTopWidth. При обращении к сокращённому: padding, margin, border – правильный результат не гарантируется. Например, если есть свойства paddingLeft/paddingTop, то что мы получим вызывая
getComputedStyle(elem).padding; // ?Ничего, или, может быть, «сгенерированное» значение из известных внутренних отступов? Стандарта для этого нет. Есть и другие несоответствия. Например, некоторые браузеры (Chrome) отображают 10px в документе ниже, а некоторые (Firefox) – нет:
<style>
body {
margin: 10px;
}
</style>
<script>
let style = getComputedStyle(document.body);
alert(style.margin); // пустая строка в Firefox
</script>