DEV Community

Cover image for Design System 101: Top-down Approach in Component Spacing
Guilherme Ananias for Woovi

Posted on

Design System 101: Top-down Approach in Component Spacing

Here at Woovi, one of our core philosophies around the front-end is ensure that our entire UI will be resilient around any future change. In the startup scenario, we need to iterate faster in our front-end and produce a high-quality code even in this scenario.

One of the principles that serves as a guarantee of a good code in the UI is related to how we handle the spacing between children elements. In general, we will find two different approaches: top-down and bottom-up.


An example of bottom-up approach

A bottom-up approach implies in the children elements causing a side-effect in the next (or close) elements. Rules like margin, when used to determine the spacing between two or more elements, is a bottom-up.

This can be called a bad practice. But why? In the example above, each child has their own margin rule applying 8px to the next element.

In this scenario, you're creating more entropy around your codebase. You give the power to these children to determine how they will behave in the macro UI, causing an undesirable side-effect around other elements. If one of these elements has a different spacing value, like 12px to margin-bottom, will be harder to debug and identify in which of these elements is the issue.

The CSS logic around this approach would be more harder to handle too. How do you ensure that the last element won't apply another margin-bottom? You have some ways to ensure it, but it's the kind of code that is useless because someone already solved to you.

If someone wants to change the spacing between elements from 8px to 12px, instead of changing only one element, you'll need to deep dive around the children finding where we're putting these margins and modify it, then you modify 3 (three) elements instead of only 1 (one).


An example of top-down approach

This is an example of top-down spacing. With this pattern, the parent element applies the spacing around their children. With a flexbox, you put a gap rule in the parent element and add the spacing around the children elements.

You're reducing the entropy around this code. You apply this rule only for the children elements, not having an external side-effect around other elements that aren't related to this scope. Putting the rule inside only one element is a better practice too, it's easier to debug and find around if necessary.

When margin rule can be applied?

A margin rule is unnecessary in almost every case. But can be acceptable given some context, for example, a spacing between a heading, and the rest of their siblings. MaterialUI provide to us an example of it, exposing a gutterBottom prop that adds a margin-bottom of 8px in the Typography element. In cases like that, where you want to add some spacing between the heading element and the "rest of the body", a margin is acceptable.

Another scenario are insets, like the Inset exposed by the Radix UI. Is a good practice around design stuffs to give a better centralization around some icons and other related stuffs, a good way to do it is using margin. It gives to you an easier way to centralize an element with a more predictable way around a specific parent.

About us

Woovi is a startup that enables shoppers to pay as they like. To make this possible, Woovi provides instant payment solutions for merchants to accept orders.

We are hiring!

Top comments (6)

receter profile image
Andreas Riedmüller

Thanks for sharing, I am very much into the spacing topic and always eager to read about others opinions and solutions. Currently I use margin-top for almost all spacing and it works really well so far. I wrote a post about this quite a while ago: Why I fell in love with margin top.

In our design system we do have a stack component as well and it basically looks like this:

.stack > * + * {
  margin-top: 42px;
Enter fullscreen mode Exit fullscreen mode

The reason why I did not go with gap for the stack was mainly due to my relatively strict margin-top policy. (in some some other scenarios we do use gap though).

The other thing I like about the margin-top stack is that the CSS stays very explicit and clean even when some elements in the stack need another spacing.

Imagine an example a stack that has a gap of 16px and 10 elements but:
element2 needs to have 24px (at the top)
element5 just 12px (at the top)

Solution 1: You don’t use a stack for this but individual spacing.
Solution 2: You use multiple stacks (I am not a huge fan of this solution)
Solution 3: You solve it with individual margin like so:

gap stack:
element2 needs margin-top: 8px
element5 needs margin-top: -4px

or better you can expose the gap size in a CSS var and write it more explicit:

element2 margin-top: calc(24px - var(--gap))
element5 margin-top: calc(12px - var(--gap))

margin-top stack:
element2: margin-top: 24px
element5: margin-top: -12px

Happy to hear your thoughts. As you can tell I am very much into my margin-top stuff, but because it works so well for me since years. If you somewhen need someone to discuss spacing stuff I am all in.

I once worked in a Drupal skin project and to change the spacing between 2 elements I had to change multiple paddings and collapsing margins, this is the Hell 😂

artxe2 profile image
Yeom suyun

Is it appropriate to handle it with wrapper's padding instead of margin?

joelbonetr profile image
JoelBonetR 🥇 • Edited

If you have a background-image on a wrapper and use padding, the spacing between the image and the content above/below will be halved.

Padding's for the inner space, margin's for the outer space [insert astronaut picture for the meme] 😁

noghartt profile image
Guilherme Ananias

I would say that is a bad practice to use padding as a spacing ruler. Even more because of facts like border-box, etc.

I always would prefer to use a gap or a margin (as a polyfill for old browsers) in an abstraction, like the Stack exposed by Material UI. Or other similar solution.

z2lai profile image

I would say you would be adding padding to containers in most cases, but thats besides the point of having to manage the space between container child elements either with margins on the children or flexbox gap on the container.

z2lai profile image

Excellent topic and writeup! Such a simple concept which I find myself struggling with more than I should. Your MaterialUI real world example is invaluable in driving this approach home.