Theme
On this page (15)
Component Skill — components/separator/component-skill.md

Native basis

<hr> element (horizontal rule) and <div role="separator"> for vertical orientation.

Web Platform APIs

<hr>role="separator"forced-colorsprefers-contrast

Classes

.separator.separator-label

Data attributes

data-orientationvertical - the line runs top to bottom (parent: a flex row)data-variantneutral, primary, secondary, accent, info, success, warning, destructive (alias error) - the line colordata-alignstart / end - the text's position along the line (default center)data-sizesm 1px (default), md 2px, lg 4px, xl 8px - the thicknessdata-gapnone, sm, md (default), lg, xl - space between text and linesdata-orientation-md / -lgvertical from 48 / 64rem up (the parent turns into a row at the same width)

Variants

data-orientationDirection - Element*(default)*Horizontal - <hr>verticalVertical - <div role="separator">

ARIA

role="separator"<div>Required on vertical separatorsrole="none"<hr>Marks decorative separators - hidden from ATaria-hidden="true"<hr>Alternative for decorative separators

Notes

• The vertical separator requires the parent to be a flex container.

• Text inside a <div class="separator"> sits on the line (two pseudo-element lines flank it). An empty separator must be truly empty - even a space turns it into a text separator.

• With meaningful text ("or"), leave role="separator" off - that role hides its text from screen readers - or name it with aria-label.

• The older .separator-label wrapper (two <hr> around a span) keeps working.

• Decorative separators should use role="none" or aria-hidden="true".

• In forced-colors mode, the separator uses CanvasText system color.

• In prefers-contrast: more mode, an unsized separator is 2px thick and an uncolored one takes --foreground.

• Separators are purely visual - no JavaScript required.

§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.

§Menu

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