The Curious Case of Android Font Size

Mihir Patel
5 min readApr 13, 2019

--

Scratching your head over font size for different screens in your new Android app? Use “sp” for font size and “dp” for margins, that’s the Law. But is it that straight forward? Well, not really.

Basics first

“dp” — Density-independent Pixel — An abstract unit based on the physical density of the screen. The unit which is relative to a dpi (dots per inch) screen, on MDPI devices 1dp is roughly equal to 1px. When running on a higher density screen, the number of pixels used to draw 1dp is scaled up by a factor appropriate for the screen’s dpi. Likewise, when on a lower density screen, the number of pixels used for 1dp is scaled down. More on these scaling later. Using dp units is a simple solution to making the view dimensions in your layout resize properly for different screen densities. That is, dp for margins.

“sp” — Scale-independent Pixels — Has everything which “dp” got, but gets scaled by the user’s font size preference. Recommended unit for font sizes.

Clear enough, let’s use sp for font size and see results in different font preferences.

As expected, “sp” adopts the user’s font preference and ramps up the font size accordingly. While the idea of “sp” fonts has a good heart but is a poor idea. From a design point of view, using “sp” is not the right thing to do.

Now, let’s break the law and use “dp” instead of “sp”.

Looks better, isn’t it?

Why go for “dp” whereas it is not recommended unit for font size?

Because going forward with “sp” may end up breaking your beautiful design if the user has some wonky font size preference. Moreover, the user may end up blaming your app for not handling this and not their own life choice!

That’s not it. We can still have more superior control over this by using pixels(“px”) instead of “dp”.

We can define custom font size by declaring how much pixels should it accommodate in different density screens. This is more like “dp” only but with your custom scale factor.

To define a custom scale factor, let’s first understand how “dp” is scaled.

MDPI is a base scale (1x)

LDPI is 0.75 x MDPI

HDPI is 1.5 x MDPI

XHDPI is 2 x MDPI

XXHDPI is 3 x MDPI

XXXHDPI is 4 x MDPI

Now let’s define a font size name “font_size_m”, and declare it in the respective dimen folder.

MDPI

<dimen name="font_size_m">14px</dimen> <!--1X-->

LDPI

<dimen name="font_size_m">10.5px</dimen> <!--LDPI = (MDPI*0.75)-->

HDPI

<dimen name="font_size_m">21px</dimen> <!--HDPI = (MDPI*1.5)-->

XHDPI

<dimen name="font_size_m">28px</dimen> <!--XDPI = (MDPI*2)-->

XXHDPI

<dimen name="font_size_m">42px</dimen> <!--XXDPI = (MDPI*3)-->

XXXHDPI

<dimen name="font_size_m">56px</dimen> <!--XXXDPI = (MDPI*4)-->

This conversation is the same as how dp is scaled as per different screen sizes, but here we get an upper hand by varying number of pixels for particular screen size. For example, the font size we declared will occupy 21 pixels in HDPI screen size, if you feel 21 pixels are more, you can reduce the number of pixels or more until it fits into your design.

Let’s again take a previous example but with different DPI screens.

XXHDPI looks fine but the text in HDPI looks HUGE.

dimen.xml(XXHDPI)

<resources><!--XXDPI = (MDPI*3)-->
<dimen name="font_size_xxxl">150px</dimen>
<dimen name="font_size_xxl">120px</dimen>
<dimen name="font_size_xl">90px</dimen>
</resources>

dimen.xml(HDPI)

<resources><!--HDPI = (MDPI*1.5)-->
<dimen name="font_size_xxxl">75px</dimen>
<dimen name="font_size_xxl">60px</dimen>
<dimen name="font_size_xl">45px</dimen>
</resources>

Now, as we have control over how much pixels it should occupy in particular screen density, let’s reduce the number of pixels for HDPI only and see results.

For each font size in HDPI, reduced number of pixels by 15.

dimen.xml(HDPI)

<resources><!--HDPI = (MDPI*1.5)-->
<dimen name="font_size_xxxl">60px</dimen>
<dimen name="font_size_xxl">45px</dimen>
<dimen name="font_size_xl">30px</dimen>
</resources>

This one looks neater than the previous image, as we have reduced pixel count. This change will affect only HDPI devices, XXHDPI and rest of configurations remain as it.

The question still remains, why “sp” is recommended unit for font size then?

Because it considers the font size preference of the user. This is the only primary reason for it, while I appreciate the point of using “sp”, this cannot be used when you are building an app which has complex design and you cannot compromise on even a pixel.

It all comes down to a preference of developers/designers of the app that how they want their app to look on different screens and if preference should be given to the user or not.

How big players are doing it?

Here is a comparison of how Reddit & Swiggy have their own approach to font size.

Comparison of Reddit on the Same device with different font preferences

Reddit is primarily used for content consumption, for them, it makes sense to go with “sp” approach, where preference is given to the user. It’s clearly seen in comparison that what happens when the user increases font size.

Comparison of Swiggy on the Same device with different font preferences

Here is what Swiggy does. They’re rigid, they don’t care what preference user has, their design stays as it is, no matter what font size you choose. They’re focusing on containing too many elements in a screen, if they had used “sp”, their design would have been completely messed up in case of larger font size.

Conclusion

There is no definite rule for what unit of font size should be used. It depends on the preference of the developer/designer and the complexity of the design. In our app Hush, we followed a mixed approach. We defined our own scale factors where it was necessary and used “sp” as well.

I hope this article will be helpful in designing your app. I would love to hear your comments/suggestions/corrections/questions!

--

--