HextaUI

Hairline

Des bordures et anneaux larges d’exactement un pixel d’appareil sur chaque écran, via une seule variable que tout le thème lit.

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 fait partie du thème HextaUI. Si vous avez ajouté le thème ou un composant, vous l’avez.

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

Ou ajoutez-le à votre CSS global à la main.

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

Vous aurez rarement besoin d’y recourir. Le thème en fait la largeur de bordure par défaut : border, border-t et divide-y dessinent donc tous des hairlines. Utilisez la variable directement là où Tailwind n’a pas de valeur par défaut, comme les anneaux, les contours et les lignes dessinées avec un arrière-plan.

Un pixel CSS couvre deux ou trois pixels physiques sur la plupart des écrans : une bordure de 1px fait donc en réalité deux ou trois pixels d’appareil d’épaisseur. --hairline divise par le ratio de pixels de l’écran pour que chaque ligne mesure exactement un pixel d’appareil, comme les applications natives dessinent leurs séparateurs. Sur un écran standard, il reste à 1px.

Ratio de pixelsDescription
1×1px
1.5×0.667px
2×0.5px
3×0.333px
4×0.25px

Listes et cartes

border et divide-y simples. Des séparateurs plus fins regroupent les lignes sans les enfermer.

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>
  )
}
  • Les composants HextaUI dessinent leurs bords avec inset-ring-(length:--hairline) plutôt qu’avec des bordures. Un anneau intérieur n’occupe pas d’espace de mise en page : un état qui change la couleur ou la largeur de l’anneau ne décale donc jamais le contenu.
  • Les hairlines sont plus légères à l’écran : une couleur de bordure réglée pour des lignes de 1px peut paraître pâle. Le --border du thème est réglé pour les hairlines.
  • Utilisez border-2 ou plus large pour souligner, comme une carte sélectionnée. Ceux-ci restent en pixels CSS.
NomDescription
--hairlineUn pixel d’appareil, en pixels CSS.
border-hairlineDéfinit border-width sur --hairline.
--default-border-widthDéfini sur --hairline : border et divide l’utilisent donc par défaut.