One rem equals the computed font size of the document's root element, so a 24 px value at a 16 px root becomes 1.5 rem using the formula rem = pixels ÷ root pixels. Designers reading measurements from a Figma file usually see lengths expressed in pixels, because Figma frames, components, and text styles store dimensions as raw px values regardless of how those sizes will be reimplemented on the web. Converting those numbers to rem keeps spacing, font sizes, and component dimensions scaling with the user's preferred text size, which is the main reason designers reach for rem in CSS in the first place. The conversion is mathematically simple, but the answer depends on a single number — the root font size — that many people silently assume is 16 px even when it is not. The PX to REM Converter accepts your pixel value, your actual root size, and returns a copy-ready CSS value you can paste straight into a stylesheet, so the question becomes less about arithmetic and more about reading the right root size from the document you are coding against.

Why Figma values are stored in pixels, not rem
Figma is a vector design tool, and every frame, constraint, auto-layout gap, and text style is recorded internally in device-independent pixel units that map directly to CSS reference pixels. A 24 px spacing in an auto-layout component, a 16 px line height on a label, and a 1.5 rem gap on a card all show up as the same kind of number in the inspector: a plain pixel value. The design file does not know whether you intend to ship the result with px, rem, em, or % on the web, so it does not store that intent. The choice of unit lives in the implementation, and that is precisely where the conversion has to happen.
The same Figma file can therefore be implemented by several teams with different unit conventions. One developer may rebuild spacing as fixed px for pixel-perfect screenshots, another may rebuild it as rem for accessibility-aware scaling, and a third may convert a portion of the values to % for fluid layouts. The pixel value coming out of Figma is the only common ground between those implementations, and the conversion that follows it has to be repeatable and accurate, which is the gap a strict converter is meant to fill. Other Figma-to-CSS translations follow the same pattern: when a layout uses gradients, matching the original angle and color stops takes a comparable inspect-and-translate workflow described in matching gradient angle and stops from Figma to CSS.
How to convert px to rem from a Figma design
- Open the Figma file and select the element, text style, or auto-layout gap whose measurement you need to translate to CSS. Read the value from the inspector exactly as it appears, including decimal fractions such as 12.5 if the design uses fractional px.
- Open the PX to REM Converter and confirm the direction is set to PX to REM before typing.
- Type the pixel value from Figma into the value field. The field accepts strict decimal numbers and scientific notation such as 2e2 or 1e-3; hexadecimal syntax, commas, CSS unit suffixes inside the input, and mixed text are rejected on purpose so the calculation cannot quietly accept malformed data.
- Inspect the actual computed font-size of the target document's root element — typically the <html> node — using browser developer tools, and enter that px value into the root font size field. Keep the default of 16 only when that is genuinely the computed root of the document you will ship.
- Run the conversion and read the displayed CSS value, for example 1.5rem. If the converter shows an approximation marker, the binary floating-point representation of the quotient differs from the displayed digits at 12 significant figures, so the value is mathematically close to but not literally equal to what you see.
- Click copy to put the displayed number and unit on the clipboard, then paste it into your stylesheet. If the browser blocks clipboard access because of permission or secure-context rules, the tool surfaces a manual-copy message instead of clearing the result.
Finding the actual root font size in your target document
The CSS rem unit is defined relative to the font size of the root element, per the W3C CSS Values and Units specification, and that is the only number the converter needs in the root field. Sixteen pixels is a long-standing browser default, and the converter pre-fills it as a convenience, but the value is not guaranteed. Browser zoom, minimum-font-size preferences, user stylesheets, accessibility settings, embedded documents such as iframes, and an application design system that declares its own root size can all produce a different computed value. Treating 16 as fixed is the most common source of rem numbers that look right at the developer's machine and quietly miss the design at the user's machine. For a wider view of how rem compares with other relative length units, MDN's reference on root-relative lengths walks through each option and its scope.
| Root font size source | How to confirm it | What to enter in the converter |
|---|---|---|
| Untouched browser default | Inspect the <html> computed font-size in DevTools | The px value DevTools reports |
| CSS reset or design system declaration | Read the :root or html rule that sets font-size | The px value that rule resolves to at runtime |
| Embedded iframe or shadow root | Inspect the iframe document or the shadow host's root, not the parent page | The computed root px value inside that scope |
| Accessibility or user-style override | Inspect after applying the user's browser settings; do not assume default | The px value that is actually applied in the user's session |
If you are shipping a stylesheet from scratch and want root-relative scaling, set the root size explicitly in your CSS so the converter has a stable number to use and your team has one source of truth. When the document is already styled by someone else, the converter is most accurate when you copy the computed px value straight from DevTools rather than reconstructing it from declarations.
Reading the approximation mark on the result
JavaScript performs arithmetic in IEEE 754 binary floating point, which means some decimal quotients cannot be stored with an exact finite representation. The converter formats every result to at most 12 significant digits, strips decorative trailing zeros, retains scientific notation when it communicates the magnitude more clearly, and explicitly labels the output as approximate when the displayed text differs from the number's canonical shortest decimal form. Exact results such as 1.5rem are not labelled, because 1.5 has a clean binary representation; values whose displayed digits were rounded show the marker so you can tell the difference at a glance.
The marker is informational rather than blocking. Twelve significant figures is several orders of magnitude beyond what any CSS layout work needs, so an approximate label is a signal to inspect the value, not a signal that the result is wrong. If your design system requires a specific number of decimal places, the marker tells you which outputs to round manually rather than trusting browser-level formatting. Exact negative zero is normalised to ordinary zero, so a rem output of 0rem never carries an approximation marker for that reason.
A worked example: turning 24 px from Figma into rem
Suppose a Figma auto-layout component shows a 24 px gap between two cards, and the target stylesheet uses the common 16 px root.
- Formula: rem = pixels ÷ root pixels
- Substituted: rem = 24 ÷ 16
- Result: 1.5rem
The reverse direction is equally mechanical: a designer who wrote 1.25rem in an existing stylesheet at a 16 px root is committing to 1.25 × 16 = 20 px at the root's default zoom, which you can confirm by entering 1.25 in the converter with REM to PX selected and a root of 16. If the same Figma file were implemented against a stylesheet whose root had been resized to 20 px, the same 24 px gap would resolve to 1.2rem instead of 1.5rem; the px value coming out of Figma does not change, but the rem representation does. That difference is the reason the converter does not assume that a design exported at one root size will preserve its pixel result under another, and it is why the Figma source number has to be paired with the real root before the conversion can be trusted.
Inputs the converter accepts and the limits it enforces
The value field uses a strict decimal grammar. Whole numbers, decimal fractions, leading decimals such as .5, signed values, and scientific notation such as 2e2 or 1e-3 all parse correctly. Hexadecimal syntax, commas, CSS unit suffixes inside the input, Infinity, NaN, partial exponents, and mixed text are rejected, so a stray 16px paste cannot be quietly trimmed into 16. Each raw field is also bounded by a 100 UTF-16 code-unit budget, checked before trimming; over-limit input fails explicitly rather than being truncated. Leading and trailing whitespace are tolerated, but internal whitespace inside the number is not silently removed.
Numeric ranges are explicit. The main value is accepted within ±1,000,000,000 and the root font size within 1 through 1,000 px. The largest reverse result the tool will produce is 1,000,000,000,000 px, and any nonzero division that underflows to zero after parsing is rejected instead of silently becoming zero. Negative values are allowed because several CSS properties and calculations accept signed lengths, even though individual properties such as margin-top or font-size may impose their own non-negative rules at the CSS layer. The converter performs unit arithmetic; it does not validate whether a given output is legal for every CSS property, and it does not evaluate a stylesheet, resolve cascade or inheritance, inspect browser preferences, or predict the special declaration context in which rem refers to its own initial value at the root.
Editing the value, the root, the direction, or running a fresh conversion clears any prior copy status immediately, so a stale clipboard notification cannot overwrite the current state after the inputs change. Each copy attempt receives a generation token, which means a late success or failure from an older clipboard request is ignored once new work has started. If you are translating several Figma measurements at once and need to keep the root size constant while the px value changes, leave the root field untouched between runs and only update the value field, then run Convert to produce the new CSS value; the previous copy badge is cleared as soon as any input changes.