Minimum accessible font size checker for body, captions and buttons
Small text can make otherwise useful interfaces difficult to read, especially for people with low vision, older readers, and anyone using a screen in challenging conditions.
Run — free
This checker compares a font size in CSS pixels with a practical minimum for body text, captions, or button labels. It reports the applicable threshold, whether the size meets it, and the exact difference. The result is guidance for an early accessibility review, not a claim that font size alone makes a design accessible.
Choose the content role before judging the number
A font size does not communicate enough by itself because text serves different purposes. Body copy carries sustained reading and therefore uses a common minimum of 16 CSS pixels in this checker. Captions are shorter and secondary, so the comparison threshold is 12 pixels. Button labels must remain legible while also fitting a control, and this checker uses 14 pixels for that role. Select the role that describes how the words function, not how the text happens to look. A line below an image is a caption even if it uses the same typeface as an article. Text inside an actionable control is a button label even when the control has been styled to resemble a link. Keeping the role explicit makes repeated audits consistent across pages and prevents teams from quietly applying the smallest threshold to every element. These values represent widely used practical guidance rather than universal legal pass criteria. A product design system may deliberately set larger minimums for its audience, brand typeface, device mix, or reading conditions.
Read the result as a screening decision
The result includes the submitted size, the selected content type, the minimum used for comparison, a pass-or-flag boolean, and a signed pixel difference. A difference of zero means the size lands exactly on the selected threshold and therefore meets this check. A negative difference shows how far below the guidance the current setting falls, while a positive difference shows the available margin. This direct comparison is useful in design-token reviews, component inventories, automated quality checks, and acceptance criteria because it converts an informal concern into a stable decision. However, passing should be treated as the beginning of accessibility evaluation rather than its end. Apparent size changes with the typeface, weight, letterforms, line height, display density, zoom, and surrounding layout. Text at 16 pixels can still be tiring if its contrast is weak or its line length is excessive. Conversely, a carefully drawn face may appear clearer than another face at the same nominal size. Use the flag to find likely problems quickly, then inspect the rendered component with real content and representative users or assistive settings.
Combine minimum size with resilient typography
Accessible typography must survive the ways people actually adapt a page. After resolving a flagged size, verify that text can zoom without clipping, controls can grow without losing their labels, and layouts reflow without forcing horizontal scrolling. Prefer relative CSS units in the implemented interface when they help preserve user settings, even though this checker accepts a pixel value for a clear and comparable calculation. Check contrast in every interactive state, including hover, focus, disabled, and error states. Give body text comfortable line spacing and line length, and avoid relying on tiny captions to carry essential instructions or legal choices. Button labels deserve special attention because a readable label can still fail when the clickable target is too small, focus is hard to see, or the accessible name is missing. The thresholds here are intentionally simple: 16 pixels for body text, 12 for captions, and 14 for button labels. That simplicity makes the tool suitable for repeatable screening, but context remains decisive. If your design serves readers with known low-vision needs, appears on distant displays, or operates outdoors, choose a larger house standard and treat this result only as a baseline warning system.
What you can do with it
Review design tokens
Check typography token values against a consistent baseline before components are implemented across a product.
Audit a component library
Flag undersized body copy, captions, and button labels while inventorying reusable interface components.
Add a release check
Use the deterministic API result to catch a font-size regression in a documented accessibility workflow.
FAQ
Does meeting the minimum guarantee accessibility compliance?
No. This is a practical screening check, not a legal certification. Contrast, zoom, reflow, spacing, typeface legibility, content, and interaction design also matter.
Which font-size unit should I enter?
Enter the computed font size in CSS pixels. If your stylesheet uses rem or em, convert the rendered value to pixels before checking it.
What thresholds does the checker use?
It compares body text with 16px, captions with 12px, and button labels with 14px. These are common practical baselines and may be raised by your design system.
Why are captions allowed to be smaller than body text?
Captions are usually brief and secondary, but they must remain readable. Essential instructions should not be hidden in small caption text.
What happens if I submit another content type?
The request returns an invalid-input error. Use body, caption, or button_label so the checker can apply a defined threshold.
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/accessibility-font-size-min-check \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"font_size":16,"content_type":"body"}'const res = await fetch("https://api.kit.forhosting.com/verify/accessibility-font-size-min-check", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"font_size": 16,
"content_type": "body"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/verify/accessibility-font-size-min-check",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"font_size": 16,
"content_type": "body"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/verify/accessibility-font-size-min-check", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"font_size":16,"content_type":"body"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"font_size":16,"content_type":"body"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/verify/accessibility-font-size-min-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,
"content_type": "body"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "verify.accessibility_font_size_min_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. |