Spacing strategy
Make intelligent spacing decisions inside Client-First. This documentation page explains strategies for applying spacing throughout our project.
Intro
Spacing strategy
This page explains how to implement all spacing methods recommended by Client-First.
Client-First spacing strategy should bring more consistency to our project. We want to create less chaos and confusion. Our workflow and project quality improves if we use Client-First spacing strategies intelligently.
We organize this docs page into two parts:
- Part 1: Utility classes
- Part 2: Custom classes
Part 1: Utility classes
Part 1 of Client-First spacing is about global utility classes. We include several strategies for using utility classes inside the project.
Different projects, use cases, and implementations may favor one strategy over another. Having multiple spacing strategies with utility classes gives us flexibility when building our projects.
Client-First utility class spacing gives us options for implementation:
- Spacing block strategy (padding-[direction]-[size])
- Spacing wrapper strategy (margin-[direction]-[size] or padding-[direction]-[size])
These utility class systems are included with the Client-First utility classes.
Spacing values and variables
Every spacing class in Client-First pulls its value from a variable. We do not hardcode spacing values on utility classes.
Spacing variables live in the Layout collection in the Variables panel.

Spacing sizes
Client-First uses a fixed set of size names across all spacing classes. The same size names work for padding, margin, and gap.
xxtiny
xtiny
tiny
xxsmall
xsmall
small
medium
large
xlarge
xxlarge
huge
xhuge
xxhuge
A size name always means the same distance, no matter which class it is applied through. padding-top-medium, margin-bottom-medium, and gap-medium all use the same value.
Updating spacing globally
If we want to update a spacing value, we update the variable connected to it and the change applies sitewide. Any utility class or custom class using the same variable updates to match the new value.

Breakpoint values
Spacing variables can hold different values per breakpoint mode. This means our spacing scales down on tablet and mobile without us writing breakpoint styles on individual elements.
We set the value once per mode. Every element using that size follows.

Spacing block strategy
padding-bottom-[size]
In Client-First, a "spacing block" is an empty Div Block with a utility class that creates space between two sibling elements.
- Add a Div Block to the page with the class padding-bottom-[size]
- Add content elements to the page as siblings of the spacing block.
- The spacing block creates space (padding) between elements.

Spacing blocks can be used to create space between any elements vertically.
The spacing block uses one class. Direction and size are combined into a single utility class, so padding-bottom-medium applies both the direction and the value.
Spacing wrapper strategy
padding-[direction]-[size]
and
margin-[direction]-[size]
In Client-First, a "spacing wrapper" is a Div Block that wraps a child element and creates space between a sibling element.
1. Add a Div Block "spacing wrapper" to the page with the class margin-[direction]-[size] or padding-[direction]-[size]
2. Nest a content element inside the spacing wrapper.
3. The spacing wrapper creates space (margin or padding) between itself and a sibling element.

The spacing wrapper uses one class. Direction and size are combined, so margin-bottom-medium applies margin to the bottom at the medium value.
We nest an element inside the spacing wrapper to create space between the nested element and something else.
Use cases for: Utility spacing in general
1. Use default global spacing values
Benefit: We keep our spacing values more consistent and unified throughout the project
We want to unify our website's spacing across sections and pages. If we're using 4rem, 8rem, 12rem as our primary spacing values across the project, we want those values to be consistent everywhere.
The more we use the Client-First utility spacing system, the more consistent our spacing will be throughout the project.
A spacing block or spacing wrapper automatically implements unified site-wide spacing adjustments across all breakpoints.
If we apply spacing blocks and wrappers to 100 elements across the project, that's 100 fewer tablet and mobile styles we have to apply in our project.
For each breakpoint level, elements spaced with blocks and wrappers will receive the default spacing values used across the project.

Benefit: We can make global site-wide spacing updates throughout the project.
We can update many spacing values across the project with one variable change. The update influences every element that uses that variable, whether it comes from a utility class or a custom class. For example, if a client says, "I want less spacing between all of the content", this update can be made relatively quickly by adjusting the spacing variables.
2. Workflow and scalability benefits
Benefit: If we are using a utility class strategy, we can reduce the number of custom classes used for margin and padding CSS properties
We want to reduce the number of custom classes created specifically for spacing. Spacing blocks and wrappers can help us create fewer classes for our project.
We can rely on the utility classes already created for the spacing. As we use the utility spacing system more, we will rely less on creating custom classes for spacing.
Benefit: We avoid deep stacking classes on top of an element.
Client-First is against deep stacking inside Webflow projects. We want to avoid deep stacking at all times. Spacing wrappers and blocks help us avoid deep stacking classes on our elements. Learn more about deep stacking in Classes strategy 2.
Benefit: If used correctly, spacing wrappers can help us work faster.
Spacing blocks and wrappers in Client-First exist to help us work faster and maintain our project better.
If we use wrappers and blocks, and this results in a slower workflow or project management difficulty, we may be misusing spacing wrappers.
It's not required or recommended to use utility spacing everywhere.
Applying margin and padding CSS properties directly to custom classes is acceptable. There are use cases where it’s more efficient to apply spacing on a custom class. We discuss custom class use in the second part of this article.
3. Spacing of typography and buttons
In this example, we have an H2, Paragraph, and Button. We can create spacing for these elements without creating a new class.

We use spacing blocks or wrappers to create space between each text element, which helps us avoid the creation of custom classes.
Our Typography strategy encourages that we use few or no custom classes on our typography elements. We want to avoid creating new custom classes specifically for spacing typography elements.
Instead, we can pair our global typography strategy with our global spacing strategy to create text content layouts without custom classes.
Benefit: Avoid utility class deep stacking on text elements.
In Client-First, we want to keep our Headings and Paragraph font clean from non-typography classes.
Ideally, there are no classes applied to our typography elements. Using the default tag styles is best. If the typography has a variation from the default, we can place text- or heading- classes on it.
We want to avoid margin- or padding- classes directly to the text element. We will quickly approach deep stacking issues if we apply typography and spacing classes to text elements.
Spacing blocks and wrappers help us avoid deep stacking.
We do not want to do this:
The spacing block solves the issue of stacking spacing classes on the text element.
With our spacing classes separated from our typography classes, we can manage each separately without the issue of deep stacking.
4. Spacing for reused components
Benefit: We can create instance-specific spacing for Components (previously called Symbols).
When we want to apply spacing to components, the spacing must be applied to all instances of the component.
Unified component spacing may be a problem if instances of our components require different spacing values.
Using spacing blocks or wrappers, we can have different spacing for different component instances.
No combo class required, no new classes created, no custom CSS needed. Our spacing system gives us instance-specific spacing while using the core content stored in the component.
Use cases for spacing block strategy
1. Create space between two elements
Spacing blocks are very useful when we create space between two elements. They're fast to implement, we have fewer nested levels, and our elements are more visible.

2. See children in Navigator
When we use spacing blocks, we create a clear view in Navigator. We can see all elements of the component.
Using too many spacing wrappers may "hide" too many of our important elements inside nested folders. Spacing blocks will create less nesting inside Navigator.
Spacing blocks show our important elements more visibly in Navigator.

Use cases for: Spacing wrapper strategy
1. Use with CSS Grid spacing strategy
Using the CSS Grid spacing strategy, we can quickly create equal space between children elements.
We can use spacing wrappers to create unique spacing for one element in the list. When spacing wrappers are used together with CSS Grid strategy, we can apply custom spacing quickly with less effort.
For example, a content item has 1rem between each child element. The last item in the list needs more space above it.
We can apply margin-top-medium as a spacing wrapper for the last item in the list.

The spacing wrappers allow us to use CSS Grid spacing without creating multiple custom classes.
FAQ. Are empty divs bad for my website?
We are commonly asked about the impact of empty divs and spacing-only divs used in the Client-First spacing system.
- Will search engines have trouble reading my website?
- Will I generate too many elements on the web page?
- Will there be a problem with accessibility?
- Will my project be more difficult to maintain?
The short answer is no.
As long as the empty divs don't have any content or accessibility attributes (like aria-label) added to them, screen readers will omit them.
Search engines will not be confused by blank divs either. An empty div with a CSS class is easy to identify by us humans and by search engines.
"Excessive DOM size" is a common error alert found in many web performance tools. For example, Google's PageSpeed Insights. It is very unlikely that the Client-First spacing system is the cause of this error. The most likely causes are layered animations, Lottie files, and embeds. These implementations can generate exponentially more DOM elements than Client-First spacing.
A web page built with Client-First guidelines has little or no impact in causing the "Excessive DOM size" performance alert.
Interested in further reading on empty divs? We loved reading Don't Fear Empty Divs by Cory Etzkorn.
Part 2: Custom classes
The Client-First utility spacing classes are not the only implementation method for spacing on our site.
We can apply margin and padding CSS properties directly to the custom class.
Inside the custom class mindset, we present 3 spacing strategies:
- Custom class on element
- Display Flex with gaps parent spacing
- CSS Grid parent spacing
All three strategies use a custom class to create space between elements.
When we use custom classes for spacing, we should have a good use case for the custom class. Fewer custom classes equals more consistency in spacing.
Custom class on element strategy
"Custom class on element" applies margin and padding values directly to the element that needs to be spaced.
For example, we apply faq_title to a Heading that requires unique spacing, which the utility class system can not achieve. A CSS property of margin-bottom: 0.75rem is applied directly to the faq_title class.

This graphic applies a custom class and custom spacing on the element.
This strategy is the most flexible. We have total control of a specific element across all breakpoints. We must use this power with purpose.
By overusing this strategy, we can create too many custom classes for spacing. This may result in a disorganized project spacing system and many manual breakpoint updates.
Apply spacing through variables
If the spacing value we need already exists as a variable, we can apply that variable directly to the custom class instead of typing a fixed value.
The custom class still gives us full control of the element. The value stays connected to our global spacing system.

This keeps our spacing consistent even when we work outside the utility classes. If the variable updates, this element updates with it.
Display Flex with gaps parent spacing
Display Flex spacing applies flex to a parent wrapper and uses gap to create space between the children inside it.
We set the parent to display flex, choose a vertical or horizontal direction, then apply a gap value from our spacing variables or using gap-[size] utility classes.

One parent controls the space between every child. We do not add classes or elements to the children themselves.
Because the gap uses a spacing variable or utility class, the space between children matches the rest of the project.
CSS Grid strategy
CSS Grid spacing strategy applies CSS Grid to a parent wrapper which creates space for the children inside it.
We can create vertical and horizontal space between child elements using CSS Grid.
We set the gap between rows and columns using a value from our spacing variables or a gap-[size] utility class. This keeps the spacing between children consistent with the rest of the project.
Instead of applying many blocks, wrappers, or custom classes on elements in a list, we can use CSS Grid strategy to manage all children with one controller. That controller is the parent wrapper.

Use cases: Custom class on element
1. Globally manage the spacing of a specific element
The key words are "of a specific element".
When we have recurring elements that should have the same spacing value across the project, it may be best to use a custom class to manage the spacing. A custom class allows us to make spacing updates for this recurring element.
Global spacing wrappers on recurring elements may slow us down and make project management more difficult to manage.
We can ask ourselves two important questions to understand if we should use utility class spacing or a custom class for a specific element.
How many instances of [this element] are in the project?
If there are many instances of this specific element, the element is a recurring element in the project. We can target each instance by using a custom class.
For example, if there are 25 instances of this element in the project, we can use one custom class to target all 25 instances.
How do we want to manage each instance of [this element]?
If we want to manage each instance of [this recurring element] as one group, a custom class will help us target that group of elements and apply changes to the group globally.
Custom class on input example
Let's look at an example use case with form inputs in our project. Form inputs are used across 4 pages of the project.
The setup below shows each form_input separated by a spacing block. This strategy is used across the entire project.

If we wanted to reduce the spacing between each form_input, we would need to update each spacing block individually.
This example above is not ideal, as this change may take unnecessary effort to update each form in the project. We must go input by input to update the spacing block value.
A change to all form inputs across the project can take seconds and require little effort with the proper setup.
A custom class on the form_input will allow us to manage all form_input elements as one unified element group.
This screenshot shows each form_input with margin-bottom applied to it. The value comes from a spacing variable, so the space between inputs matches the spacing used across the project.

We have complete global control of spacing this specific element. We can change every form input on this page, and across the project, with a single change of the form_input margin-bottom CSS property.
2. Unique tablet and mobile spacing sizes
Spacing blocks and wrappers have the powerful 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, spacing blocks and wrappers will make our customizations more difficult.
We can apply spacing directly to the custom class if we need spacing customizations across breakpoints. The custom class will allow us to manage the spacing across each breakpoint.
On the breakpoint that needs a different value, we can select a different spacing variable for the element. If no variable matches what we need, we can apply a custom value directly to the element.
3. Unique one-off spacing
Sometimes we have an element that needs unique spacing. It's not part of a group of other elements, and doesn't have any specific mobile customizations. It's an element that requires a single use one-off spacing.
For example, a client insists that padding-bottom-small is too small and padding-bottom-medium is too large. They want something in the middle.
Instead of forcing this unique one-off into the utility spacing system, we can create a custom class for the element and continue with our build. For example, we can create about_testimonial-title with a one-off margin-bottom value.

When we are not clear on integrating the utility spacing system into the layout, we can create a one-off spacing for this specific element.
It's important to understand that the more we create one-off custom classes for spacing, the less we follow a globally unified spacing system. This should not be a common practice for every element.
Use cases: CSS Grid spacing
1. Spacing children elements in a list
The core use case for CSS Grid is spacing items in a list. When there are sibling elements that need the same space between each other, applying CSS Grid to a parent wrapper is an efficient way to space these elements.
CSS Grid footer links example
Let's look at an example use case with links in the footer.
We have a parent wrapper called footer_links-column that wraps footer links. We can apply display: grid with rows to create equal space between all footer links.
If we want to change the space between each footer link, we can make a single change to the footer_links-column class. Adjusting the row distance will adjust the space between all footer links.

This is an excellent strategy for a list of items that require spacing. One adjustment gives us flexible control of the spacing between the items.
CSS Grid content card example
CSS Grid spacing also works with children of content items.
We have 'content card' items nested inside a list. Each content card has elements nested in it. We can apply CSS Grid directly to the content card to space the icon, title, and paragraph inside it.

CSS Grid is applied to the benefits_item, and the elements inside are influenced.
We can adjust the gap value and adjust all benefits_item contents together with one controller. The gap value can come from our spacing variables or a gap-[size] utility class.
This strategy works very well if the spacing between each child element is equal. In our example, the spacing between each child element of the benefits_item is the same. This scenario fits perfectly into CSS Grid gap controls.
To add a child element with different spacing values in the CSS Grid, we can use our utility class spacing wrapper method together with the CSS Grid method.
In the example below, we add a button to the content card. This button requires more distance below the paragraph than the other children. This does not work with the gap value applied to benefits_item.
We can add a spacing wrapper under the paragraph that wraps the new button.

Now spacing wrapper margin-top-medium is creating additional space within the benefits_item CSS Grid system.
Spacing wrappers are excellent for using CSS Grid spacing strategy with flexibility and variation.
This works well for creating global controlled content spacing.
The benefits_item may be a recurring component throughout the site.
Some benefits_item cards have a CTA, some don't have a CTA, and some may have entirely new elements.
We can keep a global and unified benefits_item spacing with our CSS Grid controls while taking advantage of instance-specific elements and spacing variations.
Responsive spacing
Spacing in Client-First is responsive by default. We no longer need to add a second class or a combo class to change spacing at smaller breakpoints.
Our spacing values come from variables, and those variables hold a different value for each breakpoint using Webflow's Variable Modes. When the breakpoint changes, the variable returns the value set for that mode.

Any utility class or custom class using that variable follows the change automatically.
Editing responsive values
We edit responsive spacing inside the Variables panel. Select the mode we want to change, then update the value for that mode/breakpoint.
The update applies everywhere that variable is used, at that breakpoint only. Our desktop values stay as they are.
This means one edit controls how spacing scales across the entire project.
Spacing tips
padding-section-[size]
padding-section-[size] is a set of utility classes that help us manage top and bottom padding for sections globally throughout the project.
By default, we apply section padding directly to section_[section-identifier] through variables in the Section Padding group. The classes are used when we keep padding as a separate layer inside the section. Learn more in Core Structure strategy.
padding-section-small
padding-section-medium
padding-section-large


padding-section-[direction]-[size]
When a section needs a different value on the top and the bottom, we use the directional classes.
padding-section-top-[size]
padding-section-bottom-[size]
For example, a section that needs large padding above and small padding below uses padding-section-top-large and padding-section-bottom-small.

If a section's vertical padding is custom or unique, we can apply the custom padding directly to the section class, section_[section-identifier].
Optionally add margin on Heading tags
We may want each Heading tag to have the same amount of space above and below. We want to unify the spacing in our typography system.
We use a spacing variable for this margin value. The Heading spacing stays connected to our global spacing system, and it updates with the rest of the project when the variable changes.
For example, every H2 in the project has the same margin-bottom value, set from a variable.

Applying margin to the Heading tag is an effort to unify spacing above and below our Heading tags. This is how we create global spacing rules for our typography.
Margin on Heading tags works well if we have design control over the project. We can choose to have a very formalized spacing system. This is a method to unify typography in the project further.
If we are working on a website with many variations in Headings and how Headings are used in the design, this may not be a good strategy.
If we continue overriding the default Heading margin values, we create more work for ourselves.
If all or most Headings should follow the same margin across the project, this may be an effective strategy.
We have a full explanation of this typography spacing method in Typography strategy.
Flex or grid for buttons and button rows
Use CSS flex or grid to create simple button layouts.
Button with icon example
Create a button with text and an icon. Apply flex or grid to button element to create space between the text and the icon.

This is a quick and simple way to implement a button with multiple nested elements.
Button row example
Create horizontal space between two buttons. Apply the horizontal space between the buttons through the parent wrapper.

Using flex or grid on the parent wrapper of the buttons, we can create horizontal space between the buttons.
Applying margin-right directly to the button class will limit how we can use our button. We want our button to work in all instances, not only in a row of buttons.
Applying spacing blocks for horizontal margin may not work well for mobile. Many mobile designs require specific horizontal spacing.
We believe flex or grid for creating space in a row of buttons is ideal.
Avoid using utility padding to create size for inner elements
We don't recommend using the utility classes to create padding around the item content. This strategy works in terms of CSS and may achieve our required result, but we want to avoid this practice. It encourages deep class stacking and mobile styling conflicts.

Usually, the padding for inner elements will need specific size customizations through each breakpoint. We can apply the inner element padding directly on the custom class.