zumra-mobile / docs/background/webview.md
WebView
Zumra Mobile Apps for Android & iOS
WebView
We show the message list inside a browser environment, in a WebView
component.
Styling
The message list styles are controlled by two files:
src/webview/css/css.js and src/webview/static/base.css.
Lengths: px vs rem; no em
For CSS lengths in the webview, we use the two units px and
rem. We do not use em.
Specifically, we use rem for the size of text, and px for
everything else. See our style guide for more details.
We do this because it implements in the webview the same behavior that's standard for native mobile apps, and because it's important for accessibility. Detailed reasoning is below.
Background on what each unit means:
-
A length in
pxis exactly that many logical pixels. In particular this is an approximately constant physical length across devices, and across different system settings:16pxis approximately 0.1 inches or 2.5mm, and might be as large as about 0.13 inches or 3.2mm. -
A length in
remscales with the font size at the root of the document, which in turn scales with the system font-size settings. By default1remequals16px, but depending on user settings it can be a bit smaller or much, much larger. In particular, many visually impaired users set their devices to a very large font size. -
A length in
emscales with the font size of the current element or its parent (depending on what property it's used for.) This is likeremexcept it depends additionally onfont-sizevalues found elsewhere in the stylesheet.
Why rem and not em
When em is used, it becomes complicated to understand what length
the value found in a given rule actually works out to -- and the
answer can even vary for a single rule as applied in different places.
In a website with a variety of design contexts where different kinds
of text appear with different sizes, and with detailed text style
rules that appear across multiple kinds of text, that variation can
potentially be a useful feature. This is what em is for and why
some web-design advice urges using it.
In our message list, there is just one kind of text that appears at
significant length: the message bodies. Other text comes in small
pieces, and in highly structured contexts like timestamp pills or the
emoji + counts in reactions. There are few if any style rules
affecting text in multiple contexts (and if there are, that's likely a
bug), which means little to no benefit to be had from letting a rule's
meaning vary across contexts. Meanwhile, using em means a major
cost in comprehensibility as the reader has to do a global search for
font-size rules that might apply to ancestors of the given element.
At one time (before 6ef229e42) our CSS had a chaotic mixture of
values in em and px. Because of the variation in font-size and
correspondingly in the meaning of em, this meant that to understand
what a given length meant, and what the constraints were on changing
it, was a complicated matter. That in turn made it hard to make
changes, and easy to introduce small bugs.
For more discussion, see the following articles:
- https://zellwk.com/blog/rem-vs-em/ (detailed background, and examples of several approaches)
- https://j.eremy.net/confused-about-rem-and-em/ (advises
em, for web design with a variety of kinds of complex text)
Why (mostly) px and not rem
Typical advice for web design is to use rem or em for nearly all
lengths. This means that when the font size grows or shrinks, not
only the text but the whole layout scales with it, including padding,
margin, and images.
But on mobile, if you go to a device's settings and change the font size, you'll find this is not at all what apps do. When you make the font size giant, the text in an app grows with it -- but everything that isn't text stays the same. Icons in the UI; user avatars; padding around text; padding or margin between elements; indentation of items in a list; all stay exactly the same. This is true on Android and iOS, and of flagship apps from Google, Apple, Facebook, and others.
On Android, an app implements this behavior by using sp for text and
dp for everything else, following the upstream recommendation; see
our layout.md.
In a webview, this translates to using rem for text and px for
everything else. So that's what we do.
To understand why this is the standard on mobile, consider that mobile screens are often small and the layouts don't have a lot of room to spare. If when a user doubled their text size to make it readable for them, that also doubled all the spacing in the UI... then that could leave very little room for the actual text they wanted to read. See our commits ebaffb456 and 3dc7fee83 for discussion.