defuss-shadcn / Primitives / separator
SeparatorATM
Visually or semantically separates content. Built on the native <hr> element with support for vertical orientation and labeled separators. No JavaScript required.
On this page (15)
§Horizontal
Default horizontal separator.
§Vertical
Vertical separator between inline items. Parent must be flex.
§With text
Text inside the separator sits on the line - the lines draw themselves left and right of it. Meaningful text keeps role="separator" off, so screen readers read it.
§Side by side
data-orientation="vertical" in a flex row: the text sits on a vertical line between the two blocks (DaisyUI calls this divider-horizontal - it divides horizontally placed items).
§Responsive
data-orientation-lg="vertical": stacked with a horizontal line on small screens, side by side with a vertical one from 64rem - the parent switches to a row at the same width. Try the device sizes in the toolbar.
§Colors
data-variant colors the line (the text stays muted): neutral, primary, secondary, accent, info, success, warning and destructive (alias error). Secondary and accent take the theme's chart colors - its --secondary / --accent are pale surfaces; success, warning and info are fixed colors.
§Text position
data-align="start" or "end" moves the text to the start or end of the line (default: centered).
§Text position (vertical)
The same on a vertical line: start is the top, end the bottom.
§Sizes
data-size sets the thickness: sm 1px (the default), md 2px, lg 4px, xl 8px - with or without text.
§Gaps
data-gap sets the space between the text and the lines: none, sm, md (the default), lg, xl. For space around a separator, use the margin utilities (my-4, my-8 …).
§With Label
The older wrapper form - two separators around a span - still works; text inside the separator itself (above) is simpler.
Vertical separators between menu items with descriptions.
§List
Horizontal separators between list items.
§Decorative
A purely visual divider hidden from assistive technology using role='none'.
§CSS view file
/* -- Separator component ---------------------------------------- */@layer components { /* One element, three looks: - empty: a plain line (1px, --border) - horizontal, or vertical with data-orientation="vertical" (inside a flex row) - with text inside: the text sits ON the line - two pseudo-element lines left and right of it (above and below when vertical) Knobs: data-variant (line color), data-size (thickness), data-gap (space between text and lines), data-align="start|end" (text position), data-orientation-md / -lg="vertical" (switch to a vertical line from 48 / 64rem). --_line / --_thick / --_gap are private. */ .separator { --_line: var(--border); --_thick: 1px; --_gap: 0.75rem; border: none; margin: 0; flex-shrink: 0; background: var(--_line); /* Horizontal (default) */ height: var(--_thick); width: 100%; /* Vertical */ &[data-orientation="vertical"] { height: auto; width: var(--_thick); align-self: stretch; } /* Decorative - hidden from assistive technology */ &[aria-hidden="true"], &[role="none"] { /* No visual change - purely semantic */ } /* -- Text on the line ------------------------------------ */ &:not(:empty) { display: flex; align-items: center; gap: var(--_gap); height: auto; background: none; font-size: 0.75rem; font-weight: 500; line-height: 1.25rem; letter-spacing: 0.02em; color: var(--muted-foreground); white-space: nowrap; &::before, &::after { content: ''; flex: 1 1 0; height: var(--_thick); background: var(--_line); } /* text position along the line */ &[data-align="start"]::before { display: none; } &[data-align="end"]::after { display: none; } &[data-orientation="vertical"] { flex-direction: column; width: auto; align-self: stretch; &::before, &::after { width: var(--_thick); height: auto; min-height: 0.5rem; } } } /* -- Colors (the line; the text stays muted) -------------- */ &[data-variant="neutral"] { --_line: var(--foreground); } &[data-variant="primary"] { --_line: var(--primary); } /* the tweakcn --secondary / --accent are pale surfaces, too faint for a line: the theme's vivid chart colors instead (like the status dot) */ &[data-variant="secondary"] { --_line: var(--chart-2); } &[data-variant="accent"] { --_line: var(--chart-4); } &[data-variant="destructive"], &[data-variant="error"] { --_line: var(--destructive); } /* success / warning / info: literals - the token set has no such pairs */ &[data-variant="success"] { --_line: #16a34a; } &[data-variant="warning"] { --_line: #f59e0b; } &[data-variant="info"] { --_line: #0ea5e9; } /* -- Thickness -------------------------------------------- */ &[data-size="sm"] { --_thick: 1px; } &[data-size="md"] { --_thick: 2px; } &[data-size="lg"] { --_thick: 4px; } &[data-size="xl"] { --_thick: 8px; } /* -- Gap between the text and the lines ------------------- */ &[data-gap="none"] { --_gap: 0; } &[data-gap="sm"] { --_gap: 0.375rem; } &[data-gap="md"] { --_gap: 0.75rem; } &[data-gap="lg"] { --_gap: 1.5rem; } &[data-gap="xl"] { --_gap: 2.5rem; } /* -- Responsive: a vertical line from a breakpoint up (DaisyUI's lg:divider-horizontal). The PARENT must turn into a row at the same width - the separator only follows it. */ @media (min-width: 48rem) { &[data-orientation-md="vertical"] { height: auto; width: var(--_thick); align-self: stretch; &:not(:empty) { flex-direction: column; width: auto; &::before, &::after { width: var(--_thick); height: auto; min-height: 0.5rem; } } } } @media (min-width: 64rem) { &[data-orientation-lg="vertical"] { height: auto; width: var(--_thick); align-self: stretch; &:not(:empty) { flex-direction: column; width: auto; &::before, &::after { width: var(--_thick); height: auto; min-height: 0.5rem; } } } } } /* -- Labeled separator (the older wrapper form) -------------- Still supported; text inside .separator itself is the simpler form. */ .separator-label { display: flex; align-items: center; gap: 0.75rem; & .separator { flex: 1; } & span { font-size: 0.75rem; font-weight: 500; color: var(--muted-foreground); text-transform: uppercase; letter-spacing: 0.05em; white-space: nowrap; flex-shrink: 0; } } /* -- Accessibility ----------------------------------------- */ @media (forced-colors: active) { /* system colors would erase the line (a background) - keep it */ .separator { forced-color-adjust: none; --_line: CanvasText; color: CanvasText; } } @media (prefers-contrast: more) { .separator:not([data-variant]) { --_line: var(--foreground); } .separator:not([data-size]) { --_thick: 2px; } }}Comments, ideas or improvements? Edit this page's source on GitHub