The Inch CSS Unit. 🧮

The Inch CSS Unit. 🧮

  • toucaan
  • 5 minutes
  • May 19, 2020

[Updated draft: June 08, 2020]

Ever used the inch CSS unit for modern web design?

No?

Well, let’s try and change that today:

/* Include on the <head></head> element. */
/* A portrait ⇋ landscape Toucaan switch media query. */
@import url('path/to/css/app/portrait/portrait.css') only screen and (orientation: portrait);

/* Notice the use of `in` (inches) on the environment queries below: */

/* portrait.css */
@media only screen and (max-width: 2in) {
  body{
    /*  All the style for a smartwatch or a very tiny mobile screen 
        goes in here. We don't use pixels for the Apple Watch because 
        its viewport is too small for the pixels to scale correctly. 
        Also, hardcoded values on @media-query breakpoints are somewhat 
        an antipattern now! */
    /*  Read web designing for the Apple Watch at: https://bubblin.io/blog/web-design-recommendations-for-the-apple-watch */
    /*  Read more at https://bubblin.io/blog/toucaan-introduction */
  }
}

@media only screen and (min-width: 2.000000000001in) and (max-width: 4in) {
  body{
    /* Smartphones and phablets in portrait mode.*/
  }
}

@media only screen and (min-width: 4.000000000001in) and (max-width: 8in) {
  body{
    /* Tablets and larger menu surfaces in portrait mode.*/
  }
}

/* and so on…*/

Wait, what did just happen?!

Can we use inches on screen CSS like that?

Well, yes and no both. But that doesn’t matter! Doesn’t the code above just read beautiful?

It is so natural to refer to layouts by their physical size. In inches.

1. We wanna serve the users on a 75" OLED TV. Mockup a 6" x 3" layout for it, will you?

2. I bought a 27" iMac. My app needs to cover a design space of 25" x 20" above the fold!

3. Is it an iPad Pro? Yes, a 10.5 incher! 

4. Wow, that is a large iPhone! Yeah, a Pro Max has a 6.5" screen!

5. A petite Apple Watch. Are we talking of a sub-inch UI here?

Inches practically tie our design language to the intended medium easily and it is so easy to talk about or reference in our regular day-to-day conversations. Wouldn’t it be nice to be able to compose web design using the same vocabulary?

An inch-wide button. A footlong header. 🤠

This would make speaking interactive design so much easier and accessible. Perhaps someday print and digital design could be even reconciled!


Yes, the newest wearables like the Apple Watch are also a part of the web. The new landscape of the web is quite different from the mobile web of five years ago. It makes a lot of sense for us to revisit the design principles from the past and rewrite or throwaway some of those rules to adapt for the new surfaces scalably.


But why yes and no both?

Did you notice the bug on the CSS media-query written above?

Props if you have already spotted it!

There is an embarrassing bug in CSS that has persisted since the very beginning of the Internet. A one that stems from how browsers implement absolute units like inch or centimeters across the board. Yes, even the modern ones have this issue!

This bug that has denied us the opportunity to use physical units for digital layouts for nearly four decades! The problem is that a css inch (in) on-screen media does not equal a real inch that you and I know of and use regularly. A css inch is something else altogether. It has no meaning or reliable value in the digital realm despite existence.

This means that specifying width: 1in; on our stylesheet doesn’t mean that the element painted on the DOM/window is going to be inch in width. And that’s why our beautiful-to-read MQ (media query) on the top will not work because it cannot ‘test’ for the size of a device in inches accurately.

The browser doesn’t know how much an inch is in absolute terms.

As per the definition of css inch (1in: 96px) an Apple Watch, for example, is 384px / 96px i.e 4 inches wide but that is not true at all. In fact in terms of pixels also, an Apple Watch is as wide as the first iPhone. But in reality, its glass is only an inch in size. About a third of the original iPhone.

That’s how things are on the web with absolute units right now.

A Soup of Implementations

When it comes to absolute units like mm, cm or in, implementations have been a major disappointment for the last 40 years. This isn’t a new bug or anything. It’s just that this issue hasn’t been spoken of enough (I think) and vendors aren’t paying attention to it anymore.

The last commit about an inch being equal to 96px (or 72px on the Mac) was pushed in the early 1980s, during the age of CRT monitors. And despite a few feeble voices that pop-up every now and then seeking a “fix”, we are still right here, stuck in the same era of hardcoded environment from four decades ago. It’s literally a time-capsule!

CSS Standard Update, 2011

In the past, CSS required that implementations display absolute units correctly even on computer screens. But as the number of incorrect implementations outnumbered correct ones and the situation didn’t seem to improve, CSS abandoned that requirement in 2011. Currently, absolute units must work correctly only on printed output and on high-resolution devices.

CSS doesn’t define what “high resolution” means. But as low-end printers nowadays start at 300 dpi and high-end screens are at 200 dpi, the cut-off is probably somewhere in between. (link)

So…

w3c: em, px, pt, cm, in…

” …if you are designing for print use physical units (in/mm), but if you are designing for the online medium use px, em or percentages.” (link)

And for this reason we cannot use in units for web design.

Or can we? 😏

Enter CSS Variables!

We’ll use css custom properties or css variables to teach the browser some standard units. Good thing is that the browser already knows a little about it, we just have to bring it up to speed.

IMO, inch is intrinsic to modern web design. Even if we used px, em or rem to style a webpage, physical inches have an influence over it. There is a non-zero correlation between how pixels shape-up and the size of the dot (pixel) depends on the physical size of the glass.

Actually, the term ‘size of a pixel’ can be a confusing reference. This is a tricky position to navigate, but stay with me. By definition a screen pixel has no size, no physical value or meaning outside of its mathematical construct, which is angular measurement of an object relative to its distance from the viewer’s eye and the physical size of the capturing frame, i.e. the screen.

But a pixel does have a size in the context of a screen. And it depends on only three parameters:

1. Pixel count (ppi/dpi), 
2. Height of the screen (H), and, 
3. Width of the screen (W).

“It is a part of a relationship between the physical screen size, expressed in inches, the screen resolution, expressed in pixel per inches and the pixel screen size, expressed in pixels.” – Sebastian Gabriel (link)

DPI Mac 27"

Practically speaking every device has its own pixel size (device pixel) and a boundary of ‘coordinate geometry’ to play with, i.e. pixel count and physical height and width. The collection of dots (or pixels) cover the entire area of the glowing glass, but we’ll skip the underlying math of how that works for each frame (paint-job) and that this is handled by the rendering engine.

Here’s a good read on what a pixel is if you’re interested.

Moving back to css, let’s declare a variable at the :root, like so:

/* The original inch:pixels correlation mapping from the 1980s. */
:root {
  --inch: 96px;
}

I am writing this article on a 15” Retina Macbook Pro (2017).

Since a retina display packs more pixels per inch, an inch of css inch i.e. 1in on my MBP appears shorter than the real measure.

But if we were to declare the --inch variable instead, like so:

/*  Notice the use of precise `resolution` or `device-pixel-ratio` instead of min/max.  */
@media (resolution: 192dpi) and (-webkit-device-pixel-ratio: 2) {
  :root {
    --inch: 130px;
  }
}

…the inch on our layout would scale correctly. And it would do so on all the 20 million MBPs with the same hardware on best resolve. Yay!

So we now have a better --inch:pixels mapping for a machine like mine. Not bad.

Notice that we haven’t tested for the size of the screen on the MQ above yet. For that let’s use our existing knowledge of css and wiggle out some zones to write the --inch: pixel mappings in. This way we can cover as many hardware as possible:

@media only screen and (min-width: 320px) {
  /* Small screen, non-retina */
}

@media
only screen and (-webkit-min-device-pixel-ratio: 2)      and (min-width: 320px),
only screen and (   min--moz-device-pixel-ratio: 2)      and (min-width: 320px),
only screen and (     -o-min-device-pixel-ratio: 2/1)    and (min-width: 320px),
only screen and (        min-device-pixel-ratio: 2)      and (min-width: 320px),
only screen and (                min-resolution: 192dpi) and (min-width: 320px),
only screen and (                min-resolution: 2dppx)  and (min-width: 320px) { 

  /* Small screen, retina, stuff to override above media query */

}

@media only screen and (min-width: 700px) {

  /* Medium screen, non-retina */

}

@media
only screen and (-webkit-min-device-pixel-ratio: 2)      and (min-width: 700px),
only screen and (   min--moz-device-pixel-ratio: 2)      and (min-width: 700px),
only screen and (     -o-min-device-pixel-ratio: 2/1)    and (min-width: 700px),
only screen and (        min-device-pixel-ratio: 2)      and (min-width: 700px),
only screen and (                min-resolution: 192dpi) and (min-width: 700px),
only screen and (                min-resolution: 2dppx)  and (min-width: 700px) { 

  /* Medium screen, retina, stuff to override above media query */

}

@media only screen and (min-width: 1300px) {

  /* Large screen, non-retina */

}

@media
only screen and (-webkit-min-device-pixel-ratio: 2)      and (min-width: 1300px),
only screen and (   min--moz-device-pixel-ratio: 2)      and (min-width: 1300px),
only screen and (     -o-min-device-pixel-ratio: 2/1)    and (min-width: 1300px),
only screen and (        min-device-pixel-ratio: 2)      and (min-width: 1300px),
only screen and (                min-resolution: 192dpi) and (min-width: 1300px),
only screen and (                min-resolution: 2dppx)  and (min-width: 1300px) { 

  /* Large screen, retina, stuff to override above media query */

}

That’s it!

Now we can add hardware-specific mappings as necessary to help the browser understand the inch. And use the variable on our layouts peacefully. I have turned this write-up into a tiny browser polyfill called --inch that supports several commonly available devices. This library can be included at the :root of the webpage to start using inch or centimeters on your layout.

Feel free to submit PRs to add new mappings if your hardware/browser combination isn’t already included. Given that the CSS aims for the best compromise to serve the maximum percentage of users, I think we can start, or at least consider, using inches within an acceptable margin of error.

However, the ideal would be when the vendors adopt providing these units correctly.

As far as disclaimers go, I must explicitly state here that this article and its accompanying library is an exploratory exercise. And you should probably not use it in production.

Not until Toucaan is ready to fly on its own at least. ;-)

About the author

Marvin Danig

I write code with my bare hands. 💪🏻 Yammer about Bubblin all day.

https://bubblin.io/marvin