Setting Up Dark Mode for a 1C-Bitrix Site
Dark mode on a website means CSS variables with two sets of values, logic for detecting user preferences, and saving their choice. Bitrix adds no specific complexity here — this is a pure frontend task that needs to be carefully integrated into the site template.
CSS Architecture for Two Themes
The foundation is CSS custom properties (variables). Rather than changing colours directly via a .dark class, use variables that are overridden depending on the active theme.
In the main template CSS (/local/templates/[template]/style.css):
/* Light theme — default values */
:root {
--color-bg: #ffffff;
--color-text: #1a1a1a;
--color-primary: #0066cc;
--color-border: #e0e0e0;
--color-card-bg: #f5f5f5;
--color-header-bg: #ffffff;
--color-shadow: rgba(0,0,0,0.08);
}
/* Dark theme */
:root[data-theme="dark"],
.dark-mode {
--color-bg: #121212;
--color-text: #e4e4e4;
--color-primary: #4da3ff;
--color-border: #333333;
--color-card-bg: #1e1e1e;
--color-header-bg: #1a1a1a;
--color-shadow: rgba(0,0,0,0.4);
}
/* User system preferences */
@media (prefers-color-scheme: dark) {
:root:not([data-theme="light"]) {
--color-bg: #121212;
--color-text: #e4e4e4;
/* ... */
}
}
Use variables instead of hardcoded colours in all components:
body { background: var(--color-bg); color: var(--color-text); }
.card { background: var(--color-card-bg); border-color: var(--color-border); }
Saving the User's Choice
The theme choice is saved in localStorage so it persists across sessions without authentication:
// Apply the theme immediately on page load (before rendering)
// Insert this script in the template <head>, BEFORE loading CSS
(function() {
const saved = localStorage.getItem('theme');
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
const theme = saved || (prefersDark ? 'dark' : 'light');
document.documentElement.setAttribute('data-theme', theme);
})();
Critical: this script must be inline in <head>, before styles are loaded. Otherwise there will be a flash on load — a white screen before the dark theme is applied (FOUC — Flash of Unstyled Content).
In the Bitrix template (header.php):
<head>
<!-- ... meta tags ... -->
<script>
(function() {
const t = localStorage.getItem('theme')
|| (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
document.documentElement.setAttribute('data-theme', t);
})();
</script>
<?php $APPLICATION->ShowHead(); ?>
</head>
Images in Dark Mode
Logos and icons are often unreadable on a dark background. Solutions:
Option 1 — CSS filter:
.dark-mode .site-logo img {
filter: brightness(0) invert(1);
}
Option 2 — <picture> with prefers-color-scheme:
<picture>
<source srcset="/img/logo-dark.svg" media="(prefers-color-scheme: dark)">
<img src="/img/logo-light.svg" alt="Logo">
</picture>
Option 3 — Change the src attribute via JS when the theme switches.
Bitrix Components and Dark Mode
Standard Bitrix components (pagination, forms, search) use their own styles. You will need to override CSS for each component in use. Pay special attention to:
-
.bx-sls(smart search) — has its own inline style -
.popup-window-content(Bitrix popups) - The authentication component
/bitrix/components/bitrix/system.auth.form/
Override in your own CSS:
:root[data-theme="dark"] .bx-sls {
background: var(--color-card-bg);
color: var(--color-text);
}
| Stage | Time |
|---|---|
| Converting styles to CSS variables | 6–12 h |
| Theme detection script and switching logic | 2–3 h |
| Adapting images and icons | 2–4 h |
| Overriding Bitrix component styles | 3–6 h |
| Testing across browsers and modes | 2–3 h |







