Layout

Container

Centres content at a set width, from a readable prose measure to full, with padding that clears safe areas.

Built on
env(safe-area-inset-*)max()
Client JavaScript
None
Works without React
Yes, as HTML and CSS
Source, gzipped
1.0 kB
Dependencies
React
Changelog
Try its options

Loading its options.

Code
import type { CSSProperties } from "react";
import { Container } from "@/components/equip/container";

const line = { height: 6, borderRadius: 3, background: "var(--eq-tint-strong)" };

export default function Demo() {
  return (
    <div
      style={{
        width: 208,
        paddingBlock: 12,
        border: "1px dashed var(--eq-line-strong)",
        borderRadius: "var(--eq-radius-m)",
      }}
    >
      <Container
        size="prose"
        padding="s"
        style={{ "--eq-container-prose": "120px" } as CSSProperties}
      >
        <div style={{ marginBottom: 8, fontSize: "var(--eq-text-s)", fontWeight: "var(--eq-weight-strong)" }}>
          Changelog
        </div>
        <div style={{ display: "grid", gap: 6 }}>
          <div style={line} />
          <div style={line} />
          <div style={{ ...line, width: "70%" }} />
        </div>
      </Container>
    </div>
  );
}
Your versionchange its options in Look, This part
HTMLworks in any framework, with the part's CSS
<div style="width:208px;padding-block:12px;border:1px dashed var(--eq-line-strong);border-radius:var(--eq-radius-m)">
  <div style="--eq-container-prose:120px" class="eq-container" data-size="prose" data-padding="s">
    <div style="margin-bottom:8px;font-size:var(--eq-text-s);font-weight:var(--eq-weight-strong)">Changelog</div>
    <div style="display:grid;gap:6px">
      <div style="height:6px;border-radius:3px;background:var(--eq-tint-strong)"></div>
      <div style="height:6px;border-radius:3px;background:var(--eq-tint-strong)"></div>
      <div style="height:6px;border-radius:3px;background:var(--eq-tint-strong);width:70%"></div>
    </div>
  </div>
</div>

Examples

Sizes

Shown scaled down. The real widths are 65ch, 40rem, 60rem and 80rem, and each can be overridden with a custom property.

prose
s
m
l
full
Code
import type { CSSProperties } from "react";
import { Container } from "@/components/equip/container";

const sizes = [
  { size: "prose", width: "26%" },
  { size: "s", width: "40%" },
  { size: "m", width: "60%" },
  { size: "l", width: "80%" },
  { size: "full", width: "" },
] as const;

export default function Example() {
  return (
    <div style={{ display: "grid", gap: 6, width: "100%" }}>
      {sizes.map(({ size, width }) => (
        <div key={size} style={{ border: "1px dashed var(--eq-line-strong)", borderRadius: "var(--eq-radius-s)" }}>
          <Container
            size={size}
            padding="s"
            style={
              {
                "--eq-container-prose": width,
                "--eq-container-s": width,
                "--eq-container-m": width,
                "--eq-container-l": width,
              } as CSSProperties
            }
          >
            <div
              style={{
                padding: "4px 8px",
                borderRadius: "var(--eq-radius-s)",
                background: "var(--eq-tint-strong)",
                fontSize: "var(--eq-text-xs)",
                color: "var(--eq-ink-2)",
              }}
            >
              {size}
            </div>
          </Container>
        </div>
      ))}
    </div>
  );
}
HTMLworks in any framework, with the part's CSS
<div style="display:grid;gap:6px;width:100%">
  <div style="border:1px dashed var(--eq-line-strong);border-radius:var(--eq-radius-s)">
    <div style="--eq-container-prose:26%;--eq-container-s:26%;--eq-container-m:26%;--eq-container-l:26%" class="eq-container" data-size="prose" data-padding="s">
      <div style="padding:4px 8px;border-radius:var(--eq-radius-s);background:var(--eq-tint-strong);font-size:var(--eq-text-xs);color:var(--eq-ink-2)">prose</div>
    </div>
  </div>
  <div style="border:1px dashed var(--eq-line-strong);border-radius:var(--eq-radius-s)">
    <div style="--eq-container-prose:40%;--eq-container-s:40%;--eq-container-m:40%;--eq-container-l:40%" class="eq-container" data-size="s" data-padding="s">
      <div style="padding:4px 8px;border-radius:var(--eq-radius-s);background:var(--eq-tint-strong);font-size:var(--eq-text-xs);color:var(--eq-ink-2)">s</div>
    </div>
  </div>
  <div style="border:1px dashed var(--eq-line-strong);border-radius:var(--eq-radius-s)">
    <div style="--eq-container-prose:60%;--eq-container-s:60%;--eq-container-m:60%;--eq-container-l:60%" class="eq-container" data-size="m" data-padding="s">
      <div style="padding:4px 8px;border-radius:var(--eq-radius-s);background:var(--eq-tint-strong);font-size:var(--eq-text-xs);color:var(--eq-ink-2)">m</div>
    </div>
  </div>
  <div style="border:1px dashed var(--eq-line-strong);border-radius:var(--eq-radius-s)">
    <div style="--eq-container-prose:80%;--eq-container-s:80%;--eq-container-m:80%;--eq-container-l:80%" class="eq-container" data-size="l" data-padding="s">
      <div style="padding:4px 8px;border-radius:var(--eq-radius-s);background:var(--eq-tint-strong);font-size:var(--eq-text-xs);color:var(--eq-ink-2)">l</div>
    </div>
  </div>
  <div style="border:1px dashed var(--eq-line-strong);border-radius:var(--eq-radius-s)">
    <div class="eq-container" data-size="full" data-padding="s">
      <div style="padding:4px 8px;border-radius:var(--eq-radius-s);background:var(--eq-tint-strong);font-size:var(--eq-text-xs);color:var(--eq-ink-2)">full</div>
    </div>
  </div>
</div>

An article at reading width

prose holds lines near 65 characters, the range most people read comfortably; the padding never drops below a notched phone's safe area.

How we cut cold starts by half

Our functions used to load every dependency on the first request. We moved the heavy ones behind dynamic imports and kept a warm pool in each region, so most requests now start in under 200 milliseconds.

The change shipped to eu-west-1 first, then to every other region over two weeks.

Code
import { Container } from "@/components/equip/container";

export default function Example() {
  return (
    <Container as="article" size="prose" padding="m" style={{ width: "100%" }}>
      <h2 style={{ margin: "0 0 8px", fontSize: "var(--eq-text-l)" }}>How we cut cold starts by half</h2>
      <p style={{ margin: "0 0 12px", color: "var(--eq-ink-2)", lineHeight: 1.6 }}>
        Our functions used to load every dependency on the first request. We moved the heavy
        ones behind dynamic imports and kept a warm pool in each region, so most requests now
        start in under 200 milliseconds.
      </p>
      <p style={{ margin: 0, color: "var(--eq-ink-2)", lineHeight: 1.6 }}>
        The change shipped to eu-west-1 first, then to every other region over two weeks.
      </p>
    </Container>
  );
}
HTMLworks in any framework, with the part's CSS
<article style="width:100%" class="eq-container" data-size="prose" data-padding="m">
  <h2 style="margin:0 0 8px;font-size:var(--eq-text-l)">How we cut cold starts by half</h2>
  <p style="margin:0 0 12px;color:var(--eq-ink-2);line-height:1.6">Our functions used to load every dependency on the first request. We moved the heavy ones behind dynamic imports and kept a warm pool in each region, so most requests now start in under 200 milliseconds.</p>
  <p style="margin:0;color:var(--eq-ink-2);line-height:1.6">The change shipped to eu-west-1 first, then to every other region over two weeks.</p>
</article>

Props

PropTypeDefaultWhat it does
as"div" | "main" | "section" | "article" | "header" | "footer""div"The root element.
size"prose" | "s" | "m" | "l" | "full""m"The widest the content gets: 65ch, 40rem, 60rem, 80rem, or no limit.
padding"none" | "s" | "m" | "l""m"Space at the start and end, from --eq-space-3 to --eq-space-6.
...restComponentProps<"div">noneEvery native attribute of the root element.
--eq-container-s, -m, -l, -proseCSS lengthnoneOverride a width for the whole product or one subtree.

Anatomy

root.eq-containerdata-size and data-padding.

Notes

  • Renders on the server with no client JavaScript.
  • The size is the width of the content; the padding is added outside it, so prose keeps its 65 character measure.
  • Each side's padding is never less than env(safe-area-inset-left) or right, so content clears a notch in landscape. Add viewport-fit=cover to the viewport meta for the insets to be reported.
  • Pass as="main" for the page's main region, so it is a landmark.

Source

Two files, and they are the whole part. Open either to read it, copy it straight from its bar, or add the part to your loadout and install it with everything else you picked.

components/equip/container.tsx31 lines
import type { ComponentProps } from "react";
import "./container.css";

export type ContainerProps = ComponentProps<"div"> & {
  /** The element at the root. */
  as?: "div" | "main" | "section" | "article" | "header" | "footer";
  /**
   * The widest the content gets. prose is a comfortable line length for reading,
   * full only adds the padding.
   */
  size?: "prose" | "s" | "m" | "l" | "full";
  /** Space at the start and end. Never less than the device's safe area. */
  padding?: "none" | "s" | "m" | "l";
};

/**
 * Centres content at a set width. Override a width with --eq-container-s,
 * --eq-container-m, --eq-container-l or --eq-container-prose.
 */
export function Container({ as = "div", size = "m", padding = "m", className, ...rest }: ContainerProps) {
  // The root changes element but never its attributes, so the div typing holds for all of them.
  const Root = as as "div";
  return (
    <Root
      {...rest}
      className={["eq-container", className].filter(Boolean).join(" ")}
      data-size={size}
      data-padding={padding}
    />
  );
}
components/equip/container.css30 lines
@layer equip {
  .eq-container {
    --_max: var(--eq-container-m, 60rem);
    --_pad: var(--eq-space-4);

    --_start: max(var(--_pad), env(safe-area-inset-left, 0px));
    --_end: max(var(--_pad), env(safe-area-inset-right, 0px));

    /* The size is the width of the content; the padding is added outside it. With full,
       --_max is none, the sum is invalid and max-width falls back to none. */
    box-sizing: border-box;
    display: block;
    width: 100%;
    max-width: calc(var(--_max) + var(--_start) + var(--_end));
    margin-inline: auto;
    padding-left: var(--_start);
    padding-right: var(--_end);
  }

  .eq-container[data-size="prose"] { --_max: var(--eq-container-prose, 65ch); }
  .eq-container[data-size="s"] { --_max: var(--eq-container-s, 40rem); }
  .eq-container[data-size="m"] { --_max: var(--eq-container-m, 60rem); }
  .eq-container[data-size="l"] { --_max: var(--eq-container-l, 80rem); }
  .eq-container[data-size="full"] { --_max: none; }

  .eq-container[data-padding="none"] { --_pad: 0px; }
  .eq-container[data-padding="s"] { --_pad: var(--eq-space-3); }
  .eq-container[data-padding="m"] { --_pad: var(--eq-space-4); }
  .eq-container[data-padding="l"] { --_pad: var(--eq-space-6); }
}

EqUIp is in beta: free for non-commercial use, no warranty, and things can change. Terms

Nothing picked yet. Press A on a part, or use the plus on the board, and the install command builds here.

Loading the index.

Loading the index