Изменение стилей и классов: jQuery .css() и нативный JS
Содержание
О проверке кода. Примеры не запускались в браузере — в отличие от материалов по Node.js, где приводится фактический вывод. Код дан по документации jQuery и MDN. Говорим прямо, а не ставим бейдж «проверено» без проверки.
Как менять стили
// jQuery
$('#box').css('color', 'red');
$('#box').css({ color: 'red', fontSize: '16px' });
// нативно
box.style.color = 'red';
Object.assign(box.style, { color: 'red', fontSize: '16px' });
| Задача | jQuery | Нативно |
|---|---|---|
| Задать стиль | $el.css('color', 'red') |
el.style.color = 'red' |
| Несколько разом | $el.css({...}) |
Object.assign(el.style, {...}) |
| Прочитать вычисленный | $el.css('color') |
getComputedStyle(el).color |
| Убрать инлайновый | $el.css('color', '') |
el.style.removeProperty('color') |
| CSS-переменная | $el.css('--x', '5px') |
el.style.setProperty('--x', '5px') |
Свойства с дефисом в JavaScript пишутся camelCase: font-size → fontSize, background-color → backgroundColor. Исключение — CSS-переменные: они всегда с дефисами и только через setProperty.
Ловушка первая: читаете не то, что писали
box.style.color = 'red';
$('#box').css('color'); // "rgb(255, 0, 0)"
getComputedStyle(box).color; // "rgb(255, 0, 0)"
Браузер отдаёт вычисленное значение в канонической форме. red, #f00, rgb(255,0,0) — для него одно и то же, и наружу пойдёт последнее.
То же с размерами: записали width: 50% — прочитаете width: 320px. Браузер посчитал.
Отсюда правило: сравнивать стили строками нельзя. Проверка if ($el.css('color') === 'red') не сработает никогда. Состояние держат в классах и проверяют classList.contains.
Ловушка вторая: style видит не всё
<style> #box { color: blue; } </style>
<div id="box"></div>
box.style.color; // "" — пусто!
getComputedStyle(box).color; // "rgb(0, 0, 255)" — вот оно
el.style — это только атрибут style в разметке. Правила из CSS-файла туда не попадают. Прочитать реальный стиль можно только через getComputedStyle.
jQuery это прячет: .css() на чтение сам вызывает getComputedStyle. Удобно — и именно поэтому многие не знают о различии, пока не переходят на нативный код.
Главное: не меняйте стили из JavaScript
Совет, которого не было в оригинале, а он важнее всего синтаксиса выше.
// ❌ оформление растеклось по коду
$('#box').css({ background: '#e34948', color: '#fff', padding: '12px' });
// ✅ состояние в JS, оформление в CSS
box.classList.add('box--error');
.box--error { background: #e34948; color: #fff; padding: 12px; }
Почему второй вариант лучше:
- Инлайновый стиль перебивает таблицу стилей. Написали из JS — переопределить это можно теперь только через
!important. Вы своими руками сломали каскад. - Оформление оказывается в двух местах. Дизайнер меняет цвет ошибки в CSS, а он не меняется, потому что настоящий цвет зашит в JS.
- Тема и адаптив ломаются. Тёмная тема и медиазапросы живут в CSS; инлайновый стиль их не видит и остаётся прежним.
JavaScript должен отвечать на вопрос «в каком состоянии элемент», а не «какого он цвета».
Оформление из JavaScript
.css() / el.style на каждый чих
- Инлайн перебивает таблицу стилей
- Переопределить только через
!important - Цвета в двух местах: в CSS и в коде
- Тёмная тема и медиазапросы не работают
- Дизайнер не может ничего поменять
Состояние из JavaScript
classList.toggle() + правила в CSS
- JS говорит что происходит, CSS — как это выглядит
- Каскад цел,
!importantне нужен - Тема и адаптив работают сами
- Правишь оформление, не трогая код
- Переходы и анимации бесплатно
Когда значение всё-таки динамическое
Прогресс-бар, позиция по курсору, высота от контента — значение известно только в рантайме. Прямая запись в style кажется единственным вариантом, но есть лучше:
// ❌ оформление в JS
bar.style.width = percent + '%';
bar.style.background = percent > 80 ? 'red' : 'green';
// ✅ JS отдаёт данные, CSS решает вид
bar.style.setProperty('--progress', percent + '%');
.bar::after {
width: var(--progress);
background: green;
transition: width .2s;
}
.bar[data-danger]::after { background: red; }
CSS-переменная — это способ передать в CSS число, не описывая в JS оформление. Код сообщает «прогресс 70%», а решение про цвет, ширину и анимацию остаётся в стилях, где ему и место.
Что было на этой странице в 2017 году
Первая версия вышла 18 августа 2017 года — самая большая статья цикла про jQuery. Она подробно разбирала .css(), .addClass(), .removeClass(), .toggleClass() и была для своего времени исчерпывающей.
Синтаксис не устарел ни на символ. Устарела рамка, в которой он подавался: .css() и классы описывались как два равноправных способа поменять внешний вид, а выбор — как дело удобства.
Сегодня понятно, что это не так. Инлайновый стиль ломает каскад и растаскивает оформление между CSS и JS — и это не вопрос вкуса, а причина, по которой в проекте потом появляется !important на каждом втором правиле.
Чего в 2017-м не было и быть не могло: CSS-переменных в этой роли. Они появились раньше, но привычка отдавать значение в CSS вместо записи стиля сложилась позже. А ведь именно она решает единственный законный случай для .css() — динамическое значение.
Смежные темы: узнать класс элемента; изменить содержимое; установка атрибутов; уроки JavaScript.
Частые вопросы
Почему `.css('color')` возвращает `rgb(255, 0, 0)`, а не `red`?
getComputedStyle. Сравнивать стили строками поэтому ненадёжно: red, #f00 и rgb(255,0,0) — одно и то же значение в трёх записях.Чем `el.style.color` отличается от `getComputedStyle(el).color`?
el.style читает только инлайновые стили — то, что стоит в атрибуте style. Правило из CSS-файла там не появится, вернётся пустая строка. getComputedStyle показывает итог всех правил.Как менять стили правильно?
classList.toggle('active'), а сами правила — в CSS. Прямая запись в style перебивает таблицу стилей и создаёт код, который нельзя переопределить без !important.Что такое CSS-переменные и чем они удобнее?
el.style.setProperty('--progress', '70%'). JS передаёт данные, CSS решает, как их показать.