CodeChroma All articles
Accessibility & Colour Systems

When the Sky Clocks Off Early: A Seasonal Palette for UK Websites

CodeChroma
When the Sky Clocks Off Early: A Seasonal Palette for UK Websites

The UK does not do binary light. In Lerwick, a December afternoon can feel finished before the school run; in Cornwall, a July evening can still be glowing at 9.30pm. A website that flips from light to dark at 19:00 is not responding to that rhythm. It is responding to a developer’s idea of a rhythm.

The 6pm sunset argument is really about the weeks when the sky clocks off before the day feels done. Fixed modes ignore all of it. They also tend to create a second problem: the dark mode is often a cool, blue-grey affair that looks smart on a monitor and grim on a train home from Leeds in February. A seasonal palette will not fix British weather, but it can make a site feel less detached from it.

Why a two-mode toggle misses the point

Most light/dark toggles are built around a user preference, which is good, and around a schedule, which is often crude. prefers-color-scheme tells you what the operating system is doing. It does not tell you whether the user is in Aberdeen at 15:40 in November or in Brighton at 21:00 in June.

A dawn-to-dusk theme is not an excuse to override user choice. Think of it as a third layer: the user’s explicit toggle wins; the system preference is the fallback; the seasonal phase only shifts the palette when the user has not asked for something else. That is the difference between a thoughtful colour system and a site that redecorates itself while you are trying to read.

Start with tokens, not themes

Keep the number of moving parts small. Four phases are enough: dawn, day, dusk and night. Each phase should change a handful of custom properties — background, ink, surface, accent — rather than rebuilding entire components.

:root {
  --bg: #f7f3ea;
  --bg: oklch(0.97 0.01 90);
  --ink: #1f2933;
  --ink: oklch(0.25 0.02 250);
  --surface: #efe7d8;
  --accent: #a33b2b;
}

[data-light-phase='dawn'] {
  --bg: #f3eee7;
  --ink: #22313a;
  --surface: #e9e1d8;
  --accent: #b4513b;
}

[data-light-phase='dusk'] {
  --bg: #2f2a2a;
  --ink: #f4eee2;
  --surface: #3b3331;
  --accent: #e0a45a;
}

[data-light-phase='night'] {
  --bg: #15171d;
  --ink: #f0ece3;
  --surface: #20232b;
  --accent: #f0b36b;
}

The hex values before the OKLCH lines are deliberate fallbacks for older rendering engines. More importantly, the dusk and night palettes are not just warmed-up versions of day. They raise text lightness and keep the accent away from muddy browns. If you let the accent drift into the same family as the background, every button becomes a contrast gamble.

A tiny sunrise/sunset switch

You do not need a full solar calculator for a first version. A month-based approximation is enough to prove the idea, then you can swap in real sun times later. Run this inline in the head so the attribute is set before first paint.

const root = document.documentElement;

function phaseFor(date = new Date()) {
  const month = date.getMonth();
  const hour = date.getHours() + date.getMinutes() / 60;
  const winter = month <= 1 || month >= 10;
  const summer = month >= 4 && month <= 8;
  const sunrise = winter ? 7.6 : summer ? 4.8 : 6.2;
  const sunset = winter ? 16.2 : summer ? 21.2 : 18.5;

  if (hour < sunrise - 0.75) return 'night';
  if (hour < sunrise + 1) return 'dawn';
  if (hour < sunset - 1) return 'day';
  if (hour < sunset + 0.75) return 'dusk';
  return 'night';
}

function paintPhase() {
  root.dataset.lightPhase = phaseFor();
}

paintPhase();
setInterval(paintPhase, 15 * 60 * 1000);

That is deliberately blunt. It treats the whole UK as one timezone, ignores cloud cover and does not know that Shetland is darker than Sussex. For a proper implementation, use a solar-position library or a small API and store the calculated phase rather than the raw time. The point is the architecture: one attribute on the root element, one set of tokens, no component-level colour chaos.

Accessible by default, not as an afterthought

Seasonal colour is a trap if you treat dusk as an excuse for low contrast. Warm greys on warm browns may look atmospheric in a moodboard; at 20% phone brightness on a Northern Rail service, they can be unreadable.

Keep body text at WCAG 2.2 AA — 4.5:1 for normal text, 3:1 for large text — in every phase. Test the accent colour as a link, as a button background and as a focus ring. Do not rely on colour alone to show phase changes or state.

Fallbacks matter too. If JavaScript fails, the page should still use prefers-color-scheme. If forced-colors mode is active, let the system colours win. If the user prefers reduced motion, drop any colour transition rather than easing them through a sunset they did not ask for.

@media (prefers-color-scheme: dark) {
  :root:not([data-light-phase]) {
    --bg: #15171d;
    --ink: #f0ece3;
    --surface: #20232b;
    --accent: #f0b36b;
  }
}

@media (prefers-reduced-motion: reduce) {
  * {
    transition: none !important;
  }
}

A test plan for gloomy conditions

Test the thing in the conditions it is meant for. Check the site at 8am, 1pm, 4pm and 10pm in January and July. Use DevTools to emulate forced-colors and reduced motion. Run axe and Lighthouse, but also do the boring manual checks: tab through the page, read a long paragraph, find the focus ring on a dark surface.

Then make it worse. Turn the screen brightness down. Sit near a window at 4pm. Try it with JavaScript disabled. Try it with a slow connection so the inline script and the CSS arrive at different times. If the page flashes a bright background before settling into night, you have a first-paint problem, not a palette problem.

A dawn-to-dusk theme will not suit every brand. But for UK sites that live outdoors in the national imagination — weather, travel, gardens, local news, makers’ journals — a palette that acknowledges the actual sky is more honest than a toggle that pretends the day is always the same length.

All Articles

Related Articles

Beyond the Muted Middle: A Bolder Colour System That Still Behaves

Beyond the Muted Middle: A Bolder Colour System That Still Behaves

Contrast Without the Beige: An OKLCH Palette Workflow for UK Public-Sector Sites

Contrast Without the Beige: An OKLCH Palette Workflow for UK Public-Sector Sites

Blue from Woad, Red from Madder: Mixing Britain’s Dye Garden in GLSL