A second colour scheme makes small assumptions visible. A grey that looked like supporting text becomes too faint, a shadow stops separating surfaces, and a logo designed for white space develops an obvious rectangle around it. Dark mode asks more of a design than swapping two background colours.
The useful starting point is to describe what each colour does. Text, muted text, page background, raised surface, border and action are roles. Their values can change while the meaning of the interface stays consistent.
Name the role before choosing the value
A variable called “grey-100” describes a position in a palette. A variable called “surface” describes a job. Both can be useful, but components are easier to adapt when their styling refers to the job rather than assuming that the same swatch suits every background.
Begin with a small set of roles and apply them consistently to a representative page. Include a form, navigation, an error, an image and a long passage of text. A collection of attractive colour samples cannot show whether those parts remain distinguishable together.
Use the system preference as a starting point
The prefers-color-scheme media query lets CSS respond to a light or dark preference. This small example changes only the page background and text. It is a starting point for a design, not a complete theme.
:root {
color-scheme: light;
--page: #ffffff;
--text: #171717;
}
@media (prefers-color-scheme: dark) {
:root {
color-scheme: dark;
--page: #171717;
--text: #f5f5f5;
}
}
body {
background: var(--page);
color: var(--text);
}
The separate color-scheme property informs browser-rendered parts such as form controls about the supported scheme. It does not automatically redesign custom component colours, illustrations or every state of a button.
If the product offers an explicit switch, make its choice understandable and allow a return to the system setting. Decide how a saved choice is applied before the first paint so that a dark preference does not produce an avoidable flash of the light page. That is part of implementing the preference, not a reason to hide the control’s meaning behind an unexplained icon.
Check contrast in context
WCAG’s minimum text contrast criterion requires at least 4.5:1 for ordinary text and 3:1 for qualifying large text, with defined exceptions. Check the actual foreground and background pair rather than judging the text colour in isolation.
Measure supporting copy, placeholder text where it conveys information, links, error messages and text on buttons. A heading may look excellent while the explanation beneath it is difficult to read. Review states as well as defaults, especially keyboard focus and selected controls.
Colour should not carry every distinction on its own. Keep a link recognisable, give errors useful words, and make a selected state evident beyond a small hue change. A contrast result is valuable evidence, but it is not a complete assessment of an interface’s accessibility.
Review the whole page in both schemes
Images deserve individual attention. Transparent artwork may work well on both backgrounds, while a dark logo needs a deliberate alternative. Avoid applying a blanket inversion to photographs or brand artwork just to make the surrounding page look consistent.
Spend time reading in each scheme, at different sizes and with the actual content. Check the separation between stacked surfaces and whether a diagram remains legible. A design can satisfy a numeric text check while still feeling visually confusing because too many neighbouring areas share the same tone.
Not every site needs to offer both schemes. This portfolio currently uses a light presentation. The broader lesson still applies: colour choices become easier to maintain when their purpose is explicit, and a change can be checked against the content and controls it is meant to support.