Accessible color palette generator

An accessible color palette is a set of colors that reach WCAG 2.2 contrast when you pair them: 4.5:1 for normal text, 3:1 for large text and UI components. This tool builds a 50 to 950 scale for up to five colors, suggests companion colors from your first one, measures every pair and finds the nearest shade that passes.

Published . Last reviewed .

Free · No signup · Runs entirely in your browser. The colors you enter are never uploaded

1. Your brand colors

Enter one to five colors as hex, rgb(), hsl() or a CSS color name, or pick them with the color picker. A name is optional; it becomes the name of the color in the exports. No brand colors yet? Choose color 1 and ask for companion colors below.

Brand color 1

Hex such as #2F80ED; rgb(), hsl() and color names work too. A solid color: no transparency.

Brand color 2

Hex such as #2F80ED; rgb(), hsl() and color names work too. A solid color: no transparency.

Brand color 3

Hex such as #2F80ED; rgb(), hsl() and color names work too. A solid color: no transparency.

Suggest companion colors from color 1

Replaces colors 2 and up with as many as three suggestions built on color 1. Each reaches 4.5:1 on your light background, and the neutral reaches 7:1. A starting point, not a finished palette, and you can undo it.

The color behind your text on a light page or card. White is the default; type your own, such as an off-white, and every ratio, suggestion and export follows it.

The background for dark mode, a dark footer or a dark banner.

2. Shade scales

Each color is kept exactly as you entered it, at the step closest to its lightness, and marked "your color". The other steps change only lightness and chroma. Under each hex is its contrast ratio on your light background (white unless you changed it) and on your dark background, with the level it reaches.

Blue

Coral

Yellow

3. Contrast matrix

Every text and background pair, with the exact ratio and the level it reaches. Each row is a text color and each column is a background; the "Aa" shows the pair. Your light and dark backgrounds come first in every matrix.

Which matrix to show

What the label in each matrix cell means
LabelRatioWhat it passes
AAA7:1 or moreAAA normal text (7:1), AA normal text (4.5:1), AA large text and UI components (3:1)
AA4.5:1 up to 7:1AA normal text and AA large text and UI components; not AAA normal text
Large only3:1 up to 4.5:1AA large text and UI components only
FailUnder 3:1None of the three

Pairs that reach 4.5:1

    4. Nearest shade that passes

    For each color, the smallest change in lightness that reaches 4.5:1 on your light background and on your dark background. Hue and chroma are kept wherever sRGB can show them, and every candidate is rounded to a real hex color before it is measured, so the ratio you see is the ratio you get.

    One color rarely serves both backgrounds. With the default backgrounds, 4.5:1 on white needs a relative luminance of 0.183 or less and 4.5:1 on #111111 needs 0.200 or more, so no color reaches it on both. Use a darker step on light backgrounds and a lighter step on dark ones; applying one suggestion usually means the other card then asks for a change.

      5. Export

      Names come from the name fields; a blank name becomes color-1, color-2 and so on. Colors are written as lowercase hex. Each color also gets on-light and on-dark: its nearest shade that reaches 4.5:1 on your light and on your dark background (the color itself when it already does), ready to use as text. The download buttons save the box as a file from your own browser; nothing is requested from a server.

      How to use the palette

      Choose each shade by the job it does, because WCAG sets a different minimum for each one. The matrix gives the exact ratio for every pair, so the choice is a lookup rather than a guess.

      Where each kind of color has to land, at WCAG Level AA
      UseMinimum ratioCriterionMatrix label
      Normal text4.5:11.4.3 Contrast (Minimum)AA or AAA
      Large text: at least 18 point, or 14 point bold3:11.4.3 Contrast (Minimum)Large only, AA or AAA
      User interface components and the parts of graphics needed to understand them3:1 against adjacent colors1.4.11 Non-text ContrastLarge only, AA or AAA
      Logo text, text in a disabled control, pure decorationNo minimum1.4.3 and 1.4.11Any

      W3C puts 18 point and 14 point at about 24px and 18.5px in CSS pixels. Our WCAG reference lists both criteria (1.4.3 and 1.4.11), and the color contrast guide covers the ratios, the formula and the common mistakes in full.

      • Starting from nothing. Enter or pick color 1, choose a harmony, and press "Suggest companion colors". You get up to three more colors that already reach 4.5:1 on your light background, to adjust from there.
      • Text on your light background. In a scale's matrix, read down the White column (it is called Light when you set another color) and choose a text shade labeled AA or AAA. The cards under "Nearest shade that passes" name the closest one for each of your colors, and the on-light colors in the exports hold the same answer.
      • Text on your dark background. The same, using the Dark column and the on-dark colors.
      • One brand color on another. Choose "All your colors together" and read the row of the text color against the column of the background color.
      • Buttons. The label needs 4.5:1 against the button's fill, or 3:1 if it is large text. W3C says a control with a visible text label does not need a contrasting border or fill to meet 1.4.11, so the 3:1 applies where the fill or border is what identifies the control, such as an icon-only button or the outline of a text field. A focus indicator you style yourself needs 3:1 against the colors next to it.
      • Decoration. Graphics that are purely decorative have no minimum, so a pale step can still be used for backgrounds and dividers. Do not use color as the only way to show something: 1.4.1 Use of Color asks for a second cue.

      Why brand colors often fail on white

      Low contrast text is the most common error WebAIM's February 2026 report finds: low contrast text on 83.9% of home pages, more than any of the other five categories that make up 96% of the errors it detects. Part of the reason is arithmetic. WCAG defines the ratio as (L1 + 0.05) / (L2 + 0.05), where L is relative luminance and L1 is the lighter color (WCAG 2.2 definitions). White has a luminance of 1, so a color passes 4.5:1 on white only if its luminance is at most 1.05 / 4.5 minus 0.05, which is 0.183. For 3:1 the limit is 0.30 and for 7:1 it is 0.10. Mid-tone colors sit above those limits: mid-gray #808080 is 3.94:1 on white.

      The three colors this page opens with show how far a vivid color can sit from the line. On white, Blue #2F80ED measures 3.86:1, Coral #FF6B57 measures 2.80:1 and Yellow #FFC933 measures 1.53:1. The nearest colors of the same hue that reach 4.5:1 are #2274E0 (4.52:1), #D44332 (4.51:1) and #947100 (4.54:1), which move the colors' OKLCH lightness by 0.04, 0.12 and 0.29. The further a color starts from the line, the less the passing version looks like it.

      There are two ways to keep the brand color. Use the exact color where the minimum is lower or absent: as large text, as a UI component or graphic edge at 3:1, or as decoration. And use a darker step of the same hue for small text. Text that is part of a logo or brand name has no contrast requirement under 1.4.3, so a logo can keep the exact color.

      How it works

      The color space

      The scales are built in OKLCH, the polar form of the OKLab color space by Björn Ottosson (his description and code). OKLCH has three numbers: L is lightness from 0 (black) to 1 (white), C is chroma (how colorful), and H is hue as an angle in degrees. CSS Color Module Level 4 (section 9) describes OKLab as having better hue linearity, hue uniformity and chroma uniformity than CIE LCH, which suits a scale that changes lightness and holds hue. The conversions are the ones in that specification's sample code (section 19): sRGB to linear light, to XYZ with a D65 white point, to LMS, a cube root, then OKLab and the polar form. A gray has no hue; the specification treats the hue of a color with chroma of 0.000004 or less as powerless, and a gray's scale stays gray.

      The scale

      Your color is kept exactly, at the step whose lightness is closest to its own. Every other step takes the lightness in the table below and your color's hue. Its chroma is your color's chroma times the step's share divided by the share of the step that holds your color, never more than your color's own, and lowered further where sRGB cannot show it. The shares make tints and shades quieter toward white and black.

      The fixed values behind each step of a scale
      StepOKLCH lightness (L)Chroma share
      500.9758%
      1000.94518%
      2000.938%
      3000.8365%
      4000.7488%
      5000.64100%
      6000.54100%
      7000.4494%
      8000.3884%
      9000.370%
      9500.2255%

      Steps 600 and 700 were set from a sweep of every hue in half-degree steps and every chroma from 0 to 0.4 in steps of 0.005, each result rounded to a hex color before it was measured. On pure white, steps 600 to 950 reach 4.5:1 whatever the hue and chroma (the lowest value in the sweep is 4.68:1 at step 600) and steps 700 to 950 reach 7:1 (the lowest is 7.28:1 at step 700). On #111111, steps 50 to 500 reach 4.5:1 (the lowest is 4.73:1 at step 500). The one exception is the step that holds your own color, which is kept exactly as you entered it. These promises hold for white and #111111 only; with other backgrounds, read the matrix.

      Many OKLCH colors are outside what an sRGB screen can show. The specification's gamut mapping (section 14) reduces chroma in OKLCH while keeping lightness and hue, and this tool does the same: it searches for the largest chroma that fits. It leaves out the shortcut in the specification's binary search (14.2.2), which returns the clipped color whenever clipping moves it by less than one just-noticeable difference (0.02), so a color near the edge of sRGB can differ slightly from the one a browser would draw. These values and the ladder above are our own design choices, not a standard.

      The companion colors

      Press "Suggest companion colors" and the tool first moves your color 1 to its nearest shade that reaches 4.5:1 on your light background, using the search described below. That shade's lightness and chroma are the reference. Each companion takes the reference lightness and chroma at color 1's hue turned by an angle from the table, is mapped into sRGB, and is then nudged again, because the same OKLab lightness gives a different WCAG ratio at another hue. The optional neutral keeps color 1's hue at a chroma of 0.015 and is darkened until it reaches 7:1, so it can carry body text. The angles are the usual ones from color theory applied to OKLCH hue. They are our choice and not a standard, and a suggestion reaches the ratio without being a judgment about taste: it may not suit your brand.

      The hue angles behind each harmony
      HarmonyHue turned from color 1Colors added
      Analogous30 degrees either way2
      Complementary180 degrees1
      Triadic120 degrees either way2

      The contrast numbers

      Every ratio comes from the same code as the color contrast checker: the WCAG 2.2 relative luminance and contrast ratio, measured on the 8-bit hex colors you would paste, never on the unrounded OKLCH values. A pair passes when its exact ratio is at or above the threshold. The number shown is cut off at two decimals, never rounded up, because W3C says the computed value should not be rounded: 4.499:1 does not meet 4.5:1 (Understanding 1.4.3).

      The nearest shade that passes

      From your color's own lightness the search moves outward in steps of 0.001, darker and lighter, keeping the OKLCH hue and chroma, and stops at the first candidate whose hex color reaches the target against the background. That is the smallest change in lightness that works, to the nearest 0.001. The card also names the nearest step in your scale that passes, and the same search produces the on-light and on-dark colors in the exports.

      The exports

      The CSS names follow the --color-name-step pattern that Tailwind's theme documentation uses. Tailwind CSS version 4 turns variables declared in an @theme block into utility classes, while the same variables in :root stay ordinary CSS variables, so the theme block is a separate output. The Tailwind-style output is a theme.extend.colors object for a JavaScript config file, which version 4 loads with the @config directive. The JSON follows the Design Tokens Format Module 2025.10 and its color module: a color value is an object with a colorSpace, components from 0 to 1, an alpha and a 6-digit hex fallback. The format recommends the file extensions .tokens and .tokens.json and the media type application/design-tokens+json, which the download button uses. Token names here are lowercase letters, digits and hyphens, which the format allows.

      What this tool can't do

      It measures the colors you give it, as pairs. It does not see your live page, and neither does our site scanner (what we check). To measure the colors a page actually paints, use the accessibility bookmarklet. For text over a photo or a gradient, use the image contrast checker. Limits of this generator in particular:

      • It uses the WCAG 2.2 contrast ratio only. APCA, a different method, gives different numbers and is not included.
      • It does not check images, gradients, shadows, opacity or blend modes. Every pair is two solid colors, and each background is one solid color.
      • It can't tell what counts as large text in your design, which graphics are needed to understand a page, or which controls are disabled or purely decorative. You decide which row of the usage table applies.
      • The same step number is the same OKLCH lightness in every scale (except the step that holds your own color), not the same WCAG ratio. The promises about steps 500, 600 and 700 hold for white and #111111 only. Read the matrix for any other background.
      • Companion colors are hue rotations in a color space, not design judgment. They reach the ratios and may still clash with your brand or with each other.
      • A scale is a starting point. Rounding to 8-bit hex and fitting colors into sRGB move a step's hue and chroma a little from the ideal.
      • Passing contrast says nothing about the rest of a page. Contrast is one requirement among many, and no tool can certify that a site meets WCAG.

      Related tools and guides

      Accessible color palette FAQ

      What is an accessible color palette?

      A set of colors whose text and background pairs reach the WCAG contrast minimums: 4.5:1 for normal text and 3:1 for large text (1.4.3), and 3:1 for user interface components and the parts of graphics needed to understand them (1.4.11). WCAG has no rule for a palette as such; it measures pairs, so a palette is accessible only for the pairs you actually use. Outside the US the same thing is searched as an accessible colour palette, and the rules are identical.

      Does yellow ever pass on white?

      As text, only once it is dark enough to look brown or gold. Pure yellow #FFFF00 is 1.07:1 on white, and this tool's starting yellow #FFC933 is 1.53:1. Keeping the hue and chroma and darkening it, the first yellow to reach 4.5:1 is #947100 at 4.54:1. Yellow works well in the other direction: #FFC933 behind text in #111111 is 12.27:1.

      Which ratio do buttons need?

      The button's label needs 4.5:1 against the button's fill, or 3:1 if it is large text (1.4.3). The button's own edge or fill needs 3:1 against the colors next to it when that is what identifies it as a control (1.4.11). W3C says a control with a visible text label does not need a contrasting border or fill, so a text button can pass without one.

      Does this make my site accessible?

      No. It helps you choose colors that can pass the contrast criteria, and that is one requirement among many. Whether the colors on your pages pass depends on where you use them, so measure the live page with the accessibility bookmarklet and see how to test website accessibility for the rest. No tool can certify that a site meets WCAG.

      Why do two colors at the same step have different contrast?

      Apart from the step that holds your own color, a step has the same OKLCH lightness in every scale, but the WCAG formula weighs red, green and blue differently from OKLab. For example, at OKLCH lightness 0.60 and chroma 0.12, a hue of 150 degrees measures 3.73:1 on white and a hue of 330 degrees measures 4.19:1. The matrix shows the real ratio for each pair.

      Does my logo have to pass?

      No. Text that is part of a logo or brand name has no contrast requirement under 1.4.3. W3C adds that where a logo works as a control, a link for example, a higher-contrast variant or an equivalent control is worth considering, and that low contrast chosen by the author rather than required by brand guidelines is not exempt. Beyond logos, W3C also says that text with insufficient contrast because of corporate identity or brand guidelines is not exempt (Understanding 1.4.3). Brand colors used for body text, button labels or icons are not logos and have to meet the minimum for that use.

      How does the tool choose companion colors?

      It turns the hue of your first color by a fixed angle (30, 120 or 180 degrees, depending on the harmony you pick), keeps the lightness and chroma of that color's nearest shade that reaches 4.5:1 on your light background, and nudges each result until it passes too. The optional neutral is a gray with a trace of your hue that reaches 7:1. The result reaches the ratios, but the tool cannot tell whether the colors look good together, so treat it as a starting point.

      Colors are the part machines are good at

      The part they're bad at is judgment: whether your alt text is true, whether your link text means anything out of context. That's what GotAlt was built for.

      Check if my alt text is actually right

      Colors are one check of many

      The free scan runs 16 rule-based WCAG checks on up to 3 pages of your site: missing alt text, form labels, headings, page language, link text and more. No signup.

      Scan my site for free