Commit 41896ebd authored by Laura Kalbag's avatar Laura Kalbag
Browse files

Initial add of blog post about CSS overhaul on Better

parent c480f4a4
<!DOCTYPE html>
<html lang='en'>
<meta charset='utf-8'>
<meta name='viewport' content='width=device-width,initial-scale=1' />
<title> Labs - Blog - Overhaul to Better’s CSS</title>
<!--[if lte IE 8]>
<script src=''></script>
<link rel='shortcut icon' href='/favicon.ico'>
<link rel='apple-touch-icon' href=''>
<link rel='apple-touch-icon' sizes='76x76' href=''>
<link rel='apple-touch-icon' sizes='120x120' href=''>
<link rel='apple-touch-icon' sizes='152x152' href=''>
<link rel='apple-touch-icon' sizes='152x152' href=''>
<link rel='alternate' type='application/rss+xml' title=' Labs Blog' href='' />
<link rel='stylesheet' href=''/>
<link rel="stylesheet" href="../css/highlight/kimbie.dark.css">
<link rel='stylesheet' href='../css/styles.css'/>
<script src="../js/highlight.pack.js"></script>
<body class='labs labs-blog'>
<nav class="site-navigation">
<ul class="site-navigation--list">
<li class="home-link">
<a href="">Home</a>
<li class="about-link">
<a href="">About</a>
<li class="labs-link">
<a href="">Labs</a>
<li class="forum-link">
<a href="">Forum</a>
<li class="videos-link">
<a href="">Videos</a>
<li class="news-link">
<a href="">News</a>
<li class="fund-link">
<a href="">Fund</a>
<nav class='sub-navigation labs-navigation'>
<ul class='sub-navigation--list'>
<li class='projects-link'><a href='../../'>Projects</a></li>
<li class='blog-link'><a href='../'>Blog</a></li>
<div class='main h-entry'>
<h1 class='p-name long-title'>Overhaul to Better’s CSS</h1>
<p class='post-date dt-published' datetime='2015-11-25 11:55:00'>25th November, 2016 — <span class='p-author'>Laura Kalbag</span></p>
<div class='e-content'>
<p>CSS is vital to Better. The Better apps (iOS and Mac) use web pages for their content. They’re the same pages you see on the Better site, but with slightly different templates allowing the apps to make appropriate use of their native technology. Still, the content you see on the apps is largely HTML and CSS. The pre-compiled architecture is fairly straight-forward:</p>
<li>a common CSS file for styles that cover both the site and the apps</li>
<li>a site CSS file that covers site-specific design elements such as the navigation, footer, and site homepage</li>
<li>an app CSS file that covers rendering differences between the app(s) and site</li>
<p>All the CSS is compiled into a global CSS file during the build process using the common CSS, and either the app or site CSS depending on its destination.</p>
<h2>The opportunity</h2>
<p>When we first launched Better, the iOS app had a coloured frame around the content. The frame was in the native app, and meant the content viewport size was slightly different than 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.</p>
<p> <a href="">image of old and new app layouts side-by-side</a></p>
<p>In September, Aral removed the coloured frame from the app interface. Firstly this gave the interface a much cleaner and spacious feel, but 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. This gave me the opportunity to overhaul the CSS, removing excess rules and repetition mostly caused by a gazillion media queries.</p>
<p>Skip to the CSSing.</p>
<h2>Changing the way I design for the web</h2>
<p>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 <code>em</code>s for everything. Using <code>em</code>s turned out to be easy, and made my CSS clean and simple, especially as I was writing the CSS from scratch. Using <code>em</code>s isn’t new or revelatory in the web world. But it was always an approach I shied away from before.</p>
<p>I’m pretty good at CSS. You don’t get away with being this bad at JavaScript without knowing CSS very well (and being modest.) Still, it’s taken me a long time to relinquish control over the pixel precision-based thinking learned through years of designing in bitmap graphic software. One can take the Photoshop away from the woman, but you can’t take the Photoshop mindset out of the woman. Even though I hadn’t designed in Photoshop in nearly a decade, had used vector graphic software, had jumped on responsive web design as soon as I heard about it, my brain still thought, and designed, in pixels. When I read anything new about responsive design and other development approaches, I took them on board, but I still envisioned my work as pixels mapped in the canvas space. I used <code>rem</code>s and media queries, but these were usually compiled from pixel units. I abstracted away my inflexible pixel brain.</p>
<h2>To a flexible everything with <code>em</code>s</h2>
<p>As Better no longer needed so many media queries, the leap from <code>rem</code>s and <code>px</code> to <code>em</code>s was straight-forward. Though from a design perspective, it was harder 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.</p>
<p>I started by converting all <code>font-size</code>s to <code>em</code>s, then removing any subsequent media queries relating to those font sizes, instead using two media queries on the root:</p>
/* ↓ root size */
font-size: 14px;
line-height: 1.5;
@media only screen and (min-width: 460px)
font-size: 16px;
@media only screen and (min-width: 600px)
font-size: 18px;
<p>This makes all font sizes scale up proportionally at 460px and 600px viewport widths.</p>
<p>Then I took all the paddings, margins, max-widths, and anything else related to space or layout, and converted those units to <code>em</code>s, removing their media queries too. I generally used the old <code>target/context = result</code> rule. So the <code>margin: 12px;</code> when the root <code>font-size</code> was <code>14px</code> became <code>margin: 0.857142857em;</code>. The decimals are ugly, and harder to visualise, so I rounded units to the nearest .5 or .25 as I re-factored. This makes the <code>margin: 0.857142857em;</code> a much tidier <code>margin: 0.85em;</code>.</p>
<p>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. I first style based on the naked elements (<code>h1, h2… ul… p</code> etc) themselves. (<a href="">Heydon recently wrote a great article on the benefits of this approach</a>.) Styling without classes is also necessary as most of our content is generated directly from markdown.</p>
<p>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.</p>
<p><a href="">screenshot of statistics</a></p>
<p>Once the rest of the layouts were relying on <code>em</code> units, I could make any icons (which are SVG background images) use <code>em</code>s for their sizing too. Using <code>em</code>s for SVG icons make perfect sense, as they’re vector anyway, and means they can then scale to the text around them.</p>
<p>The <a href="">Spotlight page</a> has its own CSS applied on top of the global styles, as it has a custom design for each issue. In refactoring to use <code>em</code>s, I again removed a load of CSS (100 lines exactly) that wasn’t necessary now the base elements were more flexible. Cascade FTW.</p>
<h2>A bit of vw</h2>
<p>In the spirit of refactor, I went all-out. On the current <a href="">Spotlight page</a>, we have a big “Bait!” headline, filling the width of the main container. It was a perfect opportunity to replace a load of media queries with <code>vw</code> units for the <code>font-size</code>. The only additional CSS needed was a media query to ensure it doesn&#39;t exceed the width of the container when the viewport is wider than the container.</p>
<pre><code>body.spotlight h1.headline
/* ↓ fallback */
font-size: 8em;
font-size: 36vw;
line-height: 1;
@media only screen and (min-width: 600px)
body.spotlight h1.headline
font-size: 13.2em;
<h2>Better SVGs</h2>
<p>Getting all overexcited with stripping out unnecessary CSS, I decided to do the same with our graphics too. Last month I read <a href="">Chris Coyier’s Practical SVG</a> which helped me understand the ins-and-outs of SVG much better. To help grok as I was learning, I created a little find-and-replace script to scrub all the junk out of a generated SVG file to keep it nice and small. One of Chris’ simplest tips was removing excess decimals from the path points. This alone can halve the size of an SVG.</p>
<pre><code><?xml version="1.0" encoding="UTF-8"?>
<svg width="25px" height="28px" viewBox="0 0 25 28" version="1.1" xmlns="" xmlns:xlink="">
<!-- Generator: Sketch 41.1 (35376) - -->
<desc>Created with Sketch.</desc>
<g id="Icons-and-Clouds" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="table" transform="translate(0.000000, -93.000000)" stroke="#787878">
<g id="note" transform="translate(4.000000, 99.000000)">
<polygon id="paper" stroke-linecap="round" stroke-linejoin="round" points="0.5 0.5 11.5622559 0.5 16.5 5.49975586 16.5 20.5 0.5 20.5"></polygon>
<polyline id="corner" points="11.5 0.5 11.5 5.50014165 16.5 5.5"></polyline>
<p>SVG icon generated by Sketch (which is pretty clean anyway,) 903 characters</p>
<pre><code><svg width="25px" height="28px" viewBox="0 0 25 28" xmlns="">
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g class="table" transform="translate(0.00, -93.00)" stroke="#787878">
<g class="note" transform="translate(4.00, 99.00)">
<polygon class="paper" stroke-linecap="round" stroke-linejoin="round" points="0.5 0.5 11.56 0.5 16.5 5.49 16.5 20.5 0.5 20.5"></polygon>
<polyline class="corner" points="11.5 0.5 11.5 5.50 16.5 5.5"></polyline>
<p>SVG after my script, 634 characters</p>
<h2>Cross-platform reliability</h2>
<p>If you compare the old layout to the new layout, the most noticeable change is how the content better fills the available space than before. It’s particularly noticeable inside the app. Before, the layout looked like a website inside an app. Now, it looks like the content is a more unified part of the whole.</p>
<p>In development terms, this refactor has a big performance advantage. The compiled CSS on the app has gone from 19kb to 16kb. The compiled CSS on the site has gone from 34kb to 25kb. Comparing Better to a site laden with JavaScript trackers, performance was never an issue to begin with. Where we really win is in maintainability, now the CSS is much simpler and easier to read.</p>
<p>This refactor was bigger than planned, but we still have plenty more changes on the roadmap. One of our core principles at is to iterate, rather than work on big upfront design. With this approach we hope to keep making everything we do, incrementally better<abbr title="asterisk">*</abbr>.</p>
<p><em><abbr title="asterisk">*</abbr>pun always intended.</em></p>
<div id="discourse-comments"></div>
<!-- footer -->
<footer class='site-footer'>
<div class='footer-wrap'>
<aside class='ethical-design-badge'>
<a href=''><img alt='' src=''></a>
<p>We practice <strong>Ethical</strong> Design.</p>
<small class='copyright'><strong></strong> <abbr title='Copyright'>©</abbr> <a href='/about/#trademarks'>Article 12</a>. All content is <a href=''>Creative Commons Attribution 4.0 International</a>, unless otherwise stated. <a class='view-source' href=''>View source</a></small>
<script type='text/javascript'>
var discourseUrl = '',
discourseEmbedUrl = '';
(function() {
var d = document.createElement('script'); d.type = 'text/javascript'; d.async = true;
d.src = discourseUrl + 'javascripts/embed.js';
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(d);
\ No newline at end of file
......@@ -87,7 +87,7 @@
<script type='text/javascript'>
var discourseUrl = '',
discourseEmbedUrl = '';
discourseEmbedUrl = '';
(function() {
var d = document.createElement('script'); d.type = 'text/javascript'; d.async = true;
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment