Настройка переключателя тёмной/светлой темы 1С-Битрикс
Переключатель темы — небольшой UI-компонент: кнопка или тумблер в шапке сайта, по нажатию на который меняется тема. Задача решается полностью на фронтенде и не требует изменений в PHP-коде Битрикса, только правильного встраивания в шаблон.
HTML-разметка переключателя
Простой тумблер с иконками солнца и луны:
<button
id="theme-toggle"
class="theme-toggle"
aria-label="Переключить тему"
title="Переключить тему"
>
<svg class="icon-sun" viewBox="0 0 24 24" width="20" height="20">
<!-- иконка солнца -->
</svg>
<svg class="icon-moon" viewBox="0 0 24 24" width="20" height="20">
<!-- иконка луны -->
</svg>
</button>
CSS для состояний:
.theme-toggle .icon-moon { display: none; }
.theme-toggle .icon-sun { display: block; }
:root[data-theme="dark"] .theme-toggle .icon-moon { display: block; }
:root[data-theme="dark"] .theme-toggle .icon-sun { display: none; }
JavaScript переключения
const toggle = document.getElementById('theme-toggle');
toggle.addEventListener('click', () => {
const current = document.documentElement.getAttribute('data-theme');
const next = current === 'dark' ? 'light' : 'dark';
document.documentElement.setAttribute('data-theme', next);
localStorage.setItem('theme', next);
// Если нужно сохранить для авторизованных пользователей на сервере:
if (window.BX && BX.ajax) {
BX.ajax.post('/local/ajax/save-theme.php', {theme: next});
}
});
Встраивание в шаблон Битрикса
В файле header.php шаблона сайта размещаете кнопку в нужном месте шапки. Инлайновый скрипт определения темы (для предотвращения FOUC) должен идти первым в <head>:
<!-- В <head>, до подключения стилей -->
<script>
(function() {
var t = localStorage.getItem('theme')
|| (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
document.documentElement.setAttribute('data-theme', t);
document.documentElement.classList.add('theme-ready');
})();
</script>
Класс theme-ready помогает убрать transition-анимацию при первой загрузке:
/* Отключаем анимацию до готовности темы */
html:not(.theme-ready) * { transition: none !important; }
Плавный переход между темами
Чтобы смена темы не была резкой:
body,
body *:not(.no-transition) {
transition: background-color 0.2s ease, color 0.2s ease,
border-color 0.2s ease, box-shadow 0.2s ease;
}
Добавляйте переход только на конкретные CSS-свойства цвета — не transition: all, иначе будут тормозить анимации контента.
Сохранение темы для авторизованных пользователей
Для авторизованных пользователей тему можно хранить в профиле, чтобы она применялась сразу при рендере на сервере без мелькания:
// /local/ajax/save-theme.php
if ($USER->IsAuthorized()) {
$theme = in_array($_POST['theme'], ['dark', 'light']) ? $_POST['theme'] : 'light';
CUser::Update($USER->GetID(), ['UF_THEME' => $theme]);
}
В header.php:
<?php
$savedTheme = 'light';
if ($USER->IsAuthorized()) {
$userFields = CUser::GetByID($USER->GetID())->Fetch();
$savedTheme = $userFields['UF_THEME'] ?? 'light';
}
?>
<html data-theme="<?= htmlspecialchars($savedTheme) ?>">
В этом случае инлайновый скрипт в <head> всё равно нужен — он перекрывает серверное значение предпочтением из localStorage для неавторизованных.
| Этап | Время |
|---|---|
| Разметка и стили переключателя | 1–2 ч |
| JS-логика переключения + localStorage | 1–2 ч |
| Предотвращение FOUC (инлайновый скрипт) | 1 ч |
| Плавные переходы (CSS transitions) | 1 ч |
| Сохранение в профиле пользователя (опционально) | 2–3 ч |







