# Composition

In CUBE CSS, the composition layer extends CSS and is very much a high level macro view—even when applied in smaller, component-level contexts.

The composition layer’s job is to create flexible, component-agnostic layout systems that support as many variants of content as possible.

This links back to the principle that the browser should be hinted with flexible CSS rules, rather than micro-managed with strict CSS rules. With the composition layer, we are suggesting layout rules and allowing the browser to make the right judgements, based on the context it finds itself in.

# Why macro-level thinking?

Even when you are working with tiny, reusable components, you have to, at some point, consider how they will be applied in a larger context: such as a page or view.

The composition layer is designed to aid this process by providing a skeletal layout structure that shouldn’t interfere with the components (or block, in the context of CUBE CSS) that are featured, but also, support any variant of a component.

# What should the composition layer do?

  • Provide high-level, flexible layouts
  • Determine how elements interact with each other
  • Create consistent flow and rhythm

# What shouldn’t the composition layer do?

  • Provide visual treatment such as colour or font style
  • Provide decorative styles such as shadows and patterns
  • Force a browser to generate a pixel-perfect layout instead of a flexible, progressive layout

# Examples

Here are two simple examples of composition. First, a traditional layout and second, a flexible rhythm and flow solution.

# Layout

Let’s take a look at this classic layout:

A line illustration of a basic layout withcomponents

A good ol’ classic hero and cards situation with a 3 column grid.

We’ve got various elements here that themselves are individual components. The composition of this layout is what controls the overall layout and rhythm of elements. Think of the composition as a skeleton.

The same illustration but the components are gone and a skeletal structure remains

As you can see, the composition handles how things stitch together, regardless of what component they happen to be.

To illustrate this further, we can put whatever components we like in our skeleton. Like this example, we replace a card with a call to action instead:

The initial illustration but one of the cards has been replaced with a new component

Our call to action isn’t out of place because the composition of this view handles all of the layout for us.

# Flow and Rhythm

To create flow and rhythm between elements, we can use the composition layer to generate a rule that sibling elements apply a margin that is either globally set, or contextually set.

.flow > * + * {
  margin-top: var(--flow-space, 1em);
}

Then, using the card example, we’d apply it like this:

<article class="card">
  <img class="card__image" alt="" />
  <div class="[ card__content ] [ flow ]">
    <!-- our content in here will auto-flow now -->
  </div>
</article>

This means now that each element within card__content will have a top margin of 1em, unless --flow-space is defined.

Content elements have a consistent 1em spacing

The default state when either --flow-space is not defined or we are in a globally set state.

We can then define --flow-space in context, like this:

.card__content {
  --flow-space: 1.4rem;
}

Content elements have a consistent 1.4rem spacing

Because --flow-space is set in context, we can see the larger spacing.

This flow system is almost identical to the Stack layout in Every Layout (opens new window).