Better Styles Through ems
29th November, 2016 —
CSS is vital to Better. The Better apps (iOS and Mac) are native apps that use web pages for their content. They’re the same pages you see on the Better site, but with specialised templates. Still, the content you see on the apps is largely HTML and CSS.
The pre-compiled architecture is fairly straight-forward:
- a common CSS file for styles that cover both the site and the apps
- a site CSS file that covers site-specific design elements such as the navigation, footer, and site homepage
- an app CSS file that covers rendering differences between the app(s) and site
Each of the CSS files is compiled into a global CSS file during the build process using first the common CSS file, and then either the app or site CSS files.
When we first launched Better, the iOS app had a coloured frame around the content (see below). The frame was in the native app, and meant the content viewport size was slightly different than when viewing the same content on the site in a web browser on the same device. It also meant the CSS required specific media queries to ensure more complex design elements, such as the statistics, would fit the viewport and still look good on narrow devices.
In September, Aral removed the coloured frame from the app interface. Firstly, this gave the interface a much cleaner and more spacious feel. It also meant the viewport widths were exactly the same whether you were looking at Better content in the app or in a web browser on the same device. This gave me the opportunity to overhaul the CSS, removing excess rules and repetition mostly caused by a gazillion media queries.
Changing the way I design for the web
In a yet-to-be-releasable redesign of my own site, I’d started experimenting with a new approach to units and measurements in my design and overall CSS. I started using
ems for every unit. Using
ems turned out to be easy, and made my CSS clean and simple, especially as I was writing the CSS from scratch. Using
ems isn’t new or revelatory in the web world. But it was always an approach I shied away from before.
rems and media queries, but these were usually compiled from pixel units. I abstracted away my inflexible pixel brain.
To a flexible everything with ems
As Better no longer needed so many media queries, the leap from
ems was straight-forward. Though from a visual perspective, it was hard to visualise the units as relationships between the type and space without starting from scratch. In order to better visualise the design in flexible units, it turned into a complete refactor.
I started by converting all
ems, then removing any subsequent media queries relating to those font sizes, instead using two media queries on the root:
With all font sizes scaling up from the root at 460px and 600px-wide viewports, every other rule using
ems will scale up too. Thanks to the cascade, the scaling is always in proportion to the font size. This makes most media queries redundant, with exceptions only when tweakpoints are required between or above these viewport sizes. Scaling with
ems requires fewer rules, and makes every rule proportional. It’s building on the existing flexibility of the web.
Then I took all the paddings, margins, max-widths, and anything else related to space or layout, and converted those units to
ems, removing their media queries too. I generally used the old
target/context = result rule. A
margin: 12px;, with a root
margin: 0.857142857em;. The decimals are ugly, and harder to visualise, so I rounded units as I re-factored. This makes the
margin: 0.857142857em; a much tidier
With barely any media queries, the CSS was easier to manage. It meant I could have a fresh look at the relationships between the type and the space, adjusting consistently across all the elements. When writing CSS, I first style based on the naked elements (
h1, h2… ul… p etc) themselves. (Heydon recently wrote a great article on the benefits of this approach.) Styling without classes is also necessary as most of our content is generated directly from markdown.
The few modules that rely on classes for more complex layouts and styles (such as the statistics below) didn’t need a million breakpoints either. The core typography and spacing of these modules were already adjusting to the available space derived from the base element CSS, so when refactoring, the rules only occasionally needed minor tweakpoints.