Spacing strategy

Coming soon
Close video
Make intelligent spacing decisions inside Client-first. This documentation page explains when to use, and when to not use, the Client-first utility spacing system.


This is a deep use case specific exploration into the use of the global utility spacing system that comes with Client-first. We want the spacing system to create less chaos and less classes in our project. If we use the spacing system intelligently, it can help us work faster.

The goal of this page is to help you make more educated decisions inside your project. We want you to make careful decisions with Client-first to help you work better as a developer and provide a better output for you clients.

This docs page comes with a cloneable project. Experience the examples covered on this docs page with our Spacing Decisions cloneable.

Better definitions of global and utility

In the original release of Client-first, we used the term "global" a lot. It was mostly used to describe our utility classes in Client-first. These are the classes that come with the Client-first cloneable.

In this newest docs update, we better define these terms. Global classes and styles are not only for utility classes. They can be used for custom classes as well.

It's important you understand how we are using this terminology. These terms are used throughout this entire page.

Global class or global style

A class or style that is intended for use across the entire project. A global class is not for a specific instance. It can apply styles that will remain 'global' or 'unified' across the project. Global means everywhere and anywhere.

A global class can be a custom class, such as items-list_background-layer. We may have this background layer on every items list and this class will allow us to manage its styles globally.

A global class can also be a utility class, such as margin-small to set a default globally managed margin value.

Utility class

A class that is created with a specific, usually simple, combination of css properties that can be applied to elements globally across the project.

All utility classes are global classes by nature. The concept of a utility class is a class that helps apply global CSS properties.

For example, we add utility classes background-color-red and font-size-large. to the Client-first starter project to help you organize and manage a special site-specific background color and a globally managed system of font size.

In Client-first, utility spacing classes are called spacing wrappers.

This docs page is a deep exploration into when we should and should not use spacing wrappers.

We add two classes to a div block to create a spacing wrapper. The direction class and the size class together to create margin or padding on any side of the element. This div block is a spacing wrapper.

For example, we start with our margin-top class and then add our margin-small class on top of it. Together, the two classes apply a small margin top value to the element.

We nest an element(s) inside of a spacing wrapper to create space between the element and something else.

Core benefits of the Client-first spacing wrapper system
  1. We do not have to create a new custom class to apply spacing only
  2. We do not have to stack classes on top of an element (ie. text-color-white + spacing classes)
  3. It keeps our heading and paragraph text clean from non-typography classes
  4. We can keep our spacing values more consistent throughout the project, across all breakpoints
  5. If used correctly, spacing wrappers can help us work faster.
If you are unfamiliar with the Client-first spacing system, first learn about it before reading this page. Navigate to the Classes strategy page and click on "Learn more" to read about the spacing system.

When to use spacing wrapper utility classes?

1. Spacing of typography and buttons

Let's go over the perfect example — spacing our content.
In Client-first, we like to keep our headings and paragraph font clean from classes. Ideally there are no classes applied to our typography elements. The less we apply classes and variations to our typography, the more unified and global our typography is.

If the typography has a variation, we can place text- classes on it. Ideally, the only type of class we apply to typography is text- classes.

Applying unrelated classes to our typography, like spacing, max-width, or padding can cause chaos in the build. Deep class stacking on top of our typography elements will definitely cause chaos in the build.

Instead of stacking classes or creating a custom class specifically for spacing your typography, you can use spacing wrappers as parents of each typography element.
The three spacing wrappers above will separate our these three elements
- without creating a new class.
- while keeping global typography clean
- while keeping our global cta button unedited

This is a common section and layout in our project. We can use this strategy for all or most of these layouts.

Plus we get to use global utility spacing that stays equal for all content spacing. If we use this correctly, our content spacing can stay unified across the site.

Adding a class on top of our global cta button is not recommended unless the class is for a variation of the cta, like is-button-alternative

Having something like this, spacing-home-button is not recommended
and doing this

2. Use default global spacing values

In this release of Client-first, we better define a utility class and a global class.
Our spacing wrappers are global + utility classes. They are utility classes that apply a defined margin or padding value. They are global because they are intended to be used throughout our build. We can manage the defined spacing values on a global level for our entire project.

There are several benefits of using default global spacing:

Elements will receive the default spacing that is used across the project.

Usually we want our website's spacing to be as unified as possible across sections and pages. If we're using 4rem, 8rem, 12rem as our primary spacing values, we want those values to be consistent across our project. The more we use the Client-first utility spacing system, the more consistent we can be with spacing throughout the project.

Default and automatic across tablet and mobile breakpoints.

Using a spacing wrapper will automatically make unified site-wide spacing adjustments across all breakpoints. If spacing wrappers are applied to 100 elements across the project, that's 100 fewer tablet and mobile margin and padding styles we have to apply. Additionally, we receive the benefits of "Elements will receive the default spacing that is used across the project." for all breakpoint levels.

Site-wide updates.

With one value change, you can update many spacing values across the project. Every element that uses the changed spacing wrapper will be influenced. For example, if a client says "I want less spacing between all of the sections" - this update can be made much quicker by adjusting the global utility spacing wrappers.

3. Instance specific spacing for global reused components

Useful for applying spacing to symbols and reusable components.

Imagine a client-logos_component. This component is a row of client logos that is placed throughout the site. Homepage, above the footer, testimonials, work, etc. If we applied the spacing directly to the custom class, this spacing must be applied across all instances of this component. Every client logo row would need to use the same spacing value.

By using the utility spacing wrappers, we can put this component inside a spacing wrapper to give us full control of spacing for that specific instance.

The logo row in the footer can have a completely different spacing than the logo row on the testimonials page. No margin or padding values need to be updated on the component itself.

No combo class required, no new classes created.

Extra useful when working with Symbols:

If the client-logos_component is a symbol, the spacing wrappers give full flexibility without making any global adjustments to the symbol.

Using spacing wrappers conclusion

Spacing wrappers in Client-first exist to help you work faster and better maintain your project.

If you are using spacing wrappers and you are working slower and making your project more difficult, you may be using spacing wrappers incorrectly.

Remember that it's not required to use spacing wrappers everywhere.

Sometimes it's best to use spacing wrappers. Sometimes it's best to apply margin and padding directly to the custom class.

When we run into workflow destroyers and roadblocks using spacing wrappers, it's likely due to one of the reasons in the next section.

When to apply spacing directly to a custom class

The Client-first utility spacing system is not intended for all use cases. It's not the only implementation method for spacing on our site.

When we want to add spacing and the utility spacing wrappers are not ideal for the use case, we can apply the spacing directly to the custom class.

For example:

Instead of wrapping footer_link inside a div with margin-top margin-medium

We apply margin-top: 4rem directly to the footer_link class
There are several reasons we would want to do this instead of use our global utility spacing system.

1. Globally manage the spacing of a specific element

When you have repeated items in your project, and these items should have the same spacing value, using the global spacing wrappers may slow your down and make project management more difficult.

Adding a spacing wrapper in between each repeating element would require to change to each spacing wrapper to update spacing. This can lead to a frustrating workflow for simple updates.

Footer example

Let's look at an example use case with links in the footer.
Above we show each footer_link wrapped inside a margin-top margin-small spacing wrapper.

If we wanted to change the spacing between each footer link, we would need to update each margin-small class to margin-xsmall.

This is not ideal and this change may take several minutes. This type of change should take seconds and require little effort.

Let's look at how we can make this more efficient
This screenshot shows each footer_link with margin-top: 2rem applied to it.

If I wanted to change the space between each footer link, I can make a single change to the footer_link class. Changing the margin will change the value for all footer links.

This gives me full global control of spacing specifically for the footer link. We can change every footer link on this page, and across our project, with a single change of the margin-top CSS property.

Pricing table example

Similar to the footer example, a pricing table will likely have a list of features.

With a unique custom class created specifically for the pricing table items, it will be very easy to make a change to all rows of the pricing table. We can make rapid adjustments that update as one unified element
The footer and pricing table examples are clear. Sometimes the decision is not as clear. There can be conflicting benefits between using the utility spacing system vs. applying the spacing to a custom class.

Let's look at an example of an element that can benefit from either method.

Stat item example

stat_item class that has three child elements inside, H4, stat_dots-wrapper, Text Block.

We can apply custom margin-top and margin-bottom properties to the stat_dots-wrapper to create the space we need between all three elements. This works well here and may be much easier to manage globally across our project.

There is no right or wrong in this example use case. There is more and less efficient. Below we present questions you can use to make powerful decisions as you're building.

Earlier in the docs we talk about how utility spacing wrappers can be used to space our content. This is content!

We can absolutely use our spacing wrappers here. Both spacing wrapper and custom class work here. Before we choose, we should ask ourselves these two important questions.

How many instances are there?

Are there only 4 of these stat_item elements on the website?

Or is this a recurring stat_item that we may see throughout the project?

If it's limited to 4 items, global spacing wrappers may work well here. If a change needs to be made, there aren't many spacing wrappers to update. It would be manageable update in this use case.

If stat_item is recurring across the project, making a change to these 4 items would only influence these 4 items only. If we want the stat_item content spacing to be the same everywhere, we would need to go on each page the stat_item exists to update the spacing wrappers.

As there are more instances of the element, updates become more difficult with spacing wrappers if you you want to maintain unified spacing for that specific element.

How do I want to manage these instances?

We may want to manage the stat_item globally across the project as we explain above.

We may not want to manage all stat_item elements together.

Maybe one page has different spacing and sizes than another page.

Maybe the three color boxes don't exist on one of the instances and the spacing works differently from page to page.

If either of these is the case, we may want to have the flexibility to use our utility spacing system for each instance.

2. Layout purposes

In some situations, spacing wrappers will break a layout or prevent you from using certain css properties.

In this case, we should apply the spacing value directly to the custom class.



3. Unique tablet and mobile spacing sizes

Spacing wrappers have a huge benefit of maintaining default spacing across all breakpoints. However, we may not want default spacing across all breakpoints. Sometimes we have elements that require unique spacing on tablet, mobile, or both. In this case, using spacing wrappers will make our customizations more difficult.
The screenshot above shows an element that has default spacing on desktop with a requirement for tablet and mobile spacing customizations. We can apply all spacing directly to the custom class so we have full control of the element across all breakpoints.

Custom class spacing strategy with CSS grid

We can create space between elements using CSS grid. This is not a strategy recommended for the entire website, but rather for specific components that can benefit from it.

Let's continue the stat_item example above. We have two options when applying spacing to the custom class.

As we showed above, we can apply margin-top and margin-bottom properties to the stat_dots-wrapper. This works well here. We can create space between the three squares and the two pieces of text.

We can achieve the same outcome using CSS grid on the parent wrapper, stat-item. Doing this will allow us will create the space we need between the three elements AND allow for new items to be added to the stat item. These items will be automatically spaced with CSS grid.
As I update the CSS grid options, I am able to update the stat_item globally across the project. This implementation strategy works really well for growing lists or spacing situations that don't have custom classes already applied to child elements.

Avoid using global padding to create size for inner elements

We don’t recommend using the utility classes to create padding around the item content. It works in terms of CSS, but this becomes very difficult to edit.

This requires a class change on each instance when spacing is updated. Additionally, will have no control of spacing values across breakpoints. Oftentimes, the padding for inner elements will need specific size customizations as go through each breakpoint.

This is not recommended:
Instead apply the inner element padding directly on the custom class

Clone the examples in this docs page

Check out our Spacing Decisions cloneable to experience with these examples live.

Next: Spacing decisions

Understand how to make intelligent decisions around spacing on your website.