← Back to list

CSS Doesn’t Know What a Centimeter Is

“In theory, theory and practice are the same. In practice, they are not.” — Albert Einstein

Michael Navasardyan · 2026-03-14 20:58 · 2 claps · 4.7 min read
#css #chrome-extension #centimeter #front-end-development #rulers
Open on Medium ↗
Wiki topics: 🌐 · Web Development

CSS Doesn’t Know What a Centimeter Is

“In theory, theory and practice are the same. In practice, they are not.”

  • — Albert Einstein*

Photo by Raghav Modi on Unsplash

Photo by Raghav Modi on Unsplash

I once decided to develop a On-screen Ruler Chrome Extension, to provide an opportunity for browser users to measure some widely-known real-world units(millimeters centimeters, inches) on the screen. Since CSS already supports these units, I initially used them to render the ruler marks. But when I compared the result with a real physical ruler, I noticed something unexpected — the measurements didn’t match.

The Illusion of Physical Units in CSS

CSS defines several units that appear to represent real-world measurements: in — inches, cm — centimeters, mm — millimeters, etc. At first glance, these seem like true physical units. If you set an element to 1cm, you might reasonably expect it to be exactly one centimeter on the screen. However, browsers don’t measure your monitor to determine the real size of these units. Instead, CSS defines them mathematically based on a fixed assumption:

1in = 96px

Why Browsers Assume 1in = 96px

If CSS physical units aren’t truly physical, where did this rule come from?

In the 1990s, most desktop monitors had a pixel density close to 90–100 pixels per inch. Many applications were already designed with the assumption that 96 pixels roughly corresponded to one inch on the screen.

When CSS specifications were later formalized by the **World Wide Web Consortium (W3C), they needed a consistent relationship between physical units and pixels**. Without such a rule, layouts using cm, mm or in, could behave unpredictably across browsers.

That is, when dealing with physical measurements, css takes 96 PPI (pixels per inch) as a base for construction of real-world measurement units. In other words, it assumes your monitor has specific pixel density, and all those CSS values are going to match with real ones only when users monitor has 96 PPI. This worked reasonably well in the early days of the web when most monitors had similar densities.

From that, all other physical units are derived as well (1cm ≈ 37.8px, 1mm ≈ 3.78px)

Modern Displays Broke the Assumption

Today we have high-resolution 4K monitors, Retina displays, laptops with 200+ PPI, different screen sizes with the same resolution. Eventually, those assumptions are not applicable for modern monitors and not only. Thus, CSS units are consistent within the layout system, but not accurate in the physical world. So when I put a real ruler on a monitor, my extension on-screen virtual ruler didn’t match with it.

Why the Browser doesn’t Know PPI of Each Device

You might wonder: why doesn’t the browser simply detect the real physical dimensions of the screen?

The problem is that browsers typically don’t have access to reliable information about:

  • the physical width, height, diagonal of your monitor
  • the true pixel density (PPI)

The browser usually knows instead is only

which are not enough for having a real-world measurement on the screen, at least one physical dimension of the device is needed.

Reconstructing the Real Measurement

While building the extension, I needed a way to convert virtual pixels into real physical units.

If the browser doesn’t know the screen size, could we calculate it ourselves. Surprisingly, the answer is yes — with just one piece of information: The monitor’s diagonal size. Most people already know this value because monitor sizes are typically advertised like 24", 27", 32", etc.

Once we know the diagonal size and the screen resolution, we can calculate the true pixel density of the display.

Step 1 — Get the Screen Resolution

The browser already exposes the screen resolution in pixels:

const width = screen.width
const height = screen.height

But wait! There is another problem as well

In modern browsers, layout does not use hardware pixels directly. Instead it uses virtual unit called CSS pixel. It represents a logical layout unit, not an actual screen pixel. So measurement flow becomes like

Fortunately, browsers do expose one piece of information that reflects this scaling: devicePixelRatio = physical pixels / CSS pixels. It tells us how many physical pixels are used to display a single CSS pixel.

devicePixelRatio = 2

means 1 CSS pixel = 2 physical pixels. So real physical dimensions in pixels should be

const realPxWidth = screen.width / window.devicePixelRatio
const realPxHeight = screen.height / window.devicePixelRatio

Step 2 — Calculate Real Pixel Diagonal

const realPxDiagonal = Math.sqrt(realPxWidth ** 2 + realPxHeight ** 2)

Step 3 — Calculate Real Pixel Density

const PPI = realPxDiagonal / realInDiagonal

and as one inch equals to 2.54cm,

const pixelsPerCm = PPI * 2.54

Now we know the real pixels per inch of the display — essentially the conversion rate that allows us to translate virtual measurements into real-world units.

Calibration on My Laptop Example

const diagonalInches = 15.6

// Dimensions in logical pixels
const logicalWidth = screen.width / window.devicePixelRatio // 1440 / 2 = 720
const logicalHeight = screen.height / window.devicePixelRatio // 810 / 2 = 405
// Diagonal in logical pixels
const diagonalPx = Math.sqrt(logicalWidth**2 + logicalHeight**2)
// √(720² + 405²) ≈ 825 px
// PPI in terms of CSS/logical pixels
const ppi = diagonalPx / diagonalInches
// 825 / 15.6 ≈ 52.88 px/in
// Convert to px per cm
const pxPerCm = ppi / 2.54
// 52.88 / 2.54 ≈ 20.8 px/cm

So CSS assumes 1 inch = 96 px (≈38 px/cm), but on my laptop 1 inch is actually about 53 CSS px (≈20 px/cm).

Demonstration of the Ruler Extension

Demonstration of precise mode of the chrome extension On-screen Ruler

Top block is just a div, which has

and 2 versions of the On-screen Ruler, A is painted based on the css assumption (1in = 96px), B — in precise mode (calibrated with real diagonal of the device in inches and OS scaling/Browser zoom). Obviously there is tangible difference between 20cm that CSS assumes and real one (almost 1cm deviation).

Here is the snippet from the extension codebase that one might use to detect real PPI of his monitor.

const getPPIByDeviceDiagonalInInches = (
 diagonalInInches: number, 
 scale: number
) => {
 const widthInPx = screen.width / scale
 const heightInPx = screen.height / scale
 const diagonalInPx = Math.sqrt(widthInPx ** 2 + heightInPx ** 2)
 const ppi = diagonalInPx / diagonalInInches
 return ppi
}

Summary

CSS units like cm, mm, and in exist mostly for historical compatibility. In modern displays with high-DPI screens, OS scaling, and browser zoom, they no longer correspond to real physical measurements.

Knowing the screen diagonal of the device, we can adjust and precisely paint physical units on it.

Curious about real-world measurements on your screen without diving into the technical details of OS, browser, or CSS? Try On-screen Ruler Chrome extension, and if you enjoyed this stuff, you might support development on Patreon.😌

Originally published at https://medium.com on March 14, 2026.


메타데이터
post_id
d6f40e60bb35
slug
css-doesnt-know-what-a-centimeter-is-d6f40e60bb35
url
https://medium.com/@michaelnavasardyan/css-doesnt-know-what-a-centimeter-is-d6f40e60bb35
canonical_url
https://medium.com/@michaelnavasardyan/css-doesnt-know-what-a-centimeter-is-d6f40e60bb35
author_url
https://medium.com/@michaelnavasardyan
status
ok
fetched_at
2026-06-25 16:53:31