Colour contrast for text, buttons and icons
Text that is too faint is hard to read for many people. This guide explains how the contrast ratio is calculated, which values WCAG sets for text, buttons and icons, and how you adjust your brand colours without losing your brand.
Why contrast matters
Pale text costs readers. People with low vision, older readers and anyone who looks at a phone in bright light all need a clear difference between text and background. The Web Content Accessibility Guidelines (WCAG) of the W3C therefore set minimum values for text, for controls such as buttons and input fields, and for icons and graphics. They can be measured and checked before launch.
How the contrast ratio works
The contrast ratio compares how bright two colours are. WCAG does not look at the hue but at the relative luminance: a value between 0 for the darkest black and 1 for the lightest white. The three channels red, green and blue are converted and weighted: green counts most, red less and blue least. The ratio is (L1 + 0.05) / (L2 + 0.05), where L1 is the luminance of the lighter colour. The result lies between 1:1 for two equal colours and 21:1 for black on white.
Two rules from the W3C matter in practice. First, the values are not rounded: a ratio of 4.499:1 does not meet the limit of 4.5:1. Second, contrast is measured against the background that is set for the text. If a page sets only a text colour and no background colour, the W3C counts that as a failure, because the default background of the visitor is unknown. Always set both colours together.
The three success criteria
- 1.4.3 Contrast (Minimum), level AA: text and images of text need at least 4.5:1, large text at least 3:1.
- 1.4.6 Contrast (Enhanced), level AAA: text needs at least 7:1, large text at least 4.5:1. It is the stricter level and helps most with long texts.
- 1.4.11 Non-text Contrast, level AA: at least 3:1 against the colours next to it, for everything you need to see to recognise a control and its state (for example the border of an input or a focus indicator) and for the parts of graphics you need to understand the content, such as icons or lines in a chart.
What counts as large text
Large text is at least 18 point, or at least 14 point in bold. The W3C converts this to about 24 pixels and about 18.5 pixels in bold. Large text may have less contrast because the letters are bigger and their strokes wider. Be careful with thin fonts: according to the W3C, anti-aliasing can make thin or unusual fonts look fainter than their defined colour. It recommends thicker fonts or a colour pair clearly above the minimum.
What does not need to pass
- Inactive components, such as a disabled button.
- Pure decoration and text that nobody can see.
- Text that is part of a logo or brand name.
- Incidental text in a picture with significant other content, such as a street sign in a photo.
Common mistakes
- Light grey on white. Grey for dates, captions or secondary text is often too pale: #999999 on white reaches only 2.84:1. The lightest pure grey that passes AA for normal text on white is #767676 with 4.54:1.
- Text on images. The contrast changes with every part of the photo. The W3C lists background images without enough contrast as a failure (F83). Put the text on a solid area, darken the image behind it or place the text next to the image. Check the lightest spot behind the text.
- Placeholder text. The grey hint in an empty input field is text, and 1.4.3 applies to it. A light grey such as #9ca3af on white reaches only 2.53:1. A placeholder is also no replacement for a visible label.
- Hover and focus states. Text that appears or changes on mouse hover or keyboard focus must meet the same values. A hover effect must not lower the contrast of a control or weaken the focus indicator. A focus indicator you design yourself needs 3:1 against the background next to it.
- White text on bright brand colours. Orange, yellow, light green or turquoise buttons with white text often fail: white on #ff6600 reaches 2.93:1.
- Pale borders and icons. If the border is the only thing that shows where an input field is, it needs 3:1: #cccccc on white has 1.60:1. Icons that carry meaning without text, such as a dropdown arrow or a close icon, also need 3:1.
- Checking only one theme. If your site has a dark mode, check its colour pairs separately. A colour that works on white can fail on a dark background.
Fix a brand palette without losing the brand
- 1Write down every colour with its role: text, background, accent or button, border. Many problems start when one colour does every job.
- 2Keep the brand colour where the rules are easier to meet or do not apply: in the logo, on large areas, for decoration and for large headings.
- 3For text and small elements, use a darker or lighter shade of the same hue. If only the lightness changes, the colour stays recognisable: white text on #c74f00, a darker orange, reaches 4.61:1.
- 4Or change the text colour instead. Dark text on a bright brand colour often works better than white: #1a1a1a on #ff6600 reaches 5.92:1.
- 5Define one grey for secondary text that passes, for example #767676 on white, and use it everywhere instead of several pale greys.
- 6Check every state: normal, hover, focus, error and dark mode. Save the final colours as variables in your style sheet, so that nobody picks a pale colour by hand again.
- White text on #ff6600: 2.93:1, fails AA
- Secondary text #999999: 2.84:1
- Placeholder #9ca3af: 2.53:1
- Input border #cccccc: 1.60:1
- White text on #c74f00: 4.61:1, passes AA
- Secondary text #767676: 4.54:1
- Placeholder #6b7280: 4.83:1
- Input border #949494: 3.03:1
Check your colours with Do4U
The Colour contrast check computes these values for your own colours. You enter your colours, one per line, and give each one a role: text, background, accent (for example a button) or border. The code checks every sensible pair against AA and AAA for normal and large text and against 3:1 for borders, icons and button areas, without rounding up. For each pair that fails, you get the nearest colour that passes, once darker and once lighter, in the same hue. Do4U also builds an adjusted palette, checks it again as a whole and exports it as CSS custom properties, SCSS or JSON. Everything runs in code, without AI, and the check is free.
The check only knows the colour pairs you enter. It cannot see font sizes, images behind text, transparency or hover and focus states, so test the finished pages as well. Do4U builds the draft, you check and decide.
Sources
- W3C: Understanding SC 1.4.3 Contrast (Minimum) (page updated 6 September 2026) (www.w3.org)
- W3C: Understanding SC 1.4.6 Contrast (Enhanced) (page updated 6 September 2026) (www.w3.org)
- W3C: Understanding SC 1.4.11 Non-text Contrast (page updated 6 September 2026) (www.w3.org)
- W3C: Web Content Accessibility Guidelines (WCAG) 2.2, Recommendation of 12 December 2024 (definitions of contrast ratio and relative luminance) (www.w3.org)