Dark Mode vs Light Mode: Design Systems for Code Editors
The dark mode versus light mode debate is a false dichotomy. Picking one theme and sticking with it forever ignores how your eyes, environment, and tasks actually work. The real answer is adaptive theming: an editor design system that shifts its contrast, saturation, and color palette based on context.
A 2023 survey by JetBrains found that 82% of developers prefer dark themes, but 93% of those same developers admitted they occasionally switch to a light theme depending on lighting conditions. That is not indecision. It is a signal that one theme cannot cover every scenario.

Dark Mode vs Light Mode: Design Systems for Code Editors.
This is not about aesthetics. It is about cognitive load, accessibility, and productivity. And the best part? You do not need to wait for IDE vendors to build it. You can do it today in both VS Code and Neovim.
The Problem with Picking a Side
Dark mode advocates are not wrong—they are just context-blind.
A dark theme genuinely helps in low-light conditions, reduces glare, and saves battery on OLED screens. That is why every developer tool defaults to it. But the same theme that makes code pop at midnight washes out syntax highlighting at noon and turns into a reflective mess near a window.
Research on visual fatigue shows that prolonged exposure to high-contrast dark mode can increase eye strain for people with astigmatism—a condition affecting roughly 33% of the population. The halation effect (blurred edges around bright text on dark backgrounds) forces the eyes to work harder to focus. Light mode avoids this but introduces its own problems: harsh brightness in dark rooms and lower perceived contrast for certain color pairs.
Light mode has its strengths: superior contrast for complex syntax, better readability in bright environments, and easier prolonged reading for people with vision conditions like astigmatism or presbyopia. But it is punishing in a dark room and feels sterile after hours of deep work.
The problem is not which theme is “better.” It is that one theme cannot adapt to all conditions, and choosing a side means accepting those trade-offs permanently.
What Adaptive Theming Actually Means
Most developers stop at “dark theme during the day, light theme at night” reversal. That is a start, but it is not a design system.
A proper editor design system adjusts to three variables:
- Time of day: Your eyes adapt to ambient light. A theme that works at 2 PM will not work at 2 AM. Circadian rhythm affects color perception—warm tones at night reduce melatonin suppression, while cool blue light in the morning supports alertness.
- Task type: Reading documentation needs different contrast ratios than writing new code. Debugging needs different color cues than refactoring. A diff view should not use the same palette as your main editor.
- Environment: The same theme looks completely different on a laptop display versus an external monitor versus a projector. A theme calibrated on a MacBook Pro’s XDR display will look muddy on a budget external panel.
Adaptive theming takes automatic theme switching further. Instead of just flipping between two color schemes, the editor adjusts the entire visual system—contrast curve, saturation levels, syntax highlight palette, even UI chrome opacity—based on context.
Adaptive Theming in VS Code
VS Code has excellent extension support for theme switching. The approach breaks down into three layers:
Layer 1: Time-Based Switching
The simplest layer uses extensions like Theme Switcher or Auto Theme to rotate themes at set hours. I covered the basics previously, but here is a refined configuration:
{
"auto-theme.timezone": 3,
"auto-theme.toggleDarkTheme": "Night Owl",
"auto-theme.toggleLightTheme": "Night Owl Light",
"auto-theme.schedule": [
{ "startTime": "06:00", "endTime": "12:00", "theme": "Night Owl Light" },
{ "startTime": "12:00", "endTime": "18:00", "theme": "Cobalt2" },
{ "startTime": "18:00", "endTime": "06:00", "theme": "Night Owl" },
],
}
Layer 2: Per-Language and Per-Task Theming
VS Code supports per-language theme overrides via
editor.semanticTokenColorCustomizations and workbench.colorCustomizations.
You can fine-tune syntax colors for specific languages without switching themes
entirely:
{
"editor.semanticTokenColorCustomizations": {
"[Night Owl]": {
"enabled": true,
"rules": {
"*.declaration.readonly": { "foreground": "#82aaff" },
"parameter": { "foreground": "#c792ea" },
},
},
},
"workbench.colorCustomizations": {
"[Night Owl Light]": {
"sideBar.foreground": "#000000",
"editor.background": "#fafafa",
"sideBar.background": "#f0f0f0",
},
},
}
For task-based theming, you can bind theme switching to keyboard shortcuts and use VS Code’s profiles feature to switch between “writing mode,” “debugging mode,” and “reading mode” with different chrome densities and color treatments:
{
"key": "ctrl+shift+1",
"command": "workbench.action.switchToProfile",
"args": "Writing"
},
{
"key": "ctrl+shift+2",
"command": "workbench.action.switchToProfile",
"args": "Debugging"
},
{
"key": "ctrl+shift+3",
"command": "workbench.action.switchToProfile",
"args": "Reading"
}
Layer 3: Ambient Adaptation
For true adaptive theming, you can combine VS Code’s window.autoDetectColorScheme with OS-level automation. On macOS, Night Shift and Shortcuts can trigger theme changes. On Windows, Power Automate or AutoHotkey scripts can switch themes based on sunrise and sunset.
{
"window.autoDetectColorScheme": true,
"workbench.preferredLightColorTheme": "Night Owl Light",
"workbench.preferredDarkColorTheme": "Night Owl",
"workbench.preferredHighContrastColorTheme": "Night Owl High Contrast",
}
When paired with Windows 11’s dynamic lighting and macOS’s built-in automatic theme switching, this gives you a four-state system: light → dark → high contrast → light, following your OS settings without manual intervention.
Adaptive Theming in Neovim
Neovim offers even finer control because everything is configurable in Lua. You can build an adaptive system that responds to time, file type, and even ambient light data from your system.
Time-Based Switching
Using Lua, you can schedule theme changes with a simple timer:
local function set_theme_by_hour()
local hour = tonumber(os.date("%H"))
if hour >= 6 and hour < 12 then
vim.cmd("colorscheme night-owl-light")
elseif hour >= 12 and hour < 18 then
vim.cmd("colorscheme cobalt2")
else
vim.cmd("colorscheme night-owl")
end
end
-- Run on startup
set_theme_by_hour()
-- Re-check every 10 minutes
vim.loop.new_timer():start(600000, 600000, vim.schedule_wrap(set_theme_by_hour))
Per-Filetype and Per-Task Theming
Neovim’s FileType and BufEnter autocommands let you theme per context.
Disable syntax highlighting in large log files. Use a high-contrast scheme for
diffs. Switch to a minimal prose theme in Markdown:
vim.api.nvim_create_augroup("AdaptiveTheming", { clear = true })
-- Minimal theme for writing
vim.api.nvim_create_autocmd("FileType", {
group = "AdaptiveTheming",
pattern = { "markdown", "text", "tex" },
callback = function()
vim.cmd("colorscheme rose-pine-dawn")
vim.opt.background = "light"
end,
})
-- High contrast for diff
vim.api.nvim_create_autocmd("FileType", {
group = "AdaptiveTheming",
pattern = { "diff", "gitcommit" },
callback = function()
vim.cmd("colorscheme gruvbox-material")
vim.opt.background = "dark"
end,
})
-- Dim non-focus windows
vim.api.nvim_create_autocmd("WinEnter", {
group = "AdaptiveTheming",
callback = function()
vim.opt.winhighlight = "Normal:NormalFloat"
end,
})
vim.api.nvim_create_autocmd("WinLeave", {
group = "AdaptiveTheming",
callback = function()
vim.opt.winhighlight = "Normal:DimWindow"
end,
})
Ambient Light Integration
For the full adaptive experience, you can integrate with system light sensors.
On macOS, you can read the ambient light level via pmset -g raw. On Linux,
acpi -V or the illuminated package provides sensor data. Here is a Neovim
plugin module that polls ambient brightness:
local function get_ambient_brightness()
local handle = io.popen("pmset -g raw 2>/dev/null | grep 'Ambient' | awk '{print $3}'")
if handle then
local result = handle:read("*a"):gsub("%s+", "")
handle:close()
return tonumber(result) or 50
end
return 50
end
local function adaptive_theme()
local brightness = get_ambient_brightness()
-- Assume 0–100 range, lower = darker room
if brightness < 30 then
vim.cmd("colorscheme tokyonight-storm")
vim.opt.background = "dark"
elseif brightness < 60 then
vim.cmd("colorscheme night-owl")
vim.opt.background = "dark"
else
vim.cmd("colorscheme kanagawa-lotus")
vim.opt.background = "light"
end
end
-- Check every 5 minutes
vim.loop.new_timer():start(300000, 300000, vim.schedule_wrap(adaptive_theme))
Plugin-Based Approach
If you prefer a plugin-based setup, these plugins handle most of the work:
- tokyonight.nvim — ships with a
built-in
config.stylethat can be set dynamically based on time. - catppuccin — exposes
vim.g.catppuccin_flavourthat you can toggle betweenlatte,frappe,macchiato, andmochabased on your schedule. - auto-dark-mode.nvim — syncs Neovim’s theme with your OS dark/light mode automatically.
- nightfox.nvim — includes
dayfox,dawnfox,duskfox, andnightfoxvariants designed for different times of day.
Here is a minimal auto-dark-mode setup:
require("auto-dark-mode").setup({
update_interval = 60000,
set_dark_mode = function()
vim.cmd("colorscheme tokyonight")
vim.opt.background = "dark"
end,
set_light_mode = function()
vim.cmd("colorscheme kanagawa-lotus")
vim.opt.background = "light"
end,
})
Accessibility Is Not Optional
Most popular themes fail basic accessibility checks. This is not a side issue—it directly affects whether your editor is usable by everyone on your team.
- Contrast ratios: WCAG AA (4.5:1 for normal text, 3:1 for large text) should be the minimum. According to a 2024 audit of the 50 most popular VS Code themes on the marketplace, 34% failed WCAG AA for at least one common color pair (comments vs. background, strings vs. keywords).
- Color blindness: Red-green syntax highlighting excludes roughly 8% of male developers. It is still the default in most editors. Tools like Colorblindly (VS Code) can simulate color vision deficiency directly in the editor.
- Astigmatism and dark mode: As mentioned earlier, dark mode worsens the halation effect for people with astigmatism. Forcing one theme on everyone is not inclusive.
An adaptive system solves this by giving users per-context themes rather than one compromise. A developer with astigmatism can use a warm light theme for prose writing and a medium-contrast dark theme for focused coding, switching based on task rather than lighting.
Practical Tooling
- VS Code: Use the Accessibility Checker to audit your custom themes against WCAG standards.
- Neovim: Plugins like nvim-a11y or lush.nvim with contrast-checking helpers let you validate your color palette in real time.
- General: Tools like Lea Verou’s Contrast Ratio, Sim Daltonism (macOS), and Colour Contrast Checker help you evaluate any color pair before committing it to a theme.
A Practical Daily Setup
Here is what the full adaptive system looks like in practice across both editors:
| Time | Condition | VS Code | Neovim | Visual Goal |
|---|---|---|---|---|
| 06:00 – 09:00 | Morning, bright room | Night Owl Light + warm sidebar | kanagawa-lotus | Warm undertones, low contrast |
| 09:00 – 12:00 | Peak daylight | Cobalt2 | tokyonight-day | Neutral, medium contrast |
| 12:00 – 14:00 | Lunch, variable light | Auto theme via OS | auto-dark-mode sync | System-following |
| 14:00 – 18:00 | Afternoon grind | Night Owl | nightfox | High contrast, focused |
| 18:00 – 22:00 | Evening, winding down | In Bed by 7pm | duskfox | Reduced blue light, warmer |
| 22:00 – 06:00 | Night coding | Night Owl | tokyonight-storm | Minimal blue light, high contrast |
The specifics matter less than the principle: your visual system changes throughout the day, and your tools should adapt to you.
The Bottom Line
Stop treating theme choice as a religious identity. Build a system that adapts to your day, your task, and your environment. Whether you use VS Code with three extensions or Neovim with a 30-line Lua module, the principle is the same: your tools should meet you where you are, not force you to meet them.
Your code will not care what color your background is. Your eyes will.

