px to rem converter
With a 16 px root, 16 px is 1 rem and 0.5 rem is 8 px. Convert CSS lengths between pixels and rem against the root font size your stylesheet actually sets, and get a ready-to-paste value with the formula and steps. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Worked example
- Value
- 16
- From
- px
- To
- rem
- Base
- 16
- Result
- 1 rem
- Converted
- 1
- Css
- 1rem
A px to rem converter turns a CSS length in pixels or rem into the other unit using the root font size you actually ship. Enter the numeric value, choose from and to as px or rem, and set base to the root (html) font-size in pixels—commonly sixteen on desktop browsers, sometimes fourteen or eighteen on design systems. The tool returns the converted magnitude, a ready-to-paste css string such as one rem or sixteen px, the formula used, and step-by-step substitution so design tokens and code reviews stay aligned. Theme migrations, fluid-type audits, Figma-to-CSS handoff, and accessibility font scaling all need that same deterministic rem equals px over root math without opening a browser inspector.
What px and rem mean for CSS typography
In CSS, a pixel length (px) is an absolute length unit used throughout layouts, borders, and legacy typography tokens. A rem length is relative to the font-size of the root element—almost always the html element—so one rem equals whatever that root font-size is in pixels. If the root is sixteen pixels, then sixteen px equals one rem, thirty-two px equals two rem, and zero point five rem equals eight px.
Design systems prefer rem for type scales and spacing because users who enlarge the browser default font, or who set a larger root for accessibility, get proportional growth without hunting every hard-coded pixel. Converting the other way matters when a library still emits px tokens or when a design tool exports fixed pixel sizes and you need rem declarations that match the production root. The conversion itself is elementary: rem equals px divided by base, and px equals rem multiplied by base, where base is the root font-size in pixels.
What trips teams up is not the formula but mismatched bases—assuming sixteen when the stylesheet sets html font-size to sixty-two point five percent (ten px) or to one hundred twelve point five percent (eighteen px). This calculator forces the base into the open so the result always matches the scale you claim to use.
Practical tips, limits, and related searches
Keep value and base inside the published absolute range so products cannot overflow into a non-finite result that the solver must reject. Prefer sending numbers rather than pre-formatted strings when you control the client; string numbers are accepted only when they match a strict finite numeric pattern.
Document the root font-size next to every token table: if html uses sixty-two point five percent of the user default, base is ten px for a sixteen-pixel user agent default, and a twenty-four px heading becomes two point four rem—not one point five rem. When from equals to the tool returns the value unchanged so pipelines can normalize units without a special case, but the base is still required and still validated as non-zero.
Prefer this capability when you already know the root size in pixels and only need the length conversion; if you need live computed styles from a real page, use browser tooling instead. Round-trip checks are easy: convert px to rem and back with the same base and confirm the original value within the same twelve-decimal rounding.
What you can do with it
Design-token tables from Figma pixels
Export spacing and type sizes as px from design tools, set base to your production root font-size, and emit rem tokens that match the live stylesheet.
Theme migration from px to rem
Batch-convert legacy pixel typography and spacing scales to rem while documenting the exact base used for every batch.
FAQ
How do you convert px to rem?
Divide the pixel length by the root font-size in pixels: rem = px / base. With a 16px root, 24px becomes 1.5rem.
How do you convert rem to px?
Multiply the rem length by the root font-size in pixels: px = rem × base. With a 16px root, 1.25rem becomes 20px.
Does this convert em or % units?
No. It only converts between px and rem with an explicit root base in pixels. Em is relative to a parent element, not the root.
Is the px to rem converter free?
The browser tool is free and runs locally.
What base should I use if my stylesheet sets html to 62.5%?
Use 10 px, because 62.5% of a 16-pixel browser default is ten pixels. With that base a 24 px heading is 2.4 rem, not the 1.5 rem you would get with a base of 16.
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/conv/typography-px-rem \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"value":16,"from":"px","to":"rem","base":16}'const res = await fetch("https://api.kit.forhosting.com/conv/typography-px-rem", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"value": 16,
"from": "px",
"to": "rem",
"base": 16
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/conv/typography-px-rem",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"value": 16,
"from": "px",
"to": "rem",
"base": 16
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/conv/typography-px-rem", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"value":16,"from":"px","to":"rem","base":16}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"value":16,"from":"px","to":"rem","base":16}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/conv/typography-px-rem", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"value": 16,
"from": "px",
"to": "rem",
"base": 16
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "conv.typography_px_rem",
"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.
Limits
max_abs | 1000000000000 |
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
When base is zero the scale is undefined, so the API returns a clear invalid_input error instead of inventing infinite lengths.
How to call the API and what comes back
Base must be non-zero; absolute values at or below one times ten to the minus fifteen are treated as zero and rejected. Send a JSON body with four required fields: value (aliases amount, n, length), from (aliases from_unit, unit_from, source), to (aliases to_unit, unit_to, target), and base (aliases root, root_font_size, root_px, base_px). Value and base must be finite numbers whose absolute values stay within the published limit of one trillion so intermediate products remain finite in IEEE double precision on the Worker and in the browser. From and to must resolve to px or rem after alias normalization—pixel, pixels, rem, rems, root em, and similar spellings are accepted; unknown unit names return invalid_input. On success the response echoes rounded value, from, to, and base; sets result and converted to the same rounded output magnitude; unit to the target unit; css to a compact string like one rem or twenty four px; formula to rem equals px over base, px equals rem times base, or the identity message when from equals to; message to a short English summary; and steps to an ordered array of substitution lines. Failed validation—missing fields, non-finite numbers, values outside absolute limits, unknown units, zero base, or a non-finite result—returns invalid_input and is never charged. Pricing is a flat $0.002 per successful request with unit item and zero marginal unit price.
Practical tips, limits, and related searches
Pair examples for teaching and tests: sixteen px to rem with base sixteen yields one rem; one point five rem to px with base sixteen yields twenty-four px; twenty px to rem with base ten yields two rem; and base zero with any value demonstrates the hard invalid_input path. This landing targets people searching for a px to rem converter, rem to px calculator, or CSS root font-size typography tool; it is not an em converter relative to a parent element, not a fluid clamp generator, and not a viewport-unit calculator. Failed tasks that return invalid_input do not consume prepaid balance, which keeps exploratory scripts cheap when developers deliberately set base to zero.
Integration use cases
Unit tests for CSS length helpers
Generate known-good px↔rem pairs plus deliberate zero-base rejections for frontend utility libraries and design-system packages.
Technical questions
What happens when base is zero?
Conversion is undefined. This tool returns invalid_input instead of dividing by zero or inventing infinite lengths.