Mobile app version of vmapp.org
Login or Join
Sue6373160

: How to convert between Android DP and CSS px? I see this is probably a noob question, but it truly confuses me. I'm reading documents from the Google Material Design, along with some of its

@Sue6373160

Posted in: #Android #Css

I see this is probably a noob question, but it truly confuses me.

I'm reading documents from the Google Material Design, along with some of its implementations in css. The specification is written in Android's dp, while css codes uses px as a length unit.

What confuses me is that the css implementations often uses the exact value from specification, for example, a toast should have:


Single-line snackbar height: 48 dp tall

Minimum width: 288 dp

2 dp rounded corner


corresponding CSS:

min-height: 48px;
min-width: 288px;
...
border-radius: 2px;


In my current understanding, an Android DP is generally displayed at the size of one pixel on a 160dpi screen, while the CSS px is defined as a visual angle. So does a px happens to be the same as a dp when seeing in some distance? If so, is that a common pattern to use px as dp in css, or did I completely misunderstand the CSS code?

I know nothing about Android development before, and not a designer. Thanks for any help.

10.04% popularity Vote Up Vote Down


Login to follow query

More posts by @Sue6373160

4 Comments

Sorted by latest first Latest Oldest Best

 

@Phylliss782

There is no one right answer, there are actually two:


Recommended by Google (e.g. in Udacity course on Material Design): Use a simple conversion, which in many cases is 1:1 just like in Polymer library. It's not right for retina display for example, so rather than 1:1, use a density ratio provided in the device table in the official Material Design Guide(table with ratios and specific metrics for some popular devices) and provide suitable @media queries for resolution thresholds and assets, assuming that 1dp is equal 1px for a mdpi display (160dpi/ppi).


Note: overall idea: on the bottom of the page: Image scaling with some picture to visualize the ratios for multiple screen resolution thresholds (Breakpoint picture)


if you want an ultra consistency across your design for specific devices, you have to make some more research and calculation, and what's more important a pile of more @media queries in order to support as many devices as you want and provide fallback (with the method mentioned in the 1st place) for the ones you don't care so much.


Here is more detailed information for those wanting to dive into the topic more, but it's an explanation and logic behind, the above is a complete answer:

The thing is that "pixel density", according to Material Design's official guide (Layout > Units and measurements), is:


the number of pixels that fit into an inch.


So basically pixel density is a new name for a ppi value or since a lot of people do not recognize this as a separate thing, a dpi value.

Definition of 1dp according to the same guide:


A dp is equal to one physical pixel on a screen with a density of 160.
To calculate dp:

dp = (width in pixels * 160) / screen density

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


Core principal of Material design is to maintain consistent physical dimensions across different platforms, which raise the issue of the desktop resolution, ppi(/dpi) and the css pixel in which case you should stick with calculating the dp just like in case of the Android devices, and it's not true that most of the screens are 96ppi (it’s an assumption that is important for CSS), a great part of them has a bit higher ppi, and if you take into account not only traditional desktop but also a regular laptops, or the tablets, or the "convertibles" like Surface, there is a need for the conversion: they usually range from 100-130ppi, that said the one I’m using at the moment is 127ppi:

100% = 160ppi -> physical 1 pixel width = 1dp -> rectangle 100x100px = 100x100dp

79% = 127ppi -> physical 1 pixel width = ca. 0,8dp -> rectangle 100x100px = 80x80dp

Although dp is a pure and new unit just for Android, you should make some calculations in order to adapt the MD layouts which all come in dp. If you want to have some more idea how big will the specific element be in the physical sense the most useful for the purpose of the question is Ideal touch size range value in in Material Design guidelines for specific devices ** Below the dp value there is a physical one. **The dp value changes, but the physical stays the same.

The issue, why you need to calculate units, is further explained in Android API guide (Converting dp units to pixel units) and it still applies for elements styled with CSS:


In some cases, you will need to express dimensions in dp and then convert them >to pixels.

Imagine an application in which a scroll or fling gesture is recognized after the user's finger has moved by at least 16 pixels. On a baseline screen, a user's must move by 16 pixels / 160 dpi, which equals 1/10th of an inch (or 2.5 mm) before the gesture is recognized. On a device with a high-density display (240dpi), the user's must move by 16 pixels / 240 dpi, which equals 1/15th of an inch (or 1.7 mm). The distance is much shorter and the application thus appears more sensitive to the user.


The earlier mentioned Polymer conversion 1:1 is probably due to the fact that the density of 96dpi, or even the one that I gave is somewhere in low density or even (as in case of 96dpi) group, even below it. Taking into account that the dp value is not a css accepted, it's easier to assume that the density ratio (0,75- for low, 1,0 medium, and so on) is the one that should be used for simplification and multiple size screens support, which is shown in the device table for Material Design mentioned earlier. It's even mentioned as one the best practices in quoted above chapter of Android API guide. And that’s where Polymer conversion 1:1 might be good, since a lot of the devices have the density ratio at level 1.

Getting back to the last dilemma: the css px, if you decide to dive into subtle nuances of different devices. If you are a not so inquiring one, just stick with the Density ratio from the MD table. But if you are a perfectionist, this crux of CSS pixels and physical dimensions relation has a perfect (and pretty simple explanation) in a W3C Candidate Recomendation:


The absolute length units are fixed in relation to each other and anchored to some physical measurement. They are mainly useful when the output environment is known. The absolute units consist of the physical units (‘in’, ‘cm’, ‘mm’, ‘pt’, ‘pc’, ‘q’) and the visual angle unit (‘px’):

For reading at arm’s length, 1px thus corresponds to about 0.26 mm (1/96 inch).

Note: Note that 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 breaks the content.)


This new definition of px (taking into account the physical dimensions) fills the gap between CSS pixels and dps and lets us make sure that by using simple measurement calculations the so called output environment, which in this case is a consistent (in a physical sense) MD layout, stays the same across different devices and platforms. Moreover, both W3C and MD Guidelines use the low- and high-resolution device pictures to illustrate the core idea of pixel/dots coverage - more device pixels (dots) are needed to cover a 1px by 1px area on a high-resolution device than on a low-res one, which means that the widely used in CSS queries for retina display are indeed the same thing you have to provide (but with more thresholds) for Material Design and all mobile devices.

Concluding, either use the MD Density ratio which is best recommended practice by Google, or if you're fixated on precision or your design needs to be absolutely consistent about physical sizes: use the accurate conversion using ppi/dpi values of the specific or common devices (which is pretty insane), what you can easily test on Google resizer online tool since they respect the common thresholds suggested in MD Guide in the first place and division rules for the ratio and relevant display type names (xlarge, medium and so on) implemented in it.

So stick with the MD ratios from table remembering that the reference dp equal pixel size is for mdpi resolution (160) and you'll be good.

10% popularity Vote Up Vote Down


 

@Candy945

W3C says:


The px unit thus shields you from having to know the resolution of the device. Whether the output is 96 dpi, 100 dpi, 220 dpi or 1800 dpi, a length expressed as a whole number of px always looks good and very similar across all devices (...)


And altough it says:


To get an idea of the appearance of a px, imagine a CRT computer monitor from the 1990s: the smallest dot it can display measures about 1/100th of an inch (0.25mm) or a little more. The px unit got its name from those screen pixels.


It also says:


In fact, CSS requires that 1px must be exactly 1/96th of an inch in all printed output (...)


Taking into account that by default screen devices are configured as 96dpi, it is the best assumption on how browsers interpret a CSS pixel:

96 css-px = ~ 1 inch


And we know that in Android:

160 dp = ~ 1 inch


So:

96 css-px = ~ 160 dp
css-px-length = round(dp-length * 96 / 160)


And according to that:

min-height: 29px;
min-width: 173px;
...
border-radius: 2px; /* 2dp is 1.2px from the formula but it wont work */


Well, I thought that was right until I checked Google Polymer's Toast sizes:

min-height: 48px;
min-width: 288px;
padding: 16px 24px 12px;
box-sizing: border-box;
box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.26);
border-radius: 2px;
bottom: 12px;
left: 12px;
font-size: 14px;


So it is a 1 to 1 conversion, and from that we got that Android browsers use:

1 css-px = 1 dp


And 96 css-px per inch is used on other devices like desktops and laptops.

To conclude: css pixels are independent from device dpi and on Android devices 1 css-px is equal to 1dp.

10% popularity Vote Up Vote Down


 

@Ann6370331

I think the accepted is wrong. The css px is actually Device Independent Pixel(dip), and it is a common pattern to use px as dp in css.

10% popularity Vote Up Vote Down


 

@Frith110

I believe the full answer to your question can be found here:
stackoverflow.com/questions/2025282/difference-between-px-dp-dip-and-sp-in-android
To convert dp to px you need to take account of the display dimensions you are addressing to. The greater the DPI, the more pixels you'll have to cram in the same area to make it look good and to avoid pixelation:

ldpi: 1 dp = 0.75 px
mdpi: 1 dp = 1 px
hdpi: 1 dp = 1.5 px
xhdpi: 1 dp = 2 px
xxhdpi: 1 dp = 3 px
xxxhdpi: 1 dp = 4 px

E.g:

A 3x3 dp square in CSS or Photoshop needs to be:

2.25x2.25 px - ldpi
3x3 px - mdpi (Samsung ACE, Xperia X8)
6x6 px - xhdpi (Xperia S, Google Nexus 4)
9x9 px - xxhdpi (Samsung S4 - S5, HTC One)
12x12 px - xxxhdpi (this resolutin will be used on next generation devices)

Based on the above, your calculatins should look like this, using a 3x dp multiplier for XXHDPI screens:

min-height: 144px;
min-width: 864px;
...
border-radius: 6px;


Android automatically scales down images if it finds that the used device resolution is lower, so you are safe to develop with XXHDPI in mind, as it addresses the majority of today's high-end devices on the market.

Here is a simple converter to do the job for you: androidpixels.net/

10% popularity Vote Up Vote Down


Back to top | Use Dark Theme