Представь: дизайнер меняет фирменный цвет с синего на фиолетовый. Без переменных тебе нужно найти и заменить #3b82f6 в 50 местах файла. С CSS-переменными — поменять одну строку в начале файла. Это и есть Custom Properties — нативные переменные CSS, встроенные прямо в браузер.
/* Объявление: двойной дефис + имя */
:root {
--color-primary: #7b2ff7;
--color-text: #1a202c;
--spacing-md: 16px;
--border-radius: 8px;
}
/* Использование: var() */
.btn {
background-color: var(--color-primary);
padding: var(--spacing-md);
border-radius: var(--border-radius);
}:root — это <html>, самый верхний элемент. Переменные, объявленные здесь, доступны во всём документе.
:root {
--color-primary: #7b2ff7;
--color-secondary: #3b82f6;
--color-success: #38a169;
--color-danger: #e53e3e;
--font-size-base: 16px;
--font-size-sm: 14px;
--font-size-lg: 20px;
}Переменная доступна только внутри элемента, где объявлена, и его потомкам.
.card {
--card-padding: 24px;
--card-bg: white;
padding: var(--card-padding);
background: var(--card-bg);
}
.card .card-header {
padding: var(--card-padding); /* Работает — потомок .card */
}
.other-element {
padding: var(--card-padding); /* Не работает — переменная не видна */
}color: var(--color-brand, #7b2ff7); /* Если --color-brand не задана, используй #7b2ff7 */
font-size: var(--size-title, var(--size-base, 16px)); /* Цепочка fallback */Это киллер-фича CSS-переменных. Вместо дублирования всех стилей — просто меняем значения переменных:
:root {
--bg: white;
--text: #1a202c;
--card-bg: #f7fafc;
}
[data-theme="dark"] {
--bg: #1a202c;
--text: #f7fafc;
--card-bg: #2d3748;
}
body { background: var(--bg); color: var(--text); }
.card { background: var(--card-bg); }Переключить тему: document.documentElement.setAttribute('data-theme', 'dark')
| | CSS Custom Properties | SCSS Variables |
|---|---|---|
| Работает в браузере | Да | Нет (компилируется) |
| Изменяемы в JS | Да | Нет |
| Реагируют на медиа-запросы | Да | Нет |
| Локальная область видимости | Да | Нет |
| Поддержка браузеров | Все современные | Везде |
CSS-переменные живут в браузере — их можно читать и менять через JavaScript.
// Читать
const primary = getComputedStyle(document.documentElement)
.getPropertyValue('--color-primary').trim()
// Задать на корневом элементе
document.documentElement.style.setProperty('--color-primary', '#e53e3e')
// Задать локально на элементе
element.style.setProperty('--card-padding', '32px')Ошибка 1: Пробел между -- и именем
-- color-primary: red; /* Ошибка! */
--color-primary: red; /* Правильно */Ошибка 2: Забыть var()
color: --color-primary; /* Неправильно — это не работает */
color: var(--color-primary); /* Правильно */Ошибка 3: Переменная не определена — нет ошибки, просто невалидное значение
color: var(--undefined-var); /* Применится как 'initial' — без ошибки в консоли */
/* Используй fallback: */
color: var(--undefined-var, black);Каждый серьёзный проект сегодня использует CSS-переменные для дизайн-токенов: цветов, отступов, теней, радиусов. Они заменяют SCSS-переменные там, где нужна динамика. Tailwind CSS в версии 4 полностью перешёл на Custom Properties. Материал-дизайн от Google и Ant Design хранят свои темы именно в CSS-переменных.
CSS-переменные: создание и переключение тёмной темы
// Задаём переменные через JS на :root
const root = document.documentElement
// Светлая тема по умолчанию
root.style.setProperty('--bg-primary', '#ffffff')
root.style.setProperty('--bg-secondary', '#f7fafc')
root.style.setProperty('--text-primary', '#1a202c')
root.style.setProperty('--text-secondary', '#718096')
root.style.setProperty('--color-accent', '#7b2ff7')
root.style.setProperty('--border-color', '#e2e8f0')
root.style.setProperty('--border-radius', '8px')
root.style.setProperty('--spacing', '16px')
// Стили, которые используют переменные
const styleTag = document.createElement('style')
styleTag.textContent = `
body {
background: var(--bg-primary);
color: var(--text-primary);
font-family: Arial, sans-serif;
padding: var(--spacing);
transition: background 0.3s, color 0.3s;
}
.card {
background: var(--bg-secondary);
border: 1px solid var(--border-color);
border-radius: var(--border-radius);
padding: var(--spacing);
margin-bottom: var(--spacing);
}
.card-title {
color: var(--color-accent);
font-weight: 700;
margin: 0 0 8px;
}
.card-text {
color: var(--text-secondary);
margin: 0;
}
.theme-btn {
background: var(--color-accent);
color: white;
border: none;
padding: 8px 16px;
border-radius: var(--border-radius);
cursor: pointer;
}
`
document.head.appendChild(styleTag)
// Создаём карточку
const card = document.createElement('div')
card.className = 'card'
card.innerHTML = '<h3 class="card-title">Урок CSS</h3><p class="card-text">CSS-переменные делают темы простыми</p>'
document.body.appendChild(card)
// Кнопка переключения темы
const themeBtn = document.createElement('button')
themeBtn.className = 'theme-btn'
themeBtn.textContent = 'Тёмная тема'
document.body.appendChild(themeBtn)
let isDark = false
themeBtn.addEventListener('click', () => {
isDark = !isDark
if (isDark) {
root.style.setProperty('--bg-primary', '#1a202c')
root.style.setProperty('--bg-secondary', '#2d3748')
root.style.setProperty('--text-primary', '#f7fafc')
root.style.setProperty('--text-secondary', '#a0aec0')
root.style.setProperty('--border-color', '#4a5568')
themeBtn.textContent = 'Светлая тема'
} else {
root.style.setProperty('--bg-primary', '#ffffff')
root.style.setProperty('--bg-secondary', '#f7fafc')
root.style.setProperty('--text-primary', '#1a202c')
root.style.setProperty('--text-secondary', '#718096')
root.style.setProperty('--border-color', '#e2e8f0')
themeBtn.textContent = 'Тёмная тема'
}
console.log('Тема переключена:', isDark ? 'тёмная' : 'светлая')
})
// Читаем переменные
const styles = getComputedStyle(root)
console.log('--color-accent:', styles.getPropertyValue('--color-accent').trim())
console.log('--border-radius:', styles.getPropertyValue('--border-radius').trim())
console.log('--spacing:', styles.getPropertyValue('--spacing').trim())
// Локальная переменная на конкретном элементе
card.style.setProperty('--card-scale', '1.05')
console.log('Локальная --card-scale:', getComputedStyle(card).getPropertyValue('--card-scale').trim())Представь: дизайнер меняет фирменный цвет с синего на фиолетовый. Без переменных тебе нужно найти и заменить #3b82f6 в 50 местах файла. С CSS-переменными — поменять одну строку в начале файла. Это и есть Custom Properties — нативные переменные CSS, встроенные прямо в браузер.
/* Объявление: двойной дефис + имя */
:root {
--color-primary: #7b2ff7;
--color-text: #1a202c;
--spacing-md: 16px;
--border-radius: 8px;
}
/* Использование: var() */
.btn {
background-color: var(--color-primary);
padding: var(--spacing-md);
border-radius: var(--border-radius);
}:root — это <html>, самый верхний элемент. Переменные, объявленные здесь, доступны во всём документе.
:root {
--color-primary: #7b2ff7;
--color-secondary: #3b82f6;
--color-success: #38a169;
--color-danger: #e53e3e;
--font-size-base: 16px;
--font-size-sm: 14px;
--font-size-lg: 20px;
}Переменная доступна только внутри элемента, где объявлена, и его потомкам.
.card {
--card-padding: 24px;
--card-bg: white;
padding: var(--card-padding);
background: var(--card-bg);
}
.card .card-header {
padding: var(--card-padding); /* Работает — потомок .card */
}
.other-element {
padding: var(--card-padding); /* Не работает — переменная не видна */
}color: var(--color-brand, #7b2ff7); /* Если --color-brand не задана, используй #7b2ff7 */
font-size: var(--size-title, var(--size-base, 16px)); /* Цепочка fallback */Это киллер-фича CSS-переменных. Вместо дублирования всех стилей — просто меняем значения переменных:
:root {
--bg: white;
--text: #1a202c;
--card-bg: #f7fafc;
}
[data-theme="dark"] {
--bg: #1a202c;
--text: #f7fafc;
--card-bg: #2d3748;
}
body { background: var(--bg); color: var(--text); }
.card { background: var(--card-bg); }Переключить тему: document.documentElement.setAttribute('data-theme', 'dark')
| | CSS Custom Properties | SCSS Variables |
|---|---|---|
| Работает в браузере | Да | Нет (компилируется) |
| Изменяемы в JS | Да | Нет |
| Реагируют на медиа-запросы | Да | Нет |
| Локальная область видимости | Да | Нет |
| Поддержка браузеров | Все современные | Везде |
CSS-переменные живут в браузере — их можно читать и менять через JavaScript.
// Читать
const primary = getComputedStyle(document.documentElement)
.getPropertyValue('--color-primary').trim()
// Задать на корневом элементе
document.documentElement.style.setProperty('--color-primary', '#e53e3e')
// Задать локально на элементе
element.style.setProperty('--card-padding', '32px')Ошибка 1: Пробел между -- и именем
-- color-primary: red; /* Ошибка! */
--color-primary: red; /* Правильно */Ошибка 2: Забыть var()
color: --color-primary; /* Неправильно — это не работает */
color: var(--color-primary); /* Правильно */Ошибка 3: Переменная не определена — нет ошибки, просто невалидное значение
color: var(--undefined-var); /* Применится как 'initial' — без ошибки в консоли */
/* Используй fallback: */
color: var(--undefined-var, black);Каждый серьёзный проект сегодня использует CSS-переменные для дизайн-токенов: цветов, отступов, теней, радиусов. Они заменяют SCSS-переменные там, где нужна динамика. Tailwind CSS в версии 4 полностью перешёл на Custom Properties. Материал-дизайн от Google и Ant Design хранят свои темы именно в CSS-переменных.
CSS-переменные: создание и переключение тёмной темы
// Задаём переменные через JS на :root
const root = document.documentElement
// Светлая тема по умолчанию
root.style.setProperty('--bg-primary', '#ffffff')
root.style.setProperty('--bg-secondary', '#f7fafc')
root.style.setProperty('--text-primary', '#1a202c')
root.style.setProperty('--text-secondary', '#718096')
root.style.setProperty('--color-accent', '#7b2ff7')
root.style.setProperty('--border-color', '#e2e8f0')
root.style.setProperty('--border-radius', '8px')
root.style.setProperty('--spacing', '16px')
// Стили, которые используют переменные
const styleTag = document.createElement('style')
styleTag.textContent = `
body {
background: var(--bg-primary);
color: var(--text-primary);
font-family: Arial, sans-serif;
padding: var(--spacing);
transition: background 0.3s, color 0.3s;
}
.card {
background: var(--bg-secondary);
border: 1px solid var(--border-color);
border-radius: var(--border-radius);
padding: var(--spacing);
margin-bottom: var(--spacing);
}
.card-title {
color: var(--color-accent);
font-weight: 700;
margin: 0 0 8px;
}
.card-text {
color: var(--text-secondary);
margin: 0;
}
.theme-btn {
background: var(--color-accent);
color: white;
border: none;
padding: 8px 16px;
border-radius: var(--border-radius);
cursor: pointer;
}
`
document.head.appendChild(styleTag)
// Создаём карточку
const card = document.createElement('div')
card.className = 'card'
card.innerHTML = '<h3 class="card-title">Урок CSS</h3><p class="card-text">CSS-переменные делают темы простыми</p>'
document.body.appendChild(card)
// Кнопка переключения темы
const themeBtn = document.createElement('button')
themeBtn.className = 'theme-btn'
themeBtn.textContent = 'Тёмная тема'
document.body.appendChild(themeBtn)
let isDark = false
themeBtn.addEventListener('click', () => {
isDark = !isDark
if (isDark) {
root.style.setProperty('--bg-primary', '#1a202c')
root.style.setProperty('--bg-secondary', '#2d3748')
root.style.setProperty('--text-primary', '#f7fafc')
root.style.setProperty('--text-secondary', '#a0aec0')
root.style.setProperty('--border-color', '#4a5568')
themeBtn.textContent = 'Светлая тема'
} else {
root.style.setProperty('--bg-primary', '#ffffff')
root.style.setProperty('--bg-secondary', '#f7fafc')
root.style.setProperty('--text-primary', '#1a202c')
root.style.setProperty('--text-secondary', '#718096')
root.style.setProperty('--border-color', '#e2e8f0')
themeBtn.textContent = 'Тёмная тема'
}
console.log('Тема переключена:', isDark ? 'тёмная' : 'светлая')
})
// Читаем переменные
const styles = getComputedStyle(root)
console.log('--color-accent:', styles.getPropertyValue('--color-accent').trim())
console.log('--border-radius:', styles.getPropertyValue('--border-radius').trim())
console.log('--spacing:', styles.getPropertyValue('--spacing').trim())
// Локальная переменная на конкретном элементе
card.style.setProperty('--card-scale', '1.05')
console.log('Локальная --card-scale:', getComputedStyle(card).getPropertyValue('--card-scale').trim())Создай CSS с тремя переменными в `:root`: `--primary` для цвета кнопки, `--padding` для отступов, `--radius` для скруглений. Используй эти переменные в стилях компонентов через `var()`. Добавь кнопку переключения темы: при клике меняй значение `--primary` на `#e53e3e`.
Объяви переменные в `:root` с двойным дефисом: `--primary: #7b2ff7`. Используй через `var(--primary)`. При клике `document.documentElement.style.setProperty('--primary', '#e53e3e')` меняет переменную для всего документа.