115

For Android, people recommend using dp (density independent pixels) measurements for UI elements, and there are conventions that exist such as using 48dp for a button height, etc.

I'm working on a web application, and I'm getting a lot of criticism on the UI design saying it does not conform with Android design standards. Obviously, my application is going to look different since it is using CSS and HTML instead of the Android Holo theme, but I would still like to make it conform as much as possible. However CSS does not allow density independent measurements.

When I test my application on different resolutions and pixel densities, it does not look good, and sometimes, it is way out of proportion so it's not even functional. CSS doesn't have dp units like Android native development does, but I was wondering what some alternatives are.

Can I somehow get the pixel density using Javascript and manually scale everything appropriately? What is the best way for making a web app that looks and works nicely on all resolutions/densities?

Dupocas
  • 20,285
  • 6
  • 38
  • 56
Brad
  • 10,015
  • 17
  • 54
  • 77
  • 5
    CSS's `px` is the same as `dp` on Android. [According to the CSS3 spec. on units and values](http://www.w3.org/TR/css3-values/#absolute-lengths). – omninonsense Jul 30 '15 at 06:35

9 Answers9

225

I disagree with the currently accepted answer. As uber5001 suggests, a px is a fixed unit, and in a similar spirit to the efforts of the Android-specifc dp.

Per Material's spec:

When writing CSS, use px wherever dp or sp is stated. Dp only needs to be used in developing for Android.

Additionally

When designing for the web, replace dp with px (for pixel).

JStanton
  • 425
  • 5
  • 12
Tohuw
  • 3,630
  • 5
  • 22
  • 24
  • 29
    This is answer. +1 for quoting the Material spec. – Qix - MONICA WAS MISTREATED Jul 31 '15 at 22:11
  • -1, px is not a fixed unit. 1px = 1/96th of 1in, but 1in = 96px. pixel is the base unit, not the inch. Yes it is weird, but I actually tested it. I changed an element dimension from px to mm and the ratio between how it appeared on desktop and mobile hasn't changed at all. The accepted answer is the most correct. – Maciej Krawczyk May 15 '16 at 09:57
  • 2
    From MDN: "The unit in doesn't represent a physical inch on screen, but represents 96px. That means that whatever is the real screen pixel density, it is assumed to be 96dpi. On devices with a greater pixel density, 1in will be smaller than 1 physical inch. Similarly mm, cm, and pt are not absolute length." https://developer.mozilla.org/en/docs/Web/CSS/length#CSS_units_and_dots-per-inch – Maciej Krawczyk May 15 '16 at 10:17
  • @MaciejKrawczyk What were you trying to say by `1px=1/96"` but `1"=96px`? Should one of these be *not equals*. The latter maybe? As in `1"≠96px` physically? – Robert Koritnik Sep 15 '16 at 16:05
  • 1
    CSS inch and physical inch are 2 different things. 1 CSS inch is always 96px, regardless of screen density. So only on a 96 dpi monitor could CSS inch and physical inch be considered equal. – Maciej Krawczyk Sep 15 '16 at 16:51
  • 1
    @MaciejKrawczyk I understand the base of your contention about the disparity in scale on px. I could argue on about how a px is indeed a fixed unit, and the scale you involve doesn't change this base truth, but that's a red herring. The reality is the Material spec directly states to use px wherever dp is suggested. Given Brad asked about Android design standards, I provided the canonical, and thus correct, answer. – Tohuw Oct 06 '16 at 02:45
  • 2
    The recent update (May 2018) to material design explains Pixel Density in more depth https://material.io/design/layout/#pixel-density – Squiggle May 15 '18 at 07:53
24

http://www.w3.org/TR/css3-values/#lengths

The closest unit available in CSS are the viewport-percentage units.

  • vw - Equal to 1% of the width of the initial containing block.
  • vh - Equal to 1% of the height of the initial containing block.
  • vmin - Equal to the smaller of vw or vh.
  • vmax - Equal to the larger of vw or vh.

The only mobile browser to be aware of that doesn't support these units is Opera. http://caniuse.com/#feat=viewport-units

cimmanon
  • 67,211
  • 17
  • 165
  • 171
  • Are those units displayed properly when deploying in iOS ? – jmhostalet Apr 24 '14 at 14:13
  • @jmhostalet No, it causes the browser to go into a sort of infinite loop since the viewport height is dynamic. – rookie1024 Nov 08 '14 at 04:45
  • 8
    this answer is incorrect, because the `px` unit in css is (counter-intuitively) actually already pixel density independent -- "a css pixel is a not a pixel", there are plenty of articles about this – ChaseMoskal Dec 16 '18 at 01:46
24

Use rem.

It is the font size of the root element and a very good base unit for the size of other UI elements.

If one used the same absolute size (in centimeter), the text and other elements would be much too big on mobile or much too small on desktop.

If one used the same amount of pixels, the text and other elements would be much too small on mobile or much too big on desktop.

The rem unit is on spot because it says "Hey, this is how big normal text should be." Basing the size of other UI elements on this is a pretty reasonable choice.

Konstantin Schubert
  • 3,242
  • 1
  • 31
  • 46
20

In CSS3 it may be more accurate to say that the web doesn't have Android's px. The spec for CSS3's px says this:

pixels; 1px is equal to 1/96th of 1in

px might be the measurement you want, in the future.

Emile Bergeron
  • 17,074
  • 5
  • 83
  • 129
uber5001
  • 3,864
  • 4
  • 23
  • 44
16

As of CSS3, there are no CSS units that are truly device-independent. See the W3C spec on absolute lengths. In particular, the absolute units might not match their physical measurements. From the spec:

Note: If the anchor unit is the pixel unit, the physical units might not match their physical measurements. Alternatively if the anchor unit is a physical unit, the pixel unit might not map to a whole number of device pixels.

Note: This definition of the pixel unit and the physical units differs from previous versions of CSS. In particular, in previous versions of CSS the pixel unit and the physical units were not related by a fixed ratio: the physical units were always tied to their physical measurements while the pixel unit would vary to most closely match the reference pixel. (This change was made because too much existing content relies on the assumption of 96dpi, and breaking that assumption broke the content.)

If physical units were true to their purpose, you could use something like points; points are close enough to dps:

1 in = 72 pt
1 in = 160 dp

1 dp = 72 / 160 pt

If you use SCSS, you can write a function to return in pts:

@function dp($_dp) {
  @return (72 / 160) * $_dp + pt;
}

And use it:

.shadow-2 {
  height: dp(2);
}
Mihai Danila
  • 2,229
  • 1
  • 23
  • 28
10

What about a interface based on rem units?

I'm not experienced enough on the matter to confirm, but I think you could make some math based on the viewport size to apply a font-size in the root element and the entire interface would adjust accordingly. This stuff is a bit of witchcraft to me yet.

Darlan Alves
  • 503
  • 5
  • 13
1

Why not use points, it is a consistent size across devices. And is relative to the screen size. Most are not familiar with it since it comes from traditional publishing.

1

It's 2023 and responsive web design with breakpoints that target device widths are the best practice to anticipate changes to screen and appropriate sizes for typography. An alternative to using break points to adjust font sizes is to load discrete CSS files per device, so separate sets of CSS exist in parallel for each width. This latter however is a nightmare to maintain, and simply keeping CSS written with breakouts for breakpoints together keeps everyone sane and everything tidy.

That all said, use PX, reduce font sizes for smaller screens with breakpoints, and let the devices themselves handle the smoothing.

Having lived in the world of relative units where sub-elements refer up a level for their size reference so 1em at the root level and 1em two levels down the child hierarchy / DOM are not the same is another recipe for madness.

Melissa
  • 11
  • 1
0

What about use some mix between vw ( screen's width for any device) and em? Here font-size is changing dynamically, depending your device screen width. Use in your main CSS file next rule:

font-size: calc(100vw * 10 / 375);

(width for iPhone 6/7/8 is 375px, change it to 320px (iPhone5) and etc)

In all cases it is going work perfect. There is only one minus. If your goal is "pixel perfect", then you need to use big numbers after dot.

Example: your goal is font-size h5: 18px on all screens.

Then your perfect "em" will be:

h5 { 
 font-size: 1.79904em;
 }

without perfection use 18 / 10:

h5 { 
 font-size: 1.8em;
 }

According to Google Chrome you get 18.0096px;