HextaUI

Hairline

テーマ全体が読み取る 1 つの変数により、どの画面でも、ちょうど 1 デバイスピクセル幅の枠線とリング。

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 は HextaUI テーマの一部です。テーマまたは任意のコンポーネントを追加していれば、すでに入っています。

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

または、グローバル CSS に手動で追加します。

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

直接使う機会はほとんどありません。テーマがこれをデフォルトの枠線の幅にしているため、border、border-t、divide-y はすべてヘアラインを描画します。リング、アウトライン、背景で描く線など、Tailwind にデフォルトがない場面では、この変数を直接使ってください。

CSS の 1 ピクセルは、ほとんどの画面で 2 つか 3 つの物理ピクセルに相当するため、1px の枠線は実際にはデバイスピクセルで 2 つか 3 つ分の太さになります。--hairline はディスプレイのピクセル比で割るため、ネイティブアプリがセパレーターを描くのと同じように、すべての線がちょうど 1 デバイスピクセルになります。標準的なディスプレイでは 1px のままです。

ピクセル比説明
1×1px
1.5×0.667px
2×0.5px
3×0.333px
4×0.25px

リストとカード

プレーンな border と divide-y。より細いセパレーターは、行を囲い込まずにグループ化します。

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>
  )
}
  • HextaUI のコンポーネントは、枠線ではなく inset-ring-(length:--hairline) で縁を描画します。内側のリングはレイアウト上の空間を取らないため、リングの色や幅が変わる状態でも、コンテンツがずれることはありません。
  • ヘアラインはページ上でより薄く見えるため、1px の線に合わせた枠線の色は薄すぎるかもしれません。テーマの --border は、ヘアライン向けに調整されています。
  • 選択されたカードのように強調したい場合は、border-2 かそれ以上の太さを使います。これらは CSS ピクセルのままです。
名前説明
--hairlineCSS ピクセルで表した 1 デバイスピクセル。
border-hairlineborder-width を --hairline に設定します。
--default-border-width--hairline に設定されているため、border と divide のデフォルトになります。