A few years ago, a Prague-based fintech startup asked us to add a dark mode toggle to their dashboard. We figured it would take a couple of days. It took two weeks — because dark mode is not simply inverting colors. It demands its own design language, its own palette, and careful attention to every element on the page. That project changed how we approach the feature ever since.
What dark mode actually requires
Dark mode has moved from a niche preference to a mainstream expectation. Operating systems, browsers, and major applications all offer it, and users have grown accustomed to switching between light and dark depending on their environment. For many people, dark mode reduces eye strain during late-night browsing sessions. For others, it simply looks more refined.
From a design standpoint, dark mode introduces constraints that force better decision-making. You cannot rely on subtle gray borders or faint drop shadows the same way you would on a white background. Every element needs to earn its place and remain legible against a dark surface. The result, when done well, is an interface that feels intentional and polished.
Getting colors right
The most common mistake is reaching for pure black (#000000) as the background. It seems logical — the opposite of white — but pure black creates harsh contrast that fatigues eyes over extended reading. Google’s Material Design guidelines recommend dark gray tones in the #121212 to #1E1E1E range, and our experience backs that up.
Accent colors need their saturation brought down. An electric blue that looks sharp on a white background can feel aggressive and glaring against dark surfaces. We typically reduce saturation by 15–25% and increase lightness slightly for dark mode variants. On a recent e-learning project, we built a dedicated color token system where every accent had both a light-mode and dark-mode value, wired through CSS custom properties. It added a day of setup and saved hours of debugging later.
Elevation works differently in dark mode too. In light mode, shadows convey depth. In dark mode, shadows disappear into the background — so you build depth through progressively lighter surface colors instead. A card might sit at #1E1E1E on a #121212 base, with a modal stepping up to #2C2C2C. The layering is subtle but effective.
Typography on dark surfaces
Light text on a dark surface tends to appear slightly bolder than identical text on white — an optical effect called halation. If your light-mode body text is weight 400, you may need to drop to 350 or tighten letter spacing slightly in dark mode to preserve the same visual weight. It is a small adjustment, but readers notice the difference even if they cannot name it.
Pure white (#FFFFFF) text creates the same harsh contrast problem as pure black backgrounds. We use #E0E0E0 for body text and reserve full white for headings or high-emphasis elements. That step down builds a quiet hierarchy without straining the reader.
Testing properly
A quick toggle is not a test. We build a checklist for every project: every page state, including empty states, error states, and loading skeletons. Form elements — inputs, dropdowns, checkboxes — need specific attention because they often inherit browser defaults that work fine in light mode and fall apart in dark.
Device testing matters more than most teams expect. An OLED display renders dark mode differently from an IPS LCD because OLED pixels turn off entirely for true blacks, creating sharper contrast at boundaries. During a photography portfolio project, images that looked great on our calibrated monitors appeared washed out on the client’s AMOLED phone. The surrounding darkness was shifting perceived image brightness. We would have missed that in a browser toggle test.
Automated visual regression testing tools like Percy or Chromatic can catch unexpected dark-mode regressions when you push updates. We integrate these into our CI pipeline so that every pull request generates comparison screenshots for both modes.
Do not let the light theme drift
Once a team starts investing in dark mode, the light theme sometimes gets neglected. Both modes deserve equal attention. We treat them as two expressions of the same design system, not a primary with a secondary variant.
The toggle between modes should feel seamless — layout, spacing, and content hierarchy stay identical, only surface colors and text tones shift. If toggling feels like landing on a different site, something is broken.
Respecting user preference
Use the prefers-color-scheme media query to respect the system default, but always provide a manual toggle. Some users prefer dark mode everywhere except specific sites, and giving that control is a small thing that builds genuine trust.
Store the preference in a cookie or local storage so it persists across sessions. The white flash that happens when a user returns to a dark-mode site before JavaScript loads is one of the most reliably frustrating experiences in web design. For server-rendered sites, a cookie-based approach loads the correct theme on first paint, eliminating the flash entirely. It is worth the extra implementation step.
Dark mode is not a toggle feature. It is a design system constraint that, when taken seriously, produces better interfaces in both modes.