Layout

Split Content

Overview

A flexible two-column layout that keeps content aligned with the container.

The grid uses --container-inset for outer gutter columns. Each side is a SplitContentItem that can align to the container or screen edge. Use the responsive variant to stack below the md breakpoint, or fixed to keep two columns at all widths. Choose viewport (breakpointQuery="media", default) or container width (breakpointQuery="container") to control when the layout switches.

Install

npx shadcn@latest add @uxio/split-content

Usage

import { SplitContent, SplitContentItem } from "@/components/ui/split-content"

export function HeroSplit() {
  return (
    <SplitContent className="divide-y divide-border md:divide-x md:divide-y-0">
      <SplitContentItem anchor="container">…</SplitContentItem>
      <SplitContentItem anchor="screen">…</SplitContentItem>
    </SplitContent>
  )
}

For @container relative breakpoints, set breakpointQuery="container" and use @md: in your className / column classes so they stay in sync with the component.

You must pass exactly two SplitContentItem children (no wrappers that break direct children). Other node types (e.g. whitespace-only text) are ignored for that count.

Props

SplitContent

PropTypeDefaultDescription
variant"responsive" | "fixed""responsive"responsive: stack on small screens, two columns from md. fixed: always two columns.
breakpointQuery"media" | "container""media"media: viewport md:. container: default --container-inset (padding, then cqw gutter from md); responsive also gets an @container wrapper + @md: layout. Parent @container needed for cqw when fixed.
ratio"1:1" | "1:2" | "2:1""1:1"Relative column widths at the multi-column breakpoint.

SplitContentItem

PropTypeDescription
anchor"container" | "screen"container: align to the centered content column. screen: extend into the inset gutters toward the viewport edge.

Example

The preview sets --container-max-width: 480px on the wrapper so container vs screen anchors are easy to compare. With breakpointQuery="container", SplitContent itself sets --container-inset (padding below md, then the same centered-gutter math as the site shell using cqw from md up). You do not need this narrow max width in a real app; it is only for the demo.

With anchor="screen", the demo adds a background image (plus overlay) so the bleed is obvious, and uses pl-container-inset / pr-container-inset on the inner copy.

Resize the panel to see container breakpoints respond to preview width. Controls update variant, ratio, and each column’s anchor.

Left columnanchor=container
Right columnanchor=container
Drag the handle to resize the preview