Stack β
Introduction β
In web development, it's a common practice to apply spacing, or margin, between elements to create a visually pleasing layout. However, a challenge arises when these elements may appear in different contexts or alongside various other elements. The margin applied directly to individual elements doesn't always account for the dynamic nature of web content, leading to issues like redundant or undesired spacing.
Using Stack β
To implement the Stack layout in your HTML, follow these steps:
- Add the
.stackclass to an HTML element to create a stacked layout.
<div class="stack">
<div>Box 1</div>
<div>Box 2</div>
<div>Box 3</div>
</div>- Optionally, add one of the
.stack-space-*classes next to.stackto adjust the spacing between elements. Choose the class that corresponds to your desired spacing:
List of stack-space classes
| Class | Value |
|---|---|
| .stack-space-3xs | --cds-sys-spacing-3xs |
| .stack-space-2xs | --cds-sys-spacing-2xs |
| .stack-space-xs | --cds-sys-spacing-xs |
| .stack-space-s | --cds-sys-spacing-s |
| .stack-space-m | --cds-sys-spacing-m |
| .stack-space-l | --cds-sys-spacing-l |
| .stack-space-xl | --cds-sys-spacing-xl |
| .stack-space-2xl | --cds-sys-spacing-2xl |
| .stack-space-3xl | --cds-sys-spacing-3xl |
For example:
<div class="stack stack-space-s">
<div>Box 1</div>
<div>Box 2</div>
<div>Box 3</div>
</div>Nested Stacks β
When you nest Stack layouts and apply margin classes to elements at different levels, it's important to maintain control and prevent unintended margin changes. Scoping with an additional div allows you to encapsulate and isolate the margin changes within specific sections, keeping the adjustments confined to that scope.
Consider a scenario where you have a primary Stack layout for a web page, and within that layout, you want to create a specific section with a different margin. You can achieve this by scoping the nested Stack within an additional div element. Here's an example:
<div class="stack stack-space-l">
<!-- Main content -->
<div>Parent 1</div>
<div>Parent 2 (Large Margin)</div>
<!-- Isolate the xs scope. It prevents adding small margin to the Parent 3 -->
<div>
Parent 3 (Large Margin)
<!-- Section with a different margin -->
<div class="stack stack-space-xs">
<div>Child 4 (Small Margin)</div>
<div>Child 5 (Small Margin)</div>
</div>
</div>
<!-- More main content with large margin -->
<div>Parent 6 (Large Margin)</div>
<div>Parent 7 (Large Margin)</div>
</div>The Challenge β
Consider the following CSS code:
p {
margin-bottom: 1.5rem;
}While this margin declaration seems straightforward, it doesn't consider the context in which a paragraph appears. In some cases, it results in the desired spacing, but in others, it may create redundant margin or even double the intended space, especially when nested within a padded parent element.
The solution β
The key to solving this problem is to style the context, not individual elements. This is where the Stack layout primitive comes into play. The Stack layout allows you to inject margin between elements based on their common parent, effectively streamlining the spacing between elements in a context-sensitive manner.
Here's how it works in CSS:
.stack > * + * {
margin-block-start: 1.5rem;
}In this CSS rule, the * + * selector represents the "owl" β it applies margin only where an element is preceded by another element, eliminating any unnecessary spacing. This approach ensures that the margin is applied purposefully, avoiding double spacing and other issues.
Handling Spacing β
The magic behind this approach lies in CSS custom properties (variables) defined both at the root level (:root) and within the .stack class. These custom properties are context-bound, meaning they adjust based on the class used.
Here's a breakdown of how the spacing is calculated:
- At the
:rootlevel, a custom property,--cds-sys-spacing-s, is defined using theclampfunction, allowing for fluid spacing based on the viewport width. This is a responsive way to manage spacing. - Within the
.stackclass, the custom property--cds-comp-composition-stack-spaceis set tovar(--cds-sys-spacing-s). When you apply a specific spacing class, such as.stack-space-2xs, it overrides the--cds-comp-composition-stack-spacewith a different value, effectively changing the spacing between stacked elements.
This technique provides flexibility and responsiveness, allowing your layout to adapt to different contexts and screen sizes without relying on fixed breakpoints.
More details at the foundation > spacing page
Customization and Special Cases β
In some scenarios, you might need to make exceptions or customize the spacing further. You can do this by creating exceptions within a single Stack context. For instance:
.stack > * + * {
margin-block-start: var(--space, 1.5em);
}
.stack-exception,
.stack-exception + * {
--space: 3rem;
}This allows you to increase spacing where needed, and the cascade handles the exceptions.