Stack component manages the vertical or horizontal layout of direct children using flexbox and adjustable spacing.

Open in new tab
import type { CSSProperties } from "react";
import { Stack } from "@kesko/components";

const box = { border: "1px dashed var(--k-color-border-primary)" } as CSSProperties;

export default () => (
  <Stack direction="row" gap="sm" className="k-bg-primary k-rounded-xs k-p-sm">
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>First</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>Second</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>Third</div>
  </Stack>
);
import type { CSSProperties } from "react";
import { Stack } from "@kesko/components";

const box = { border: "1px dashed var(--k-color-border-primary)" } as CSSProperties;

export default () => (
  <Stack gap="sm">
    <Stack direction="row" gap="sm" className="k-bg-primary k-rounded-xs k-p-sm">
      <div className="k-bg-base k-px-sm k-text-sm k-font-code k-py-xs" style={box}>Start</div>
      <div className="k-bg-base k-px-sm k-text-sm k-font-code k-py-md" style={box}>Start</div>
      <div className="k-bg-base k-px-sm k-text-sm k-font-code k-py-xl" style={box}>Start</div>
    </Stack>
    <Stack direction="row" gap="sm" align="center" className="k-bg-primary k-rounded-xs k-p-sm">
      <div className="k-bg-base k-px-sm k-text-sm k-font-code k-py-xs" style={box}>Center</div>
      <div className="k-bg-base k-px-sm k-text-sm k-font-code k-py-md" style={box}>Center</div>
      <div className="k-bg-base k-px-sm k-text-sm k-font-code k-py-xl" style={box}>Center</div>
    </Stack>
    <Stack direction="row" gap="sm" align="end" className="k-bg-primary k-rounded-xs k-p-sm">
      <div className="k-bg-base k-px-sm k-text-sm k-font-code k-py-xs" style={box}>End</div>
      <div className="k-bg-base k-px-sm k-text-sm k-font-code k-py-md" style={box}>End</div>
      <div className="k-bg-base k-px-sm k-text-sm k-font-code k-py-xl" style={box}>End</div>
    </Stack>
    <Stack direction="row" gap="sm" align="stretch" className="k-bg-primary k-rounded-xs k-p-sm">
      <div className="k-bg-base k-px-sm k-text-sm k-font-code k-py-xs" style={box}>Stretch</div>
      <div className="k-bg-base k-px-sm k-text-sm k-font-code k-py-md" style={box}>Stretch</div>
      <div className="k-bg-base k-px-sm k-text-sm k-font-code k-py-xl" style={box}>Stretch</div>
    </Stack>
  </Stack>
);
import type { CSSProperties } from "react";
import { Stack } from "@kesko/components";

const box = { border: "1px dashed var(--k-color-border-primary)" } as CSSProperties;

export default () => (
  <Stack direction="column" gap="sm" className="k-bg-primary k-rounded-xs k-p-sm">
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>First</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>Second</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>Third</div>
  </Stack>
);
import type { CSSProperties } from "react";
import { Stack } from "@kesko/components";

const box = { border: "1px dashed var(--k-color-border-primary)" } as CSSProperties;

export default () => (
  <Stack direction="row" style={{ "--k-stack-gap": "3rem" } as CSSProperties} className="k-bg-primary k-rounded-xs k-p-sm">
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>First</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>Second</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>Third</div>
  </Stack>
);
import { Button, Stack } from "@kesko/components";

export default () => (
  <Stack direction="row" gap="xs" align="center" justify="end">
    <Button type="reset" appearance="outline">Reset</Button>
    <Button type="submit">Submit</Button>
  </Stack>
);
import type { CSSProperties } from "react";
import { Stack } from "@kesko/components";

const box = { border: "1px dashed var(--k-color-border-primary)" } as CSSProperties;

export default () => (
  <Stack gap="sm">
    <Stack direction="row" gap="3xs" className="k-bg-primary k-rounded-xs k-p-sm">
      <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>3xs</div>
      <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>3xs</div>
      <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>3xs</div>
    </Stack>
    <Stack direction="row" gap="2xs" className="k-bg-primary k-rounded-xs k-p-sm">
      <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>2xs</div>
      <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>2xs</div>
      <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>2xs</div>
    </Stack>
    <Stack direction="row" gap="xs" className="k-bg-primary k-rounded-xs k-p-sm">
      <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>xs</div>
      <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>xs</div>
      <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>xs</div>
    </Stack>
    <Stack direction="row" gap="sm" className="k-bg-primary k-rounded-xs k-p-sm">
      <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>sm</div>
      <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>sm</div>
      <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>sm</div>
    </Stack>
    <Stack direction="row" className="k-bg-primary k-rounded-xs k-p-sm">
      <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>md</div>
      <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>md</div>
      <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>md</div>
    </Stack>
    <Stack direction="row" gap="lg" className="k-bg-primary k-rounded-xs k-p-sm">
      <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>lg</div>
      <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>lg</div>
      <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>lg</div>
    </Stack>
    <Stack direction="row" gap="xl" className="k-bg-primary k-rounded-xs k-p-sm">
      <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>xl</div>
      <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>xl</div>
      <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>xl</div>
    </Stack>
    <Stack direction="row" gap="2xl" className="k-bg-primary k-rounded-xs k-p-sm">
      <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>2xl</div>
      <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>2xl</div>
      <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>2xl</div>
    </Stack>
    <Stack direction="row" gap="3xl" className="k-bg-primary k-rounded-xs k-p-sm">
      <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>3xl</div>
      <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>3xl</div>
      <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>3xl</div>
    </Stack>
  </Stack>
);
import type { CSSProperties } from "react";
import { Stack } from "@kesko/components";

const box = { border: "1px dashed var(--k-color-border-primary)" } as CSSProperties;

export default () => (
  <Stack gap="sm" align="stretch">
    <Stack direction="row" gap="sm" className="k-bg-primary k-rounded-xs k-p-sm">
      <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>Start</div>
      <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>Start</div>
      <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>Start</div>
    </Stack>
    <Stack direction="row" gap="sm" justify="center" className="k-bg-primary k-rounded-xs k-p-sm">
      <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>Center</div>
      <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>Center</div>
      <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>Center</div>
    </Stack>
    <Stack direction="row" gap="sm" justify="end" className="k-bg-primary k-rounded-xs k-p-sm">
      <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>End</div>
      <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>End</div>
      <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>End</div>
    </Stack>
    <Stack direction="row" gap="sm" justify="between" className="k-bg-primary k-rounded-xs k-p-sm">
      <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>Between</div>
      <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>Between</div>
      <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>Between</div>
    </Stack>
  </Stack>
);
import type { CSSProperties } from "react";
import { Stack } from "@kesko/components";

const box = { border: "1px dashed var(--k-color-border-primary)" } as CSSProperties;

export default () => (
  <Stack
    direction="row"
    gap="sm"
    nowrap
    role="region"
    aria-label="Categories"
    tabIndex={0}
    className="k-bg-primary k-rounded-xs k-p-sm"
    style={{ overflowX: "auto" }}
  >
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code k-text-nowrap" style={box}>Groceries</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code k-text-nowrap" style={box}>Hardware</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code k-text-nowrap" style={box}>Building supplies</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code k-text-nowrap" style={box}>Cars</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code k-text-nowrap" style={box}>Foodservice</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code k-text-nowrap" style={box}>Business</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code k-text-nowrap" style={box}>Tools</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code k-text-nowrap" style={box}>Electrical</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code k-text-nowrap" style={box}>Furniture</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code k-text-nowrap" style={box}>Sports</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code k-text-nowrap" style={box}>Home and garden</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code k-text-nowrap" style={box}>Pets</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code k-text-nowrap" style={box}>Beauty and health</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code k-text-nowrap" style={box}>Toys</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code k-text-nowrap" style={box}>Books</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code k-text-nowrap" style={box}>Electronics</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code k-text-nowrap" style={box}>Kitchen</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code k-text-nowrap" style={box}>Clothing</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code k-text-nowrap" style={box}>Office supplies</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code k-text-nowrap" style={box}>Travel</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code k-text-nowrap" style={box}>Seasonal</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code k-text-nowrap" style={box}>Outdoor</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code k-text-nowrap" style={box}>Baby</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code k-text-nowrap" style={box}>Cleaning</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code k-text-nowrap" style={box}>Beverages</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code k-text-nowrap" style={box}>Frozen foods</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code k-text-nowrap" style={box}>Bakery</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code k-text-nowrap" style={box}>Lighting</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code k-text-nowrap" style={box}>Plumbing</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code k-text-nowrap" style={box}>Paint</div>
  </Stack>
);
import type { CSSProperties } from "react";
import { Stack } from "@kesko/components";

const box = { border: "1px dashed var(--k-color-border-primary)" } as CSSProperties;

export default () => (
  <Stack direction="row" gap="sm" className="k-bg-primary k-rounded-xs k-p-sm">
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>Groceries</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>Hardware</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>Building supplies</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>Cars</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>Foodservice</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>Business</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>Tools</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>Electrical</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>Furniture</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>Sports</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>Home and garden</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>Pets</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>Beauty and health</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>Toys</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>Books</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>Electronics</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>Kitchen</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>Clothing</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>Office supplies</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>Travel</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>Seasonal</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>Outdoor</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>Baby</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>Cleaning</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>Beverages</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>Frozen foods</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>Bakery</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>Lighting</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>Plumbing</div>
    <div className="k-bg-base k-px-sm k-py-xs k-text-sm k-font-code" style={box}>Paint</div>
  </Stack>
);

Properties

NameDescriptionTypeDefault
direction

Layout direction. Defaults to "column".

"column" | "row""column"
gap

Gap between children, mapped to the --k-space- scale. Defaults to "md".

"3xs" | "2xs" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "3xl""md"
align

Cross-axis alignment. Defaults to "start".

"start" | "center" | "end" | "stretch""start"
justify

Main-axis distribution. Defaults to "start".

"start" | "center" | "end" | "between""start"
nowrap

Keep a row on one line. Rows wrap by default so they reflow on small screens; set this only when the container scrolls on purpose.

booleanfalse

Styles

CSS custom properties provide finer-grained control than props. Prefer the props API when it suits your need.

NameDescriptionDefault
--k-stack-gap

Overrides the gap between children.

var(--k-space-md)

Accessibility #

Stack is layout only. It renders a <k-stack> element with no role, no name and no focus stop, so assistive technologies see only its children.

  • Use a list when the items are a list. Stack adds no semantics. Three related links or products are still a list: render <ul> or <ol> with the items inside, and style that with @kesko/css utilities.
  • Let rows wrap. Rows wrap by default so the content reflows at 320px and when text is zoomed to 200%. Set nowrap only when the container scrolls on purpose, such as a strip of chips with overflow: auto, and give that Stack tabindex="0", role="region" and an aria-label so keyboard users can scroll it.
  • Size the children, not the stack. Stack does not resize what it holds. When you stack buttons, links or inputs, pick their own sizes so each stays at least 24×24 pixels, the minimum touch target size.

See the accessibility guidelines and the A11Y checklist for more details.


Usage #

There are two necessary parts to using the Stack component. The @kesko/components package and the CSS Framework are required. Everything else is optional:

npm install @kesko/components @kesko/css

Once installed, load the CSS Framework in your app’s entry point or root layout:

import "@kesko/css";

Then, you can import the Stack:

import { Stack } from "@kesko/components";

Projects without React can get the same styles from @kesko/css by importing the components stylesheet as well:

@import "@kesko/css";
@import "@kesko/css/components";

Resources #