HextaUI

Hairline

Bordes y anillos de exactamente un píxel de dispositivo de ancho en cada pantalla, mediante una sola variable que lee todo el tema.

1px
inset-ring-1
hairline
inset-ring-(length:--hairline)
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>
  )
}

Hairline forma parte del tema de HextaUI. Si has añadido el tema o cualquier componente, ya lo tienes.

pnpm dlx shadcn@latest add https://hextaui.com/r/theme.json

O añádelo a tu CSS global a mano.

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;
  }
}
<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" />

Rara vez necesitarás recurrir a ella. El tema la convierte en el ancho de borde por defecto, así que border, border-t y divide-y dibujan hairlines. Usa la variable directamente donde Tailwind no tiene un valor por defecto, como anillos, contornos y líneas dibujadas con un fondo.

Un píxel CSS cubre dos o tres píxeles físicos en la mayoría de las pantallas, así que un borde de 1px tiene en realidad dos o tres píxeles de dispositivo de grosor. --hairline divide por la proporción de píxeles de la pantalla para que cada línea mida exactamente un píxel de dispositivo, como dibujan los separadores las apps nativas. En una pantalla estándar sigue siendo 1px.

Proporción de píxelesDescripción
1×1px
1.5×0.667px
2×0.5px
3×0.333px
4×0.25px

Listas y tarjetas

border y divide-y simples. Los separadores más finos agrupan las filas sin encerrarlas.

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>
  )
}
  • Los componentes de HextaUI dibujan los bordes con inset-ring-(length:--hairline) en lugar de bordes. Un anillo interior no ocupa espacio en el diseño, así que un estado que cambia el color o el ancho del anillo nunca desplaza el contenido.
  • Las líneas hairline son más ligeras en la página, así que un color de borde ajustado para líneas de 1px puede verse tenue. El --border del tema está ajustado para hairlines.
  • Usa border-2 o más ancho para dar énfasis, como una tarjeta seleccionada. Esos siguen en píxeles CSS.
NombreDescripción
--hairlineUn píxel de dispositivo, en píxeles CSS.
border-hairlineEstablece border-width en --hairline.
--default-border-widthDefinido como --hairline, así que border y divide lo usan por defecto.