[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!
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…
” …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)

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. ;-)