# Hairline

> Borders and rings exactly one device pixel wide on every screen, through one variable the whole theme reads.

Docs: https://hextaui.com/docs/hairline
Markdown: https://hextaui.com/docs/hairline.md

```tsx title="components/examples/hairline/demo.tsx"
export function HairlineDemo() {
  return (
    <div className="grid w-full max-w-sm grid-cols-2 gap-4 text-sm">
      <div className="flex flex-col gap-2">
        <div className="flex h-24 items-center justify-center rounded-lg inset-ring-1 inset-ring-foreground/40">
          1px
        </div>
        <span className="text-center text-xs text-muted-foreground">
          inset-ring-1
        </span>
      </div>
      <div className="flex flex-col gap-2">
        <div className="flex h-24 items-center justify-center rounded-lg inset-ring-(length:--hairline) inset-ring-foreground/40">
          hairline
        </div>
        <span className="text-center text-xs text-muted-foreground">
          inset-ring-(length:--hairline)
        </span>
      </div>
    </div>
  )
}
```

## Installation

Hairline is part of the HextaUI theme. If you've added the theme or any component, you have it.

```bash
npx shadcn@latest add https://hextaui.com/r/theme.json
```

Or add it to your global CSS by hand.

```css title="app/globals.css"
@theme inline {
  --default-border-width: var(--hairline);
}

@utility border-hairline {
  border-width: var(--hairline);
}

:root {
  --hairline: 1px;

  @media (min-resolution: 1.5dppx) {
    --hairline: calc(1px / 1.5);
  }

  @media (min-resolution: 2dppx) {
    --hairline: 0.5px;
  }

  @media (min-resolution: 3dppx) {
    --hairline: calc(1px / 3);
  }

  @media (min-resolution: 4dppx) {
    --hairline: 0.25px;
  }
}
```

## Usage

```tsx
<div className="border" />
<ul className="divide-y" />
<div className="border-2 sm:border-hairline" />
<button className="inset-ring-(length:--hairline) inset-ring-border" />
<hr className="h-(--hairline) border-0 bg-border" />
```

You rarely need to reach for it. The theme makes it the default border width, so `border`, `border-t` and `divide-y` all draw hairlines. Use the variable directly where Tailwind has no default, like rings, outlines and lines drawn with a background.

## Why hairlines

A CSS pixel covers two or three physical pixels on most screens, so a `1px` border is really two or three device pixels thick. `--hairline` divides by the display's pixel ratio so every line is exactly one device pixel, the way native apps draw separators. On a standard display it stays 1px.

| Pixel ratio | Description |
| --- | --- |
| `1×` | 1px |
| `1.5×` | 0.667px |
| `2×` | 0.5px |
| `3×` | 0.333px |
| `4×` | 0.25px |

## Examples

### Lists and cards

Plain `border` and `divide-y`. Thinner separators group rows without boxing them in.

```tsx title="components/examples/hairline/list.tsx"
const rows = [
  ["Plan", "Pro"],
  ["Seats", "12"],
  ["Billing", "Yearly"],
  ["Renews", "Mar 4, 2027"],
]

export function HairlineList() {
  return (
    <dl className="w-full max-w-xs divide-y rounded-xl border text-sm">
      {rows.map(([term, value]) => (
        <div key={term} className="flex justify-between px-4 py-3">
          <dt className="text-muted-foreground">{term}</dt>
          <dd>{value}</dd>
        </div>
      ))}
    </dl>
  )
}
```

## Good to know

- HextaUI components draw edges with `inset-ring-(length:--hairline)` rather than borders. An inset ring takes no layout space, so a state that changes the ring's color or width never shifts the content.
- Hairlines are lighter on the page, so a border color tuned for 1px lines may look faint. The theme's `--border` is tuned for hairlines.
- Use `border-2` or wider for emphasis, like a selected card. Those stay in CSS pixels.

## API reference

| Name | Description |
| --- | --- |
| `--hairline` | One device pixel, in CSS pixels. |
| `border-hairline` | Sets border-width to --hairline. |
| `--default-border-width` | Set to --hairline, so border and divide default to it. |

## Notes for AI assistants

- Install a component with the shadcn CLI: `npx shadcn@latest add https://hextaui.com/r/<name>.json`. It adds the source, the HextaUI theme tokens and any HextaUI components it depends on. `https://hextaui.com/r/all.json` installs every component.
- The code is then owned by the project, like shadcn/ui. There is no HextaUI npm package. HextaUI is MIT licensed and free for personal and commercial use.
- Behavior and accessibility come from Base UI (`@base-ui/react`). Compose with the `render` prop, not `asChild`.
- Styling uses Tailwind CSS v4 with theme tokens. Merge classes with `cn` from the `cn` package.
- Icons come from `@tabler/icons-react`.
- Import components from `@/components/ui/<name>`, hooks from `@/hooks/<name>` and utilities from `@/lib/<name>`.

Every HextaUI doc: https://hextaui.com/llms.txt
