Difficulty: Intermediate
How do you implement print styles and dark mode in CSS?
Print styles optimize pages for printing. Dark mode adapts to user's OS theme preference.
Print styles: - Use @media print { } to add print-specific rules - Hide navigation, footers, ads - Use black text on white background - Set page margins with @page - Force background printing with print-color-adjust
Dark mode: - prefers-color-scheme: dark media query (OS preference) - Class-based toggle (.dark) for manual control - CSS custom properties for theme values - color-scheme meta tag for native form styling
@media print {
/* Hide non-essential elements */
nav, footer, .sidebar, .ads,
.no-print, button {
display: none !important;
}
/* Reset colors for print */
body {
color: black;
background: white;
font-size: 12pt;
line-height: 1.5;
}
/* Show link URLs */
a[href]::after {
content: ' (' attr(href) ')';
font-size: 0.8em;
color: #666;
}
a[href^="#"]::after,
a[href^="javascript:"]::after {
content: ''; /* skip internal/JS links */
}
/* Page settings */
@page {
margin: 2cm;
size: A4;
}
/* Avoid breaking inside elements */
h2, h3, img, table {
break-inside: avoid;
}
h2, h3 {
break-after: avoid;
}
/* Force background printing */
.badge {
print-color-adjust: exact;
-webkit-print-color-adjust: exact;
}
}
Print styles remove UI elements, optimize for paper, and show link URLs. break-inside: avoid prevents awkward page breaks in the middle of elements.
/* Define theme tokens */
:root {
color-scheme: light dark;
/* Tells browser to style native controls */
--bg: #ffffff;
--bg-surface: #f9fafb;
--text: #111827;
--text-muted: #6b7280;
--border: #e5e7eb;
--shadow: 0 1px 3px rgb(0 0 0 / 0.1);
}
/* OS preference: auto dark mode */
@media (prefers-color-scheme: dark) {
:root {
--bg: #0f172a;
--bg-surface: #1e293b;
--text: #f1f5f9;
--text-muted: #94a3b8;
--border: #334155;
--shadow: 0 1px 3px rgb(0 0 0 / 0.4);
}
}
/* Manual toggle: class on html element */
html.dark {
--bg: #0f172a;
--bg-surface: #1e293b;
--text: #f1f5f9;
--text-muted: #94a3b8;
--border: #334155;
--shadow: 0 1px 3px rgb(0 0 0 / 0.4);
}
/* Apply tokens everywhere */
body {
background: var(--bg);
color: var(--text);
}
.card {
background: var(--bg-surface);
border: 1px solid var(--border);
}
CSS variables make dark mode trivial - change the variable values and every component updates. color-scheme tells the browser to style checkboxes, scrollbars, etc.
<!-- Meta tag for native control styling -->
<meta name="color-scheme" content="light dark" />
<script>
// Check stored preference, then OS preference
function getTheme() {
const stored = localStorage.getItem('theme');
if (stored) return stored;
return window.matchMedia(
'(prefers-color-scheme: dark)'
).matches ? 'dark' : 'light';
}
// Apply theme
function setTheme(theme) {
document.documentElement.classList
.toggle('dark', theme === 'dark');
localStorage.setItem('theme', theme);
}
// Initialize
setTheme(getTheme());
// Toggle button
document.getElementById('themeToggle')
.addEventListener('click', () => {
const current = document.documentElement
.classList.contains('dark') ? 'light' : 'dark';
setTheme(current);
});
// Listen for OS changes
window.matchMedia('(prefers-color-scheme: dark)')
.addEventListener('change', (e) => {
if (!localStorage.getItem('theme')) {
setTheme(e.matches ? 'dark' : 'light');
}
});
</script>
<style>
/* Smooth theme transition */
html {
transition: background 0.3s ease, color 0.3s ease;
}
</style>
The three-tier approach: 1) check localStorage for user preference, 2) fall back to OS preference, 3) default to light. Listen for OS changes too.
Print Styles, Dark Mode, prefers-color-scheme, Color Scheme, Accessibility