iOS: Hard & Soft 8-point grids
Achieving vertical rhythm in your UI
I’ve been tumbling down this rabbit hole for a couple of months now. It’s hard not to be excited by how great grids are:
- They impose constraints on the design process, which reduce the number of options we have as designers. Fewer decisions means faster to code
- The user appreciates the increased consistency, and so does the rest of the product/design team
This feeling will be familiar to those who got excited when 960pt grids showed up in responsive web design. Like all principles, guidelines, patterns and rules across every discipline, there are times where vertical grids needs to be broken or ignored all together. But we’re increasingly of the opinion that it should serve a central role as part of our design language.
Hard vs. Soft
Take a look at the “8-Point Grid” section in this Spec “Specifics” post for a more thorough primer on the difference between the two. In short, Hard grids snap content to a fixed grid, and Soft grids define the spacing between elements rather than to some looming, document-wide grid.
They both have a place in your design language, and we’re already establishing rules that will help us pick the right one for a specific context or task.
Why just iOS?
Not all platforms are created equal. Take a look at this Smashing Magazine post about achieving baseline grids in CSS and you’ll see that when typography is involved, our implementations are often practically limited by the platform and out ability to programmatically ask questions of the underlying fonts. Apple has historically treated typography well, and I’ve been working to bridge the gap between style guides and code on iOS for some time.
We’re redesigning content cards (article, video, gallery, event) for the World Surf league across all their digital products — responsive web, Android, iOS, connected devices. We’re 90% done with the design concept (c/o Luke), and starting to tighten things up, informed by the style guide that lives and evolves alongside each one of our designs. During this process, we’re testing designs out across 4 responsive breakpoints with various keyart and copy. Quickly, it feels like the little nudges we’re making can look good with some copy, but not others (1 line vs. 2), and it’s hard to get behind any one layout because they aren’t rooted in any real logic.
This is a symptom of the decision paralysis that we know grids can address. There are two directions we can go here — Hard, where we snap each text baseline to a grid line, or Soft, where we ensure the spacing between elements conforms to our grid steps.
Because we’re constraining ourselves vertically — we control the height of the card, and by design, that height falls onto our hard grid — we opted to go with hard grid alignment here. Moreover, we mocked up both layouts, compared them directly, and preferred the spacing the Hard grid gave us. Choosing one of two options is much easier than one from many.
A note on line height
When you have multiple lines of text, line height is central to ensuring each line falls on your grid. Naturally, line heights that are multiples of 8pt will work nicely, but 4pt is reasonable too if you need a smaller step size (that way, every other line will be on-grid). It’s another case of constraining your decision space, which can be wonderfully freeing. All of these design decisions work together and inform one-another.
Implementing a Hard Grid
My Hard grid implementation is rooted in how I handle text within iOS generally. That approach and how I build to Soft grids is covered here:
This is a continuation and refinement of the work I covered in Codifying style guides in Swift, wherein I claimed…medium.com
Hard grids require a little adjustment to the math and measurements we use, but are very similar. That’s nice, because like with all style guide decisions, we want to build flexibility into our implementation.
Here’s my content card table cell xib:
A lot of this complexity is because of how I constrain content cards to a max width (for iPad, using the Content Card). We’ll focus on the layout within the Content Card, specifically the three labels — byline, title, and description.
Layout margins are your friend
If you’re anything like me, you refuse to pin constraints to margins because it’s rare they match what you’re trying to achieve — “where did you come from, 8pt indent!?”. I’d rather have a leading constraint of 8 than a leading margin constraint of zero. But since embracing a class sized world, and wanting to change margins dynamically, I’ve learned to embrace them as a valuable tool. What’s better — 4 outlets for top, bottom, leading and trailing for each view, or a single outlet for a view whose margins you can change programmatically and all at once? It’s time to embrace this aspect of the box model.
So the layout margins of that Content Card view are going to set the top indent, horizontal gutters, and bottom alignment of the description label.
Clearly, we need to adjust that bottom margin to nestle the baseline of the text on the grid line.
And here are the two utility functions which make this possible:
Which has the desired effect:
That’s all well and good. But what about text interacting with text?!
And for completeness, here’s the ascender calculation util:
Here’s the finished product: