Color and complement distance
Color and complement distance turns a familiar color-wheel idea into a reproducible measurement.
Run — free
Supply a hex or RGB color, and the calculator derives its exact 180-degree HSL complement, converts both colors from sRGB into D65 CIELAB, and reports their Delta E 76 separation. A normalized harmony-strength score makes results easier to sort or compare, while the original color, complement, RGB channels, hex codes, and Lab coordinates keep every step inspectable. Strict validation rejects incomplete or out-of-range input rather than quietly changing it.
Enter a color and define its complement consistently
Send one color using a three- or six-digit hexadecimal code, an rgb(r, g, b) expression, or three comma-separated RGB channels. Leading hash marks and hexadecimal letter case do not affect the result. RGB channels must be whole numbers from zero through 255, so malformed syntax, percentages, decimals, missing channels, and values outside the displayable sRGB range are rejected with an invalid-input response. After parsing, the calculator converts the source RGB channels to HSL and rotates hue by exactly 180 degrees while preserving saturation and lightness. That definition matches the classical opposite point on the HSL hue wheel and, importantly, makes the operation explicit instead of relying on an unnamed artistic judgment. The rotated HSL value is converted back to integer sRGB channels before measurement, matching the colors that ordinary screens and CSS workflows can actually represent. Achromatic inputs are a meaningful edge case: because gray has zero saturation, rotating its nominal hue does not create a visually different color. Its complement therefore remains the same gray and its measured distance is zero. Identical inputs always produce identical output because the calculation has no network access, random values, clock, profile lookup, or hidden state.
Read the Lab distance and harmony-strength result
The response shows the normalized original and complement as uppercase six-digit hex values, integer RGB channels, and CIELAB coordinates. Conversion starts by linearizing standard sRGB channels, maps them through the standard sRGB matrix to CIE XYZ, adapts the values to the D65 reference white used by sRGB, and applies the conventional CIELAB transfer function. The reported delta_e_76 is the Euclidean distance between the two Lab triples: zero means that the rendered colors coincide, and larger numbers indicate greater perceptual separation under this model. Delta E 76 is intentionally used because this endpoint measures one deterministic pair rather than applying industry-specific tolerance weights. The harmony_strength field maps that distance onto a convenient zero-to-100 scale by dividing Delta E by two and capping the result at 100. It is a comparative gauge, not a universal law of beauty. Labels make broad sorting easier: below 15 is weak, 15 to below 35 is moderate, 35 to below 65 is strong, and 65 or above is very strong. Saturated complements commonly score high, while muted and neutral colors score lower. Retain delta_e_76 when you need the underlying measurement and use the score or label for dashboards, filtering, and simple design rules.
Use the metric responsibly in design systems
This calculator is useful when a palette generator, theme builder, charting system, or brand-token pipeline needs more than the complement’s hex code. A team can derive complements with one stable convention, rank source colors by the perceptual separation they create, and store the Lab coordinates beside generated tokens for auditing. The API price is $0.002 for each successful item, while the browser execution can support quick interactive checks. Validation failures prevent bad color strings from becoming plausible-looking palette data. Harmony strength should not be confused with accessibility contrast: Delta E estimates color difference, whereas readable text requires a luminance-based contrast calculation and consideration of font size and context. Nor does a very strong score guarantee that a pair suits a particular brand, culture, interface state, or print process. Displays operate in sRGB here; print colors, spot inks, wide-gamut values, and measured samples require an explicitly managed color profile before comparison. Use the result as one consistent signal alongside contrast, hierarchy, saturation balance, and human review. When reproducibility matters, record the method field with the output. It identifies the complete HSL-rotation, D65 CIELAB, and Delta E 76 path so later systems do not mistake this score for CIE94, CIEDE2000, or a different complement rule.
What you can do with it
Rank generated accent colors
Measure each brand color against its derived complement and prioritize pairs with the desired amount of perceptual separation.
Audit design-token generation
Store normalized hex, RGB, Lab, method, and distance fields so a complementary token can be reproduced and checked later.
Teach color relationships
Show why saturated colors and neutral grays behave differently when the same 180-degree hue rotation is measured perceptually.
FAQ
How is the complement calculated?
The source is converted from sRGB to HSL, its hue is rotated by 180 degrees, saturation and lightness stay fixed, and the result is converted back to integer sRGB.
What does Delta E 76 mean?
It is the straight-line distance between the original and complement in CIELAB. Zero means no Lab separation; larger values mean greater modeled perceptual separation.
How is harmony strength calculated?
The calculator divides Delta E 76 by two and caps the result at 100. The score is a consistent comparative gauge, not an objective rating of aesthetic quality.
Does a high score guarantee accessible contrast?
No. Perceptual color distance and luminance contrast answer different questions. Use a WCAG contrast calculator for text and interface accessibility.
What does an API calculation cost?
Each successful API item costs $0.002. Invalid input is rejected clearly rather than silently clamped into range.
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/color/complement-distance \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"color":"#336699"}'const res = await fetch("https://api.kit.forhosting.com/color/complement-distance", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"color": "#336699"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/color/complement-distance",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"color": "#336699"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/color/complement-distance", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"color":"#336699"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"color":"#336699"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/color/complement-distance", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"color": "#336699"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "color.complement_distance",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |