The Problem
After implementing a dark/light theme switcher in our Astro blog, we encountered a critical visibility issue in light theme. The “View All” button and several UI elements became nearly invisible due to poor color contrast. This affected user experience significantly, especially for users who prefer light themes.

The specific problems were:
- “View All” buttons had text that was nearly invisible against the button background
- Sidebar labels (“Categories”, “Tags”) were too light to read
- Theme toggle button icon was barely visible
- Tag badges had poor contrast against their backgrounds
Root Cause Analysis
The issue stemmed from our CSS variable configuration using the OKLCH color space. Here’s what went wrong:
/* Original problematic configuration */:root { --on-primary: oklch(0.23 0.084 var(--hue)); /* Dark color */ --btn-regular-bg: oklch(0.23 0.084 var(--hue)); /* Same dark color! */}The --on-primary variable was being used for both:
- General text color (which should be dark in light theme)
- Button text color (which needed to be light against dark button backgrounds)
This dual usage created a conflict where fixing one use case broke the other.
The Solution
We implemented a comprehensive fix by separating concerns and creating dedicated CSS variables:
1. CSS Variable Refinement
:root { /* Text Colors */ --primary: oklch(0.7 0.14 var(--hue)); --on-primary: oklch(0.23 0.084 var(--hue)); /* Keep dark for general text */ --primary-hover: oklch(0.75 0.14 var(--hue));
/* New dedicated variables */ --btn-text: oklch(0.98 0.008 var(--hue)); /* Light color for button text */ --text-muted: oklch(0.5 0.08 var(--hue)); /* Medium contrast for secondary text */}2. Button Style Updates
.btn-regular { background: var(--btn-regular-bg); color: var(--btn-text); /* Use dedicated button text color */ @apply px-4 py-2 rounded-lg font-medium transition-colors duration-200;}3. Component-Level Adjustments
We fine-tuned individual components for better contrast:
<style> .nav-title { @apply text-lg font-semibold mb-4 text-gray-700 dark:text-gray-200; /* Changed from text-gray-800 to text-gray-700 for better visibility */ }</style>className = 'text-gray-600 dark:text-gray-400 ...'// Changed from text-gray-500 to text-gray-600<!-- TopicList.astro -->class:list={ [ // Added explicit text colors for non-selected topics { 'bg-gray-100 dark:bg-gray-800 text-gray-700 dark:text-gray-300': selectedTopic !== normalizedName, }, ]}Understanding OKLCH Color Space
OKLCH is a perceptually uniform color space that makes it easier to create consistent color systems. The format is:
oklch(lightness chroma hue)- Lightness (0-1): 0 is black, 1 is white
- Chroma (0-0.4+): Color intensity/saturation
- Hue (0-360): Color angle on the color wheel
Why OKLCH for Theme Switching?
- Predictable Lightness: Unlike HSL, OKLCH maintains perceptual lightness across different hues
- Consistent Contrast: Easier to maintain WCAG contrast ratios
- Smooth Transitions: Better color interpolation for animations
Lessons Learned
1. Separate Concerns in CSS Variables
Don’t use the same color variable for different UI contexts. Create specific variables for:
- Button text vs body text
- Interactive elements vs static content
- Primary actions vs secondary information
2. Test Both Themes Thoroughly
Always test UI changes in both light and dark themes. What works in one theme might break in another.
3. Use Semantic Color Names
Instead of generic names like --text-color, use context-specific names:
--btn-text--nav-label--card-title
4. Maintain Contrast Ratios
Ensure all text meets WCAG AA standards:
- Normal text: 4.5:1 contrast ratio
- Large text: 3:1 contrast ratio
- Use tools like WebAIM’s contrast checker
Implementation Checklist
When implementing theme switching, follow this checklist:
- Define separate CSS variables for different text contexts
- Test all interactive elements in both themes
- Verify contrast ratios meet accessibility standards
- Document color system decisions
- Create visual regression tests for theme changes
Conclusion
Theme switching is more complex than just inverting colors. It requires a thoughtful approach to color system design, considering how each variable is used across different contexts. By separating concerns and using semantic variable names, we created a robust theme system that works beautifully in both light and dark modes.
The OKLCH color space proved invaluable for maintaining consistent perceptual lightness and contrast across our theme variations. This fix not only resolved our immediate visibility issues but also established a more maintainable color system for future development.
