Repair text contrast

Adjust a failing foreground, serialize the result, and verify the exact color your application will use.

Before

Text should remain readable on every surface.

#3b82f6 3.98:1 AA fail

After hex round trip

Text should remain readable on every surface.

#468eff 4.58:1 AA pass

The display rounds ratios to two decimals. The pass or fail status compares the full, unrounded value.

Make the stored color pass

The same blue text fails on the dark surface before repair. After adjustment and a hexadecimal round trip, the stored value passes WCAG AA for normal text.

Check the value that crosses the boundary

A successful internal calculation is not the final artifact. Serialize the adjusted object, parse that representation again, then calculate the ratio from the value destined for CSS or storage.

  1. Adjust lightness4.55:1 target
  2. Serialize#468eff
  3. ReparseColor::parse()
  4. Verify4.57921969665986062:1

Repair, serialize, and measure again

This fixture uses a search target of 4.55:1 so hexadecimal channel quantization does not pull the final value below the required 4.5:1.

<?php

use PhpColor\Color\Color;
use PhpColor\Color\Contrast\ColorContrast;
use PhpColor\Color\Contrast\ContrastSolver;

$background = Color::parse('#1e293b');
$before = Color::parse('#3b82f6');

$adjusted = ContrastSolver::adjustLightnessToContrast(
    $before,
    $background,
    4.55,
);

$hex = $adjusted->toHex();
$after = Color::parse($hex);

printf(
    "%s\n%.17f:1 -> %.17f:1\n",
    $hex,
    ColorContrast::calculate($before, $background),
    ColorContrast::calculate($after, $background),
);

// #468eff
// 3.97746363148053828:1 -> 4.57921969665986062:1
use PhpColor\Color\Color; use PhpColor\Color\Contrast\ColorContrast; use PhpColor\Color\Contrast\ContrastSolver; $background = Color::parse('#1e293b'); $before = Color::parse('#3b82f6'); $adjusted = ContrastSolver::adjustLightnessToContrast( $before, $background, 4.55, ); $hex = $adjusted->toHex(); $after = Color::parse($hex); printf( "%s\n%.17f:1 -> %.17f:1\n", $hex, ColorContrast::calculate($before, $background), ColorContrast::calculate($after, $background), ); // #468eff // 3.97746363148053828:1 -> 4.57921969665986062:1

Verify every repaired representation

This page proves one foreground, one background, and one hexadecimal representation. It does not promise that every pair can be repaired with the same margin.

Serialization changes the result

A target of exactly 4.5:1 serializes this fixture as #458cff. Reparsed, it reaches only 4.49190475486645280:1.

The solver is best effort

It returns a color, not a solved or unsolved status. The application must test the final representation itself.

Light backgrounds need caution

PHPColor 1.0 has a known light-background search defect. This demonstrated dark-surface fixture does not generalize to that path.

A ratio is not the whole interface

The check covers this color pair and WCAG threshold. It does not inspect typography, rendering, states, or the complete component.

Try the verified pair

Measure, repair, then verify the stored color