← Назад к вопросам
Какой технологией лучше добавлять стили элементам: через JavaScript или CSS?
2.3 Middle🔥 241 комментариев
#HTML и CSS
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Добавление стилей: CSS vs JavaScript
Это фундаментальный вопрос в веб-разработке. Правильный ответ: CSS в 95% случаев, JavaScript только для динамических изменений. Давайте разберёмся, почему.
Способ 1: CSS (правильно)
Статичные стили:
/* button.css */
.button {
padding: 12px 24px;
background-color: #007bff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 16px;
}
.button:hover {
background-color: #0056b3;
}
.button:active {
transform: scale(0.98);
}
.button.disabled {
background-color: #ccc;
cursor: not-allowed;
opacity: 0.6;
}
<!-- HTML -->
<button class="button">Click me</button>
<button class="button disabled">Disabled</button>
Способ 2: JavaScript (обычно неправильно)
// Плохо — стили в JavaScript
const button = document.querySelector('button');
button.style.padding = '12px 24px';
button.style.backgroundColor = '#007bff';
button.style.color = 'white';
button.style.border = 'none';
button.style.borderRadius = '4px';
button.style.cursor = 'pointer';
button.style.fontSize = '16px';
button.addEventListener('mouseenter', () => {
button.style.backgroundColor = '#0056b3';
});
button.addEventListener('mouseleave', () => {
button.style.backgroundColor = '#007bff';
});
Почему это плохо:
- Код в JavaScript трудно читать
- Невозможно использовать CSS состояния (hover, active, focus)
- Дублирование с CSS
- Сложнее изменять стили
Способ 3: CSS классы + JavaScript (правильный гибридный подход)
Для динамических изменений используй классы:
/* Стили в CSS */
.button {
padding: 12px 24px;
background-color: #007bff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
transition: background-color 0.3s ease;
}
.button:hover {
background-color: #0056b3;
}
.button.is-loading {
background-color: #999;
cursor: not-allowed;
}
.button.is-active {
box-shadow: 0 0 10px rgba(0, 123, 255, 0.5);
}
// JavaScript только для управления классами
const button = document.querySelector('button');
button.addEventListener('click', async () => {
button.classList.add('is-loading');
try {
const response = await fetch('/api/data');
const data = await response.json();
button.classList.remove('is-loading');
button.classList.add('is-active');
} catch (error) {
button.classList.remove('is-loading');
console.error(error);
}
});
Это лучший подход потому что:
- CSS отвечает за внешний вид
- JavaScript отвечает за логику
- Легко менять стили без изменения JavaScript
- Переиспользуются стили и классы
Сравнение подходов
| Критерий | CSS | JavaScript | CSS + JS классы |
|---|---|---|---|
| Читаемость | ✅ Отличная | ❌ Плохая | ✅ Отличная |
| Производительность | ✅ Быстро | ❌ Медленно | ✅ Быстро |
| Hover/Focus | ✅ Встроено | ❌ Нужно код | ✅ Встроено |
| Анимация | ✅ GPU ускорение | ❌ Обновление DOM | ✅ GPU ускорение |
| Переиспользование | ✅ Да | ❌ Нет | ✅ Да |
| Масштабируемость | ✅ Масштабируется | ❌ Кошмар | ✅ Масштабируется |
| Динамические стили | ❌ Нельзя | ✅ Можно | ✅ Можно (методом) |
Когда JavaScript необходим для стилей
Есть несколько легитимных случаев, когда нужен JavaScript:
1. Действительно динамические значения (вычисления)
// CSS Variables (рекомендуется)
const element = document.querySelector('.box');
const windowWidth = window.innerWidth;
element.style.setProperty('--box-width', `${windowWidth * 0.8}px`);
.box {
width: var(--box-width, 100px); /* fallback */
}
2. Координаты и позиции (после измерения)
// Позиционирование тултипа или попапа
function positionTooltip(trigger, tooltip) {
const rect = trigger.getBoundingClientRect();
tooltip.style.top = `${rect.bottom + 10}px`;
tooltip.style.left = `${rect.left + rect.width / 2 - tooltip.offsetWidth / 2}px`;
}
3. Анимации на основе скролла или движения мыши
window.addEventListener('mousemove', (e) => {
const element = document.querySelector('.element');
const distance = Math.sqrt(e.clientX ** 2 + e.clientY ** 2);
element.style.setProperty('--mouse-distance', distance);
});
.element {
transform: scale(calc(1 + var(--mouse-distance) / 1000));
transition: transform 0.2s ease;
}
В современных фреймворках (React, Vue)
React с Tailwind (идеально):
// Используй условные классы
function Button({ isLoading, isActive }) {
return (
<button
className={`
px-6 py-3 bg-blue-500 text-white rounded
hover:bg-blue-600
disabled:bg-gray-400
${isLoading ? 'opacity-50 cursor-not-allowed' : ''}
${isActive ? 'ring-2 ring-blue-300' : ''}
`}
>
Click me
</button>
);
}
React с CSS-in-JS (когда нужна динамика):
import styled from 'styled-components';
const StyledButton = styled.button`
padding: 12px 24px;
background-color: ${props => props.isLoading ? '#999' : '#007bff'};
color: white;
border: none;
border-radius: 4px;
cursor: ${props => props.isLoading ? 'not-allowed' : 'pointer'};
&:hover {
background-color: #0056b3;
}
`;
function Button({ isLoading }) {
return <StyledButton isLoading={isLoading}>Click</StyledButton>;
}
Производительность
CSS реплит быстрее:
// Плохо — 100 перерисовок (repaints)
for (let i = 0; i < 100; i++) {
element.style.backgroundColor = colors[i];
// Браузер перерисовывает при каждом изменении
}
// Хорошо — 1 перерисовка
element.style.animation = 'colorChange 5s infinite';
// Или с классом
element.classList.add('color-animation');
@keyframes colorChange {
0% { background-color: red; }
50% { background-color: blue; }
100% { background-color: green; }
}
.color-animation {
animation: colorChange 5s infinite;
}
Чеклист
- По умолчанию — CSS (97% случаев)
- Для состояний — CSS классы с JavaScript (управление классами)
- Для вычисляемых значений — CSS Variables из JavaScript (setProperty)
- Только в исключениях — inline styles (позиционирование, вычисления)
Золотое правило: CSS — это про внешний вид, JavaScript — про логику. Не смешивай!