Empowering Color Selection - Enhancing Accessibility and Consistency with HTML Color Names

23 Feb 2024 - Estimated Reading Time: 4 min
Table of content

🌈 Why prioritize HTML Color Names?

Let me share a little story with you!

Choosing colors is a delightful agony for designers and developers.

While functional consultants happily let the choice of choosing semantic colors (πŸ’§ info, 🍏 success, πŸ‹ warning, πŸ”΄ danger) to UI experts, they sometimes request unique colors for badges or pills, not for meaning but simply for aesthetic whims.

That’s why someone, maybe me or another team member, had the bright idea of letting Functional Consultants input any color they fancy by following these simple steps:

Step 1: Type in a color like β€œred”, β€œgreen”, or why not a hex color like “#e9967a”.

Step 2: Behind the scenes, I’ll handle the calculations 1 to ensure “proper contrast” 😝.

Step 3: On the frontend, we’ll pair each color with a combination of ink (white or black) and background (the color from step 1).

This workflow has a big flow like you can guess:

  1. choosing a color in hex format would be difficult to remember

  2. their choice could be one of the following colors if they decide to use html color names:

    Using pure white or black on those color options might not provide enough contrast for optimal readability. We want our designs to pop off the screen with vibrant, high-contrast hues that are easy on the eyes and create a delightful user experience.

βœ… Pros

Here are the pros:

πŸ”΄ Cons

However, there are some cons to consider:

Unfortunately, not all colors support white or black text overlay from an accessibility standpoint.

πŸ’‘ So, what’s my proposal?

Step 1: Limit the options to only HTML Color Names.

Step 2: Remove/Replace2 from the list of HTML Color Names those that are not accessible.

By implementing this two-step approach, we ensure that only colors deemed safe for HTML are considered initially, and then further refine the selection by excluding any colors within that set that pose accessibility challenges. This strategy effectively maintains both flexibility and accessibility while addressing potential consistency issues.

Organized by foreground / ink color

βšͺ HTML Color Names with White text

⚫ HTML Color Names with Black text

HTML Color Names full lists

Below, you can find the list of all HTML Color Names with details about their contrast accessibility. This comprehensive list will aid in selecting colors that not only adhere to HTML safety standards but also prioritize accessibility considerations.

note: the one with red text are not accessible

Pink Named Colors πŸ’—

Purple Named Colors πŸ’œ

Red Named Colors ❀️

Orange Named Colors 🍊

Yellow Named Colors πŸ‹

Green Named Colors 🍏

Cyan Named Colors πŸ’§

Blues Named Colors πŸ’™

Brown Named Colors 🐻

White Named Colors β›„

Grey Named Colors 🐨


play area

I couldn’t have written this post without


  1. Using the code below:

    color1 = '#f00';
    color2 = '#000000';
    getContrastRatio() {
    const rgb1 = this.hexToRgb(this.color1);
    const rgb2 = this.hexToRgb(this.color2);
    // Calculate relative luminance for each color
    const luminance1 = this.calculateLuminance(rgb1);
    const luminance2 = this.calculateLuminance(rgb2);
    // Calculate contrast ratio
    const contrastRatio = (Math.max(luminance1, luminance2) + 0.05) / (Math.min(luminance1, luminance2) + 0.05);
    return contrastRatio.toFixed(2); // Return contrast ratio with two decimal places
    }
    hexToRgb(hex: string) {
    // Remove '#' if present
    hex = hex.replace('#', '');
    const r = parseInt(hex.substring(0, 2), 16);
    const g = parseInt(hex.substring(2, 4), 16);
    const b = parseInt(hex.substring(4, 6), 16);
    return { r, g, b };
    }
    calculateLuminance(rgb: { r: number, g: number, b: number }) {
    const { r, g, b } = rgb;
    const linearR = r / 255;
    const linearG = g / 255;
    const linearB = b / 255;
    const sRGB = [linearR, linearG, linearB].map((channel) => {
    return channel <= 0.03928 ? channel / 12.92 : Math.pow((channel + 0.055) / 1.055, 2.4);
    });
    return 0.2126 _ sRGB[0] + 0.7152 _ sRGB[1] + 0.0722 \* sRGB[2];
    }
     ↩︎

  2. replace with accessible one behind the scene ↩︎

Previous: (0.002) Love-OKLCH tool