…and how Stackable can help
Some common iOS interface design patterns are way easier to talk about than they are to develop. Adaptable, maintainable code should be as easy to write and tinker with as it is to express in a conversation with your designer.
I want to cover six tricky layouts that I encounter frequently, and how my library Stackable can help solve these problems.

UIStackView
. It closely mirrors how my designer thinks about and communicates layout.1. Variable-Sized Content

It is NEVER safe to assume that a design will fit nicely on one screen. It wont. Trust me. Make sure your development team understands this. Your designers, too. Heck, everyone else at your org. iPhones come in multiple screen sizes and users can choose their font size.
Everything should scroll. Scrolling is free. Users are used to this and comfortable with this. Even if a page doesn’t scroll, they’ll scroll anyway just to check.
All of your screens should be prepared to scroll in the case that the content overflows the screen.
Unfortunately, this is sort of annoying to code with UIKit
. Mostly due to UIStackView
being a nonrendering UIView
subclass.
Anyway, we’ve got it all figured out for you. Use ScrollingStackView
. It is a UIStackView
in a UIScrollView
that will prefer to be the size of your screen until its content overflows. Then it starts scrolling.
2. Variable Hairlines

Hairlines are all over iOS. Design wise, they seem to have their own rules. They can overflow margins. They can be inset. They can be asymmetrical. They can appear after cells, before sections, around views. They can be thick or thin and different colors. They can be a whole lot of development pain and noise for 1 pixel of interface.
Don’t let hairlines dominate your layout code. They don’t dominate your conversations with your designer.
Stackable
has a suite of tools to help concisely get the functionality you need and move on.
stack.stackable.add([
titleLabel,
UIStackView.stacakble.hairline
.outset(to: view),
cells,
UIStackView.stackable.hairlines(around: cells)
.inset(by: .left(10))
])
inset(by:)
allows you to move any view around relative to its normal UIStackView layout.outset(to:)
allows you to break outside of the bounds of the UIStackView and apply constraints against some other ancestor.
3. Custom and Conditional Spacing
Spacing rules often gets lost in the cracks. Implied, but not vocalized by your designer. Spaces are used to visually separate two items or groups. Their size depends on what they are separating. Their need is dependent on which possible combination of elements are visible on screen.
UIStackView
started with a very limited spacing API. You got one space per stack, and that was applied between everything. Later, they introduced setCustomSpacing(_:after:)
, which allowed you to apply a different value dependent on the visibility of some subview. This was a tiny step in the right direction, but still wildly limited.
Conditional spacing is implicitly all over designs. Spaces between groups of cells. Spaces between this view and that view. Spaces that should or shouldn’t be there depending on what data you have. Spaces that should be at least this much but no more than that much.
Stackable
has you covered. Custom spacing can be applied and will monitor the visibility of any view(s), showing or hiding to match. Spaces can be fixed or flexible.
stack.stackable.add([
10,
viewA,
20,
viewB,
UIStackView.stackable.space(after: viewB 20),
viewC,
UIStackView.stackable.space(before: viewD, 20),
viewD,
viewE,
UIStackView.stackable.space(between: viewE, viewF, 20),
viewF,
20...100,
])
- Spaces can be articulated using numbers (fixed space) or ranges of numbers (flexible spaces)
- Spaces immediately following a view will implicitly monitor the visibility of that view, and update accordingly.
.space(after:
) andspace(before:
are spaces that explicitly monitor the visibility of some view..space(between:)
will monitor the visibility of two views, and will only be visible if both views are.
4. Variable Alignment

Similar to custom spacing, UIStackView
can be clunky when trying to adjust the alignment of one or two subviews. Common practice is to wrap your view in a container view, apply constraints, remember to toggle the visibility of your container if you want to hide the view itself, yadda yadda. It’s a bunch of noise.
Stackable
includes a clean .aligned()
API. Set it and move on.
stack.stackable.add([
heroImage,
titleLabel
.aligned(.centerX),
bodyLabel,
readMoreLabel
.aligned(.right)
.inset(by: .right(10),
])
5. Aligning Margins

Layout margins in UIKit are a trip. You set them and hope that iOS doesn’t overwrite them. If you want a clean margin extending through all your subviews, you’ve got work to do. You’ll need to pump in your desired margin into all of your subviews, taking offset coordinate spaces into account. Monitor for changes and repeat.
Designers don’t think about or communicate margins on a subview by subview basis. Its usually one big ol’ red line that gets fiddled with depending on the screen form factor.
Stackable
includes tools to line up frames and margins and keep them in sync.
Take a group of settings cells, for example. They have their own background color that extends to the edge of the view, but their margins align with the layout of the view controller.
stack.stackable.add([
image,
titleLabel,
subtitleLabel,
cells
.outset(to: view)
.margins(alignedWith: view)
])
outset(to:)
allows you to align the cell edges (and thus, background color) extends to the horizontal edges ofview
margins(alignedWith:)
will update the.layoutMarginsGuide
ofcells
to match and monitor the horizontal edges ofview.layoutMarginsGuide
6. Variable Visibility

UI is populated by data. Optional data means optional UI. Optional UI means optional decoration, etc, etc.
Sometimes, this web of dependent-visibility can get quite complicated. Spacing, hairlines, borders, sections can all cascade based on what combination of UI end up on screen.
Stackable
includes helper functionality to monitor the visibility of some view, and toggle another view’s visibility to match. In fact, this is how the hairline and spacing APIs work under the hood.
decoration.stackable.bindVisible(to: dataLabel)
Try Stackable!
Stop writing muddy code that does simple stuff. Spend your time collaborating with your designers and listening to your users.
Stackable
will help you write cleaner, more articulate, and more consistent layout code. Give it a try and let us know what you think!