← Назад к вопросам

Как сделать кнопку смены темы влияющую на все контролы на экране без JavaScript?

2.0 Middle🔥 121 комментариев
#JavaScript Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Переключение темы без JavaScript (CSS-only подход)

Хотя полностью без JavaScript невозможно, можно минимизировать его использование. Существует CSS-only решение с использованием атрибутов и CSS селекторов.

CSS-only решение с checkbox hack

<label class="theme-toggle">
  <input type="checkbox" id="theme-toggle" />
  <span class="toggle-slider"></span>
</label>

<main>
  <button>Click me</button>
  <input type="text" placeholder="Type something" />
  <div class="card">Content</div>
</main>

<style>
  :root {
    --color-bg: white;
    --color-text: black;
    --color-primary: blue;
  }

  #theme-toggle:checked ~ main {
    --color-bg: #1e1e1e;
    --color-text: #ffffff;
    --color-primary: #00d4ff;
  }

  body {
    background-color: var(--color-bg);
    color: var(--color-text);
  }

  button {
    background-color: var(--color-primary);
    color: var(--color-text);
  }

  input {
    background-color: var(--color-bg);
    color: var(--color-text);
    border: 1px solid var(--color-primary);
  }
</style>

С prefers-color-scheme (истинно без JS)

Самый чистый способ - использовать системные настройки:

:root {
  --color-bg: white;
  --color-text: black;
  --color-primary: #0066cc;
}

@media (prefers-color-scheme: dark) {
  :root {
    --color-bg: #1a1a1a;
    --color-text: #ffffff;
    --color-primary: #00d4ff;
  }
}

body {
  background-color: var(--color-bg);
  color: var(--color-text);
  transition: background-color 0.3s, color 0.3s;
}

button {
  background-color: var(--color-primary);
  color: var(--color-text);
  padding: 10px 20px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

input {
  background-color: var(--color-bg);
  color: var(--color-text);
  border: 2px solid var(--color-primary);
  padding: 8px;
}

Комбинированный подход (рекомендуемый)

function setupTheme() {
  const toggle = document.getElementById('theme-toggle');
  const saved = localStorage.getItem('theme');
  
  if (saved === 'dark') {
    document.documentElement.setAttribute('data-theme', 'dark');
    toggle.checked = true;
  }
}

export function ThemeToggle() {
  return (
    <label className="theme-toggle">
      <input 
        type="checkbox" 
        id="theme-toggle"
        onChange={(e) => {
          document.documentElement.setAttribute(
            'data-theme',
            e.target.checked ? 'dark' : 'light'
          );
          localStorage.setItem(
            'theme',
            e.target.checked ? 'dark' : 'light'
          );
        }}
      />
      <span className="toggle-slider"></span>
    </label>
  );
}

const css = `
  :root {
    --color-bg: white;
    --color-text: #000;
    --color-primary: #0066cc;
  }

  [data-theme="dark"] {
    --color-bg: #1a1a1a;
    --color-text: #fff;
    --color-primary: #00d4ff;
  }

  body {
    background-color: var(--color-bg);
    color: var(--color-text);
    transition: background-color 0.3s ease, color 0.3s ease;
  }

  button, input, textarea, select {
    background-color: var(--color-bg);
    color: var(--color-text);
    border-color: var(--color-primary);
  }
`;

Продвинутое CSS решение с CSS Variables

:root {
  --palette-primary: hsl(210, 100%, 50%);
  --palette-primary-dark: hsl(210, 100%, 40%);
  --palette-bg-light: hsl(0, 0%, 100%);
  --palette-bg-dark: hsl(0, 0%, 10%);
  --palette-text-light: hsl(0, 0%, 0%);
  --palette-text-dark: hsl(0, 0%, 100%);

  --color-bg: var(--palette-bg-light);
  --color-text: var(--palette-text-light);
  --color-primary: var(--palette-primary);
}

@media (prefers-color-scheme: dark) {
  :root {
    --color-bg: var(--palette-bg-dark);
    --color-text: var(--palette-text-dark);
    --color-primary: var(--palette-primary-dark);
  }
}

[data-theme="light"] {
  --color-bg: var(--palette-bg-light);
  --color-text: var(--palette-text-light);
  --color-primary: var(--palette-primary);
}

[data-theme="dark"] {
  --color-bg: var(--palette-bg-dark);
  --color-text: var(--palette-text-dark);
  --color-primary: var(--palette-primary-dark);
}

* {
  transition: background-color 0.3s ease, color 0.3s ease, border-color 0.3s ease;
}

React компонент с системными настройками

function App() {
  const [theme, setTheme] = React.useState('system');

  React.useEffect(() => {
    const root = document.documentElement;
    if (theme === 'system') {
      root.removeAttribute('data-theme');
    } else {
      root.setAttribute('data-theme', theme);
    }
    localStorage.setItem('theme', theme);
  }, [theme]);

  return (
    <div>
      <button onClick={() => setTheme('light')}>Light</button>
      <button onClick={() => setTheme('dark')}>Dark</button>
      <button onClick={() => setTheme('system')}>System</button>
      <main>
        {/* Content */}
      </main>
    </div>
  );
}
Как сделать кнопку смены темы влияющую на все контролы на экране без JavaScript? | PrepBro