CaptainCSS on GitHub

Stack

An object for injecting margin between elements to space them based on their contextual relationship, instead of being based on the element itself

Default class reference

Class
Properties
stackdisplay: flex;
flex-direction: column;
justify-content: flex-start;
stack--reverseflex-direction: column-reverse;
stack > *--stack-space: 1rem;
--stack-reverse: 0;
margin-top: calc(var(--stack-space) * calc(1 - var(--stack-reverse)));
margin-bottom: calc(var(--stack-space) * var(--tw-space-y-reverse));
stack--reverse > *--stack-reverse: 1;
stack--0 > *var(--stack-space): 0px;
stack--1 > *var(--stack-space): 0.25rem;
stack--2 > *var(--stack-space): 0.5rem;
stack--3 > *var(--stack-space): 0.75rem;
stack--4 > *var(--stack-space): 1rem;
stack--5 > *var(--stack-space): 1.25rem;
stack--6 > *var(--stack-space): 1.5rem;
stack--7 > *var(--stack-space): 1.75rem;
stack--8 > *var(--stack-space): 2rem;
stack--9 > *var(--stack-space): 2.25rem;
stack--10 > *var(--stack-space): 2.5rem;
stack--11 > *var(--stack-space): 2.75rem;
stack--12 > *var(--stack-space): 3rem;
stack--14 > *var(--stack-space): 3.5rem;
stack--16 > *var(--stack-space): 4rem;
stack--20 > *var(--stack-space): 5rem;
stack--24 > *var(--stack-space): 6rem;
stack--28 > *var(--stack-space): 7rem;
stack--32 > *var(--stack-space): 8rem;
stack--36 > *var(--stack-space): 9rem;
stack--40 > *var(--stack-space): 10rem;
stack--44 > *var(--stack-space): 11rem;
stack--48 > *var(--stack-space): 12rem;
stack--52 > *var(--stack-space): 13rem;
stack--56 > *var(--stack-space): 14rem;
stack--60 > *var(--stack-space): 15rem;
stack--64 > *var(--stack-space): 16rem;
stack--72 > *var(--stack-space): 18rem;
stack--80 > *var(--stack-space): 20rem;
stack--96 > *var(--stack-space): 24rem;
stack--px > *var(--stack-space): 1px;
stack--0.5 > *var(--stack-space): 0.125rem;
stack--1.5 > *var(--stack-space): 0.375rem;
stack--2.5 > *var(--stack-space): 0.625rem;
stack--3.5 > *var(--stack-space): 0.875rem;

Usage

The stack object is used when you want to apply spacing between multiple elements.

1
2
3
<div class="stack">
    <div>1/div>
    <div>2</div>
    <div>3</div>
</div>

In this form, it looks and functions exactly like the Tailwind space-y utility. But there are several reasons why the Stack is an important layout object, and worthy of its own name and class.

Styling a relationship

We're used to styling elements directly, and 'attaching' those styles to a particular element. But the stack object looks at the relationship between two elements, and styles based on that context.

A simple example may be styling blocks from a headless CMS. If a paragraph follows a paragraph, you may want a smaller spacing than if the next section heading were to follow the paragraph.

An article section title

Some paragraph content

Some more paragraph content

A new section!

Some paragraph content

<article class="stack">
  <h3>An article section title</h2>
  <p>Some paragraph content</p>
  <p>Some more paragraph content</p>
  <h3>A new section!</h2>
  <p>Some paragraph content</p>
</article>

In fact, this is exactly the same concept on which the prose utility from the tailwindcss-typography plugin is based on. It styles the relationship between elements, rather than the elements themselves, to give them their spacing.

You can add some of your own CSS to create these relationships. Here's a simple form example:

All fields are required

.stack--form {
  > * + * {
    --stack-space: theme('spacing.6');
  }
  > label + input, 
  > label + textarea {
    --stack-space: theme('spacing.1');
  }
}

Right now, Captain doesn't implement any of these relationships for you by default, but it's something we're considering for the future.

See customization options for more information on customizing the spacing between the stack items.

Stacks within stacks

You can also build stacking contexts on the fly, using nested stacks.

The above form example inline could look like:

All fields are required

<form class="stack stack--6">
  <p>All fields are required</p>
  <div>
    <div class="stack stack--1">
      <label for="name">Name:</label>
      <input id="name" name="name">
    </div>
  </div>
  <div>
    <div class="stack stack--1">
      <label for="message">Message:</label>
      <textarea id="message" name="message"></textarea>
    </div>
  </div>
</form>

When nesting stacks like this, it's important that each nested stack is wrapped in an extra element. Otherwise, it will change the spacing for itself as well, and will not receive the correct spacing.

Wrap nested stacks in an element

 <div class="stack">
   <div>
     <div class="stack stack--6">
       <p>...</p>
       <p>...</p>
     </div>
   </div>
 </div>

Don't forget or the nested stack will not get the correct margin-top from its parent stack

 <div class="stack">
-  <div>
     <div class="stack stack--6">
       <p>...</p>
       <p>...</p>
     </div>
-  </div>
 </div>

See customization options for more information on customizing the spacing between the stack items.

Giving the Stack its own name

The Stack is an extremely useful layout tool, and can be used widely across a website.

That's why it's important to give it a name: it gives developer's the ability to talk about the concept and immediately understand, without having to explain it.

It's also useful when reading source code, to give you an immediate understanding of what a particular layout is.

When you see the class stack, you know what you're working with. This is particularly true for nested stacks, or where other classes within and around the stack may be doing something similar. It allows the primitive layout objects to stand out.

Modifiers

Spacing size

The stack class also includes spacing modifiers out of the box. The default config creates these claseses from Tailwind's space config, which in turn defaults to Tailwind's global spacing config.

A stack without a modifier defaults to a spacing of 1rem.

An item
Another item
One more item
An item
Another item
One more item
<div class="stack">
    <div>An item</div>
    <div>Another item</div>
    <div>One more item</div>
</div>

<div class="stack stack--8">
    <div>An item</div>
    <div>Another item</div>
    <div>One more item</div>
</div>

See customization options for more information on customizing the spacing between the stack items.

Reversing children order

You can reverse the order of your stack using the stack--reverse modifier class. This will ensure the spacing is applied to the correct side of the elements in the stack.

1
2
3
<div class="stack stack--reverse">
    <div>1</div>
    <div>2</div>
    <div>3</div>
</div>

Responsive

The stack object can have its spacing and reverse-order set at different breakpoints:

<div class="stack md:stack--6 lg:stack--8 lg:stack--reverse">
  <div>...</div>
  <div>...</div>
</div>

Customizing

Gap

To change the gaps available to the stack class, specify the name and gap size using the gap option in the theme.stack section of your config file:

// tailwind.config.js
module.exports = {
  theme: {
    stack: (theme) => ({
+     gap: {
+       DEFAULT: '1rem',
+       ...theme('space'),
+     },
    }),
  },
}

If you only have a single stack gap size, you can specify a single size as a shorthand:

// tailwind.config.js
module.exports = {
  theme: {
    stack: {
+     gap: '1rem',
    },
  },
}

Variants

By default, only responsive variants are generated for stack utilities.

You can control which variants are generated for the stack utilities by modifying the stack property in the variants section of your tailwind.config.js file.

For example, this config will disable all variants:

  // tailwind.config.js
  module.exports = {
    variants: {
      // ...
+     stack: [],
    }
  }

Disabling entirely

If you don't plan to use the stack utilities in your project, you can disable them entirely by setting the stack property to false in the captain.plugins section of your config file:

  // tailwind.config.js
  module.exports = {
    captain: {
      plugins: {
        // ...
+       stack: false,
      }
    }
  }