Adjust color contrast by factor
Push a color's channels away from mid-grey 128 to make it punchier, or toward it to flatten it: #3366cc with a factor of 1.5 becomes #0d59f2. A factor of 1 changes nothing. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Worked example
- Color
- #3366cc
- Factor
- 1.5
- Mid gray
- 128
- Hex
- #0d59f2
- Resistance (Ω)
- 13
- G
- 89
Contrast around mid-gray is the classic imaging move that stretches or compresses each red, green, and blue channel away from the eight-bit midpoint one hundred twenty-eight, instead of sliding HSL lightness or raising a gamma power. Designers, token authors, and graphics engineers use a contrast factor when they want punchier or flatter swatches without spinning the hue wheel or treating the color as a full image. This tool accepts a CSS hex color and a finite factor in the closed interval from zero through ten, applies the per-channel rule that output equals mid-gray plus the signed distance from mid-gray times the factor, clamps every channel to the legal zero-to-two-hundred-fifty-five range, and returns the adjusted hex and RGB integers. A factor of one leaves the swatch unchanged; a factor of zero collapses every channel to mid-gray; values above one increase contrast and may clip highlights or shadows.
What contrast around mid-gray does to RGB channels
Start with a CSS hex color such as hash three three six six c c or the short form hash three six c. The parser expands three-digit codes, lowercases the digits, and converts each pair into red, green, and blue integers from zero to two hundred fifty-five. Mid-gray on that eight-bit scale is one hundred twenty-eight: the integer pivot used by classic contrast sliders in paint programs and raster pipelines.
Each channel is rewritten with ordinary arithmetic: subtract mid-gray, multiply by the contrast factor, add mid-gray again, then round to the nearest integer and clamp into the legal zero-to-two-hundred-fifty-five box. Channels already at mid-gray stay put for every finite factor, because their signed distance is zero. Channels darker than mid-gray move farther from it when the factor is greater than one and closer to it when the factor is between zero and one.
Channels brighter than mid-gray do the same in the opposite direction. A factor of exactly one is identity: every rounded channel matches the input. A factor of zero flattens the swatch to mid-gray on all three channels, which is the hex code eight zero eight zero eight zero.
The same factor is applied independently to red, green, and blue, so relative channel balance can change compared with an HSL contrast story that freezes hue. That difference is intentional: this contract is the linear mid-gray stretch, not a perceptual slider and not a WCAG pair ratio. Alpha hex forms with four or eight digits are rejected because the contract is opaque RGB only.
What you enter and what you get back
Send two fields: color as a hex string and factor as a finite number from zero through ten inclusive. Each swatch includes role, hex, integer r g b, and a printable rgb string. Top-level hex, r, g, and b mirror the contrast-adjusted result for one-line clients.
A short formula string documents the per-channel mid-gray rule for docs and support. Typical checks include applying factor one point five to a mid blue, applying factor zero point five to flatten a saturated red toward gray, confirming that factor one returns the original hex, confirming that factor zero yields mid-gray, and rejecting factor fifteen or a missing color. Wire the free browser form for quick previews, then call the identical contract from scripts when you need bulk token generation or continuous-integration checks.
Keep the factor inside the documented interval rather than relying on silent clamps of the multiplier itself — this tool fails loudly on a bad factor so design systems and rendering pipelines stay predictable across environments.
Where a mid-gray contrast factor earns its keep
Brand and product teams often keep a single hero hex and need a punchier or quieter companion without opening a full image editor or inventing a second brand color by eye. Design-token authors generate contrast ramps by sweeping a factor across a base swatch when HSL lighten or darken feels too pastel and gamma feels too display-specific. Presentation and marketing tools produce campaign variants from a saturated logo: raise the factor for a poster, lower it for a muted background chip.
Curriculum authors teaching imaging can show that stretching RGB around mid-gray is not the same as changing HSL lightness, not the same as a gamma power curve, and not the same as measuring WCAG contrast between two colors. If you later need to compare two hex codes for accessibility, apply a gamma exponent, lighten or darken in HSL, or filter a whole photograph, treat those as separate search intents and landings rather than overloading this mid-gray factor page.
What you can do with it
Punch a brand hex without a new hue
Raise a single logo color around mid-gray and capture the resulting hex for posters, hover states, and design reviews.
Muted token ramps from one swatch
Sweep the factor below one to flatten midtones toward gray while keeping the same RGB proportions instead of sliding HSL lightness.
CI goldens for theme contrast
Assert that production tokens still match the expected mid-gray stretch after palette edits, without opening an image editor.
FAQ
How does the contrast factor change my hex color?
Each RGB channel c becomes clamp(round(128 + (c − 128) × factor), 0, 255). Mid-gray stays fixed; darker and lighter channels move away from 128 when the factor is above 1 and toward 128 when it is below 1.
What factor range is allowed?
Factor must be a finite number in [0, 10].
Which hex formats are accepted?
Three-digit and six-digit CSS hex, with or without a leading hash. Alpha forms (#rgba / #rrggbbaa) and non-hex characters are rejected.
What does adjust color contrast cost?
The browser tool is free and runs locally.
What do factors of 0 and 1 do?
A factor of 1 leaves the color exactly as it was. A factor of 0 pulls every channel to mid-grey, so any color becomes #808080. Values above 1 add contrast; values between 0 and 1 soften it.
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/contrast-adjust \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"color":"#3366cc","factor":1.5}'const res = await fetch("https://api.kit.forhosting.com/color/contrast-adjust", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"color": "#3366cc",
"factor": 1.5
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/color/contrast-adjust",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"color": "#3366cc",
"factor": 1.5
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/color/contrast-adjust", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"color":"#3366cc","factor":1.5}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"color":"#3366cc","factor":1.5}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/color/contrast-adjust", 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": "#3366cc",
"factor": 1.5
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "color.contrast_adjust",
"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
Invalid hex strings and factors outside the allowed range fail with a clear invalid_input error rather than silent wrapping.
What contrast around mid-gray does to RGB channels
Large factors clip: a dark red can hit zero and a light blue can hit two hundred fifty-five, and those clipped endpoints stay at the legal walls rather than wrapping.
Input contract, response shape, and validation
Color also accepts the aliases hex and base; factor accepts contrast and amount. Missing fields, non-hex characters, wrong lengths, NaN, Infinity, negative factors, and values above ten fail with invalid_input and are not charged. On success the response echoes the normalized six-digit color and the numeric factor, reports mid_gray as one hundred twenty-eight, then provides original and result swatches. Pricing for successful API calls is the published base of $0.002 per item; validation failures do not consume prepaid balance.
Where a mid-gray contrast factor earns its keep
Because this capability is a pure parse engine, API pricing is the published base of $0.002 per successful item and failed validation does not consume balance.
Technical questions
What happens at factor = 1 and factor = 0?
Factor 1 is identity: every channel is unchanged, so the result hex matches the normalized input. Factor 0 collapses every channel to mid-gray 128, which is #808080.