Is color light or dark
White #ffffff scores a brightness of 255, above the 128 threshold, so it counts as light and should carry black text (#000000). Use it to pick label color for buttons, badges and chips. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Worked example
- Color
- #ffffff
- Input hex
- #ffffff
- Input rgb
- 255, 255, 255
- Resistance (Ω)
- 255
- G
- 255
Choosing black or white label text on a colored button is a classic accessibility and branding problem: pure white on a pale yellow fails contrast, and pure black on navy can look wrong when the fill is almost black. This is-color-light-or-dark classifier takes one opaque hex color, computes a deterministic perceived brightness using the ITU-R BT.601 coefficients that weight green more than red and blue, compares that brightness to a configurable threshold (default one hundred twenty-eight on the zero-through-two-hundred-fifty-five scale), and returns whether the swatch is light or dark plus a recommended overlay text color. Designers wiring theme tokens, developers picking icon color on dynamic badges, and automated tests that freeze light versus dark decisions all need the same arithmetic every time.
Why perceived brightness, not raw average of channels
A naive mid-gray rule that averages red, green, and blue treats pure blue and pure yellow as equally bright, which mismatches how human vision and most UI libraries decide light versus dark. Perceived brightness for this landing follows the long-standing BT.601 luma style coefficients used across video and web tooling: brightness equals zero point two nine nine times red plus zero point five eight seven times green plus zero point one one four times blue, with each channel an integer from zero through two hundred fifty-five.
Green dominates the sum because the eye is most sensitive there; blue contributes the least. After computing brightness, the tool compares it to a threshold. The default threshold is one hundred twenty-eight, the midpoint of the eight-bit scale, which matches many open-source isLight helpers that treat brightness greater than or equal to that cut as light.
You may pass a custom threshold when your design system wants more colors classified as dark (raise the threshold) or more as light (lower it). Classification is inclusive on the light side: brightness greater than or equal to the threshold yields light, and anything strictly below yields dark.
Practical tips, limits, and related searches
Remember that this classifier answers light versus dark for a single swatch; it does not compute WCAG contrast between foreground and background, does not return relative luminance on a zero-to-one linearized sRGB scale as its primary score (it reports BT.601 channel brightness), and does not adjust for alpha or for text size. Do not pass alpha forms such as #RRGGBBAA—this landing classifies opaque hex only. Named CSS colors and rgb() strings should be resolved to hex first, then passed here, so the validation surface stays a single well-specified color string.
This page targets people searching for is color light or dark, light or dark hex checker, perceived brightness overlay text, or free classify hex light dark online; it is not a full palette generator, not a darken or lighten mixer, and not a multi-space converter.
Prefer this capability when you already have one hex token and only need a deterministic light or dark label plus a default black or white overlay recommendation; if your pipeline needs contrast ratios or AA flags between two colors, use a dedicated contrast checker after you pick candidates.
What you can do with it
Dynamic badge and chip labels
Pick black or white label text on user-chosen badge colors so product UIs stay readable without hand-tuning every brand hex.
Theme token automation
Classify design-system surface tokens as light or dark so icon sets and hairline borders switch automatically in CI.
FAQ
What overlay text color does it recommend?
Dark text (#000000) on light backgrounds and light text (#ffffff) on dark backgrounds. Always verify WCAG contrast for production small text.
Which color formats are accepted?
Hex #RGB or #RRGGBB with optional leading #, case-insensitive. Alpha hex, named CSS colors, and rgb() strings are not accepted on this landing.
Can I change the brightness threshold?
Yes. Pass threshold as a finite number from 0 through 255. Higher values classify more colors as dark; lower values classify more as light. Default is 128.
Is is color light or dark free?
The browser tool is free and runs locally.
Why is yellow light and blue dark if both are pure colors?
Perceived brightness weighs green most and blue least: 0.299 times red, plus 0.587 times green, plus 0.114 times blue. Yellow contains full green, so it scores high; pure blue contributes very little.
Related tools
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/is-light-or-dark \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"color":"#3b82f6"}'const res = await fetch("https://api.kit.forhosting.com/color/is-light-or-dark", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"color": "#3b82f6"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/color/is-light-or-dark",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"color": "#3b82f6"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/color/is-light-or-dark", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"color":"#3b82f6"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"color":"#3b82f6"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/color/is-light-or-dark", 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": "#3b82f6"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "color.is_light_or_dark",
"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. |
Technical notes
Paste brand tokens such as #3b82f6, #f8fafc, or three-digit shorthand like #abc; invalid hex strings fail with invalid_input instead of inventing a label.
Why perceived brightness, not raw average of channels
The response always echoes the numeric brightness, the threshold used, boolean is_light and is_dark flags, a classification string, and a recommended overlay text color of dark with hex #000000 on light backgrounds or light with hex #ffffff on dark backgrounds. That recommendation is a practical default for badges and chips; production products that must meet WCAG contrast ratios should still measure the final pair with a contrast checker, because black on mid-gray may pass brightness classification yet fail AA for small text. This page intentionally answers the search intent is color light or dark and light or dark hex classifier rather than computing a full contrast ratio between two colors.
Input contract, response shape, and error behaviour
Valid examples include #3b82f6, 3b82f6, #abc, and ABC. Surrounding whitespace is trimmed, letters may be upper or lower case, and the leading hash is optional. Only three-digit and six-digit hexadecimal bodies are accepted; eight-digit alpha hex, named CSS colors such as rebeccapurple, rgb() function strings, and separate numeric channel fields are out of scope and rejected so you notice rather than silently dropping alpha. Optional threshold is a finite number from zero through two hundred fifty-five inclusive; omit it to use one hundred twenty-eight. Send a JSON body with a required color string. The color field accepts aliases hex, value, text, input, and code. On success the response returns input_hex and input_rgb for the resolved source, integer channels r g b with red green blue aliases, source as hex3 or hex6, brightness on the zero-through-two-hundred-fifty-five scale with fixed display precision, brightness_0_1 as brightness divided by two hundred fifty-five, threshold, classification as light or dark, is_light and is_dark booleans, recommended_text as dark or light, recommended_text_hex as #000000 or #ffffff, formula restating the BT.601 weighted sum, method equal to perceived_brightness_bt601, message as a short English summary, and steps as ordered substitution lines for teaching or debugging. Failed validation—missing color, empty string, wrong hex length, non-hex characters, a programming 0x prefix, or an out-of-range threshold—returns invalid_input and is never charged. Pricing is a flat $0.002 per successful request with unit item. Prefer sending the exact token your design tool exported; the response always normalizes the source to a lowercase six-digit input_hex so downstream diffs stay stable.
Practical tips, limits, and related searches
Failed tasks that return invalid_input do not consume prepaid balance, which keeps exploratory scripts and form validation cheap while learners paste imperfect clipboard values. Pin classification, brightness, and recommended_text_hex in automated tests so a future change to threshold defaults or rounding cannot pass silently, and document that method is perceived_brightness_bt601 when you store results next to other luminance systems.
Integration use cases
Unit tests for overlay decisions
Freeze known-good light/dark classifications from hex fixtures so theme engines catch regressions when brightness math changes.
Technical questions
How does is color light or dark decide light vs dark?
It computes BT.601 perceived brightness = 0.299×R + 0.587×G + 0.114×B on 8-bit channels, then compares to a threshold (default 128). brightness ≥ threshold → light; otherwise dark.