WCAG text spacing checker
This WCAG text spacing checker compares stylesheet measurements with the three font-relative values commonly tested for text spacing adjustability: line height of at least 1.5 times the font size, letter spacing of at least 0.12 times the font size, and word spacing of at least 0.16 times the font size.
Run — free
Enter every measurement in one consistent unit, such as pixels or points. The result reports each observed ratio, its required minimum, the corresponding minimum value, and an overall pass or fail. It is a focused numerical check for design reviews and automated tests, not a substitute for testing whether content remains usable when readers override spacing.
Measure all four values in one consistent unit
Start with the computed font size and the line-height, letter-spacing, and word-spacing values you want to evaluate. All four numbers must use the same unit because the checker divides every spacing measurement by the font size. Pixels are convenient when you copy computed styles from browser developer tools, but points, rems converted to numbers, or any other consistent length unit produce the same ratios. For example, a 16 pixel font paired with a 24 pixel line height produces a ratio of 1.5. A 1.92 pixel letter spacing produces 0.12, and a 2.56 pixel word spacing produces 0.16. Unit labels are intentionally not accepted: send numeric values after resolving CSS keywords, percentages, unitless line-height declarations, inherited values, and relative units to comparable measurements. The font size must be greater than zero; zero and negative font sizes cannot define meaningful relative spacing and are rejected. Other finite spacing values are evaluated as supplied, so a negative spacing value receives a failing ratio instead of being silently corrected.
Read the individual checks before the overall result
The response contains one check for line height, one for letter spacing, and one for word spacing. Each check repeats the supplied value, calculates its ratio to font size, states the WCAG-oriented minimum ratio, calculates the minimum absolute value for the supplied font size, and returns a Boolean pass result. The overall passes field is true only when all three individual comparisons pass. Values exactly on a boundary pass: a line-height ratio of 1.5, letter-spacing ratio of 0.12, or word-spacing ratio of 0.16 meets its respective threshold. The algorithm uses the numeric values directly and does not round before comparing, which avoids changing a result near a boundary merely for display. This output makes failures actionable. Instead of seeing only a generic rejection, a developer can identify the property below its target and compare the current value with minimum_value. Because the calculation is deterministic and has no network dependency, identical JSON input always produces identical JSON output in a browser, build pipeline, or API integration.
Use the result as a focused adjustability check
WCAG 1.4.12 is about preserving content and functionality when users apply specified text-spacing overrides. This calculator checks whether the three supplied measurements reach the ratios associated with line height, letter spacing, and word spacing; it does not inspect a page, rewrite CSS, or prove that a layout tolerates user overrides. A complete accessibility review should still apply the relevant spacing changes in a real browser and look for clipped text, hidden controls, overlaps, truncated labels, broken dialogs, and lost content. Paragraph spacing is another part of the success criterion, but it is outside this capability because the declared input covers only line height, letter spacing, and word spacing relative to font size. Use the numerical result to catch obvious token or stylesheet mismatches early, then use rendering tests for actual behavior. The browser version is useful during manual design review, while the API costs $0.002 per successful request and fits regression suites that evaluate resolved style values from components, themes, templates, or generated documents. Invalid input is rejected rather than converted or guessed.
What you can do with it
Audit design tokens
Compare typography tokens with the target ratios before publishing a shared component library.
Add a regression assertion
Send resolved style measurements from automated tests and fail a build when any spacing ratio falls short.
Review a CSS override
Check proposed line, letter, and word spacing values numerically before testing the resulting layout in a browser.
FAQ
What ratios does the checker use?
It checks line height at 1.5 times font size, letter spacing at 0.12 times font size, and word spacing at 0.16 times font size.
Do the inputs have to be in pixels?
No. Any length unit works when font size and all three spacing values use that same unit.
Does a result at the exact threshold pass?
Yes. Each comparison is inclusive, so a value equal to its minimum ratio passes.
Does this prove that a page conforms to WCAG 1.4.12?
No. It checks three numeric ratios only. You must also apply spacing overrides to the rendered page and confirm that content and functionality are not lost.
What does the API request cost?
A successful API request costs $0.002. The same deterministic calculation is available in the browser.
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/verify/wcag-text-spacing-check \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"font_size":16,"line_height":24,"letter_spacing":1.92,"word_spacing":2.56}'const res = await fetch("https://api.kit.forhosting.com/verify/wcag-text-spacing-check", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"font_size": 16,
"line_height": 24,
"letter_spacing": 1.92,
"word_spacing": 2.56
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/verify/wcag-text-spacing-check",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"font_size": 16,
"line_height": 24,
"letter_spacing": 1.92,
"word_spacing": 2.56
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/verify/wcag-text-spacing-check", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"font_size":16,"line_height":24,"letter_spacing":1.92,"word_spacing":2.56}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"font_size":16,"line_height":24,"letter_spacing":1.92,"word_spacing":2.56}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/verify/wcag-text-spacing-check", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"font_size": 16,
"line_height": 24,
"letter_spacing": 1.92,
"word_spacing": 2.56
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "verify.wcag_text_spacing_check",
"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. |