HextaUI

Hairline

Bordas e anéis com exatamente um pixel de dispositivo de largura em qualquer tela, por meio de uma variável que todo o tema lê.

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 faz parte do tema do HextaUI. Se você adicionou o tema ou qualquer componente, você já o tem.

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

Ou adicione-o ao seu CSS global à mão.

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

Você raramente precisa recorrer a ele. O tema o torna a largura de borda padrão, então border, border-t e divide-y desenham hairlines. Use a variável diretamente onde o Tailwind não tem padrão, como rings, outlines e linhas desenhadas com um background.

Um pixel CSS cobre dois ou três pixels físicos na maioria das telas, então uma borda de 1px na verdade tem dois ou três pixels de dispositivo de espessura. --hairline divide pela proporção de pixels da tela para que toda linha tenha exatamente um pixel de dispositivo, como os apps nativos desenham separadores. Em uma tela padrão, continua 1px.

Proporção de pixelsDescrição
1×1px
1.5×0.667px
2×0.5px
3×0.333px
4×0.25px

Listas e cards

border e divide-y simples. Separadores mais finos agrupam as linhas sem encaixotá-las.

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>
  )
}
  • Os componentes do HextaUI desenham as bordas com inset-ring-(length:--hairline) em vez de borders. Um inset ring não ocupa espaço no layout, então um estado que muda a cor ou a largura do anel nunca desloca o conteúdo.
  • Hairlines são mais leves na página, então uma cor de borda ajustada para linhas de 1px pode parecer fraca. O --border do tema é ajustado para hairlines.
  • Use border-2 ou mais largo para dar ênfase, como em um card selecionado. Esses permanecem em pixels CSS.
NomeDescrição
--hairlineUm pixel de dispositivo, em pixels CSS.
border-hairlineDefine border-width como --hairline.
--default-border-widthDefinido como --hairline, então border e divide o usam por padrão.