Dark Mode vs Light Mode: Design Systems for Code Editors

8 min read · 1698 words

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.

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.style that can be set dynamically based on time.
  • catppuccin — exposes vim.g.catppuccin_flavour that you can toggle between latte, frappe, macchiato, and mocha based on your schedule.
  • auto-dark-mode.nvim — syncs Neovim’s theme with your OS dark/light mode automatically.
  • nightfox.nvim — includes dayfox, dawnfox, duskfox, and nightfox variants 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

A Practical Daily Setup

Here is what the full adaptive system looks like in practice across both editors:

TimeConditionVS CodeNeovimVisual Goal
06:00 – 09:00Morning, bright roomNight Owl Light + warm sidebarkanagawa-lotusWarm undertones, low contrast
09:00 – 12:00Peak daylightCobalt2tokyonight-dayNeutral, medium contrast
12:00 – 14:00Lunch, variable lightAuto theme via OSauto-dark-mode syncSystem-following
14:00 – 18:00Afternoon grindNight OwlnightfoxHigh contrast, focused
18:00 – 22:00Evening, winding downIn Bed by 7pmduskfoxReduced blue light, warmer
22:00 – 06:00Night codingNight Owltokyonight-stormMinimal 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.

Val Paliy avatar
Web creator, developer, and project manager with over 20 years of experience. Writing about programming, technology, and modern web standards.