Tailwind v4MIT licensed

Tailwind One Bit Bevel Borders with Box Shadow

Every raised or sunken control of the 16-bit desktop era is the same object: four box-shadow insets in a fixed order — outer light, outer dark, inner light, inner dark — with the order reversed for the pressed state. This is the demo where a four-layer shadow is too long to keep repeating in a class list, so it becomes a real named utility with @utility, and active:twr04-sunken gets the pressed state for free.

Live Demo
Plain CSSTailwind v4
Try it

Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time

Untitled UI React · Affiliate link

Get Untitled UI Pro

The code

<section class="twr-04 relative block w-full min-h-svh box-border bg-twr04-bg text-twr04-ink font-twr04-sans" aria-labelledby="twr-04-title">
  <h2 class="absolute size-px overflow-hidden [clip-path:inset(50%)] whitespace-nowrap" id="twr-04-title">One-bit bevel border states</h2>

  <div class="absolute top-4 right-4 z-6">
    <input class="peer absolute inset-0 size-11 m-0 opacity-0 cursor-pointer" type="checkbox" id="twr-04-theme">
    <label class="grid place-items-center size-11 cursor-pointer bg-twr04-face text-[#101010] twr04-raised peer-focus-visible:outline-2 peer-focus-visible:outline-dotted peer-focus-visible:outline-[#000] peer-focus-visible:outline-offset-[-6px]" for="twr-04-theme">
      <svg class="size-5" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><circle cx="12" cy="12" r="8" fill="none" stroke="currentColor" stroke-width="1.6"/><path d="M12 4a8 8 0 0 0 0 16Z" fill="currentColor"/></svg>
      <span class="absolute size-px overflow-hidden [clip-path:inset(50%)] whitespace-nowrap">Toggle dark surround</span>
    </label>
  </div>

  <div class="grid grid-cols-[minmax(0,1fr)] gap-5 max-w-[70rem] mx-auto px-[clamp(0.85rem,0.5rem+2vw,2rem)] pt-[clamp(3.5rem,3rem+3vw,5rem)] pb-16">
    <header class="grid gap-1.5 min-w-0">
      <p class="m-0 font-twr04-mono text-[0.68rem] tracking-[0.14em] uppercase text-[#d7f0f0]">Windows 95 &middot; system metrics, 3D objects</p>
      <h3 class="m-0 min-w-0 text-balance text-[clamp(1.3rem,1rem+1.9vw,2.1rem)] font-bold leading-tight tracking-[-0.02em] text-white [text-shadow:1px_1px_0_rgba(0,0,0,0.45)]">Four insets, one fixed order</h3>
    </header>

    <div class="grid grid-cols-[minmax(0,1fr)] gap-5 lg:grid-cols-[minmax(0,1.4fr)_minmax(0,1fr)]">
      <article class="min-w-0 grid content-start gap-3.5 p-4 bg-twr04-panel twr04-raised" aria-labelledby="twr-04-g1">
        <h4 class="m-0 text-[0.78rem] tracking-[0.1em] uppercase text-twr04-ink2" id="twr-04-g1">States</h4>
        <div class="grid gap-4 grid-cols-[repeat(auto-fit,minmax(min(100%,11rem),1fr))]">
          <div class="min-w-0 grid justify-items-start gap-2">
            <button class="min-h-11 min-w-11 px-4.5 py-2 font-inherit text-[0.9rem] cursor-pointer border-0 bg-twr04-face text-[#101010] twr04-raised active:twr04-sunken active:pt-[calc(0.5rem+1px)] active:ps-[calc(1.125rem+1px)] active:pb-[calc(0.5rem-1px)] active:pe-[calc(1.125rem-1px)] focus-visible:outline-2 focus-visible:outline-dotted focus-visible:outline-[#000] focus-visible:outline-offset-[-6px]" type="button">Raised</button>
            <p class="m-0 min-w-0 [overflow-wrap:anywhere] font-twr04-mono text-[0.66rem] leading-snug text-twr04-ink2">default &middot; light outer top-left</p>
          </div>
          <div class="min-w-0 grid justify-items-start gap-2">
            <button class="min-h-11 min-w-11 px-4.5 py-2 font-inherit text-[0.9rem] cursor-pointer border-0 bg-twr04-face text-[#101010] twr04-sunken focus-visible:outline-2 focus-visible:outline-dotted focus-visible:outline-[#000] focus-visible:outline-offset-[-6px]" type="button" aria-pressed="true">Pressed</button>
            <p class="m-0 min-w-0 [overflow-wrap:anywhere] font-twr04-mono text-[0.66rem] leading-snug text-twr04-ink2">order reversed &middot; caption offset 1px</p>
          </div>
          <div class="min-w-0 grid justify-items-start gap-2">
            <div class="min-h-11 min-w-0 flex items-center px-3.5 py-2 text-[0.9rem] bg-white text-[#101010] twr04-well">Sunken well</div>
            <p class="m-0 min-w-0 [overflow-wrap:anywhere] font-twr04-mono text-[0.66rem] leading-snug text-twr04-ink2">reversed, no caption offset</p>
          </div>
          <div class="min-w-0 grid justify-items-start gap-2">
            <button class="min-h-11 min-w-11 px-4.5 py-2 font-inherit text-[0.9rem] cursor-not-allowed border-0 bg-twr04-face text-twr04-shadow twr04-raised [text-shadow:1px_1px_0_var(--color-twr04-hilite)]" type="button" disabled>Disabled</button>
            <p class="m-0 min-w-0 [overflow-wrap:anywhere] font-twr04-mono text-[0.66rem] leading-snug text-twr04-ink2">etched caption &middot; shadow + highlight</p>
          </div>
        </div>
      </article>

      <article class="min-w-0 grid content-start gap-3.5 p-4 bg-twr04-panel twr04-raised" aria-labelledby="twr-04-g2">
        <h4 class="m-0 text-[0.78rem] tracking-[0.1em] uppercase text-twr04-ink2" id="twr-04-g2">Exploded edge</h4>
        <div class="grid gap-1.5 min-w-0">
          <div class="min-w-0 flex items-center gap-2.5 [overflow-wrap:anywhere] font-twr04-mono text-[0.72rem] px-2.5 py-2.5 bg-twr04-face text-[#101010] [box-shadow:inset_0_3px_0_0_var(--color-twr04-hilite),inset_3px_0_0_0_var(--color-twr04-hilite)]"><span class="flex-none grid place-items-center size-[22px] bg-[#101010] text-twr04-face text-[0.7rem]">1</span> inset 1px 1px 0 #ffffff</div>
          <div class="min-w-0 flex items-center gap-2.5 [overflow-wrap:anywhere] font-twr04-mono text-[0.72rem] px-2.5 py-2.5 bg-twr04-face text-[#101010] [box-shadow:inset_0_-3px_0_0_var(--color-twr04-dark),inset_-3px_0_0_0_var(--color-twr04-dark)]"><span class="flex-none grid place-items-center size-[22px] bg-[#101010] text-twr04-face text-[0.7rem]">2</span> inset -1px -1px 0 #000000</div>
          <div class="min-w-0 flex items-center gap-2.5 [overflow-wrap:anywhere] font-twr04-mono text-[0.72rem] px-2.5 py-2.5 bg-twr04-face text-[#101010] [box-shadow:inset_0_3px_0_0_var(--color-twr04-light),inset_3px_0_0_0_var(--color-twr04-light)]"><span class="flex-none grid place-items-center size-[22px] bg-[#101010] text-twr04-face text-[0.7rem]">3</span> inset 2px 2px 0 #dfdfdf</div>
          <div class="min-w-0 flex items-center gap-2.5 [overflow-wrap:anywhere] font-twr04-mono text-[0.72rem] px-2.5 py-2.5 bg-twr04-face text-[#101010] [box-shadow:inset_0_-3px_0_0_var(--color-twr04-shadow),inset_-3px_0_0_0_var(--color-twr04-shadow)]"><span class="flex-none grid place-items-center size-[22px] bg-[#101010] text-twr04-face text-[0.7rem]">4</span> inset -2px -2px 0 #808080</div>
        </div>
        <p class="m-0 min-w-0 text-[0.8rem] leading-normal text-pretty text-twr04-ink2">Painted first to last, top to bottom. Later layers sit underneath.</p>
      </article>
    </div>

    <article class="min-w-0 grid content-start gap-3.5 p-4 bg-twr04-panel twr04-raised" aria-labelledby="twr-04-g3">
      <h4 class="m-0 text-[0.78rem] tracking-[0.1em] uppercase text-twr04-ink2" id="twr-04-g3">Applied &mdash; a dialog built only from insets</h4>
      <div class="min-w-0 p-[3px] bg-twr04-face twr04-raised">
        <div class="flex items-center justify-between gap-2 min-w-0 m-[3px] py-1.5 pe-1.5 ps-2.5 [background:linear-gradient(90deg,var(--color-twr04-titlea),var(--color-twr04-titleb))]">
          <span class="min-w-0 overflow-hidden text-ellipsis whitespace-nowrap text-white text-[0.85rem] font-bold">Display Properties</span>
          <span class="flex flex-none gap-[3px]">
            <button class="grid place-items-center size-11 p-0 border-0 cursor-pointer font-inherit text-[0.8rem] leading-none bg-twr04-face text-[#101010] twr04-raised active:twr04-sunken focus-visible:outline-2 focus-visible:outline-dotted focus-visible:outline-[#000] focus-visible:outline-offset-[-7px]" type="button" aria-label="Minimise"><span aria-hidden="true">_</span></button>
            <button class="grid place-items-center size-11 p-0 border-0 cursor-pointer font-inherit text-[0.8rem] leading-none bg-twr04-face text-[#101010] twr04-raised active:twr04-sunken focus-visible:outline-2 focus-visible:outline-dotted focus-visible:outline-[#000] focus-visible:outline-offset-[-7px]" type="button" aria-label="Maximise"><span aria-hidden="true">&#9633;</span></button>
            <button class="grid place-items-center size-11 p-0 border-0 cursor-pointer font-inherit text-[0.8rem] leading-none bg-twr04-face text-[#101010] twr04-raised active:twr04-sunken focus-visible:outline-2 focus-visible:outline-dotted focus-visible:outline-[#000] focus-visible:outline-offset-[-7px]" type="button" aria-label="Close"><span aria-hidden="true">&#215;</span></button>
          </span>
        </div>
        <div class="grid gap-3.5 min-w-0 px-3 pt-4 pb-3.5">
          <p class="m-0 min-w-0 text-[0.88rem] leading-normal text-pretty text-[#101010]">The bevel unit is a single custom property. Every control below shares it.</p>
          <div class="flex flex-wrap items-center gap-2.5 min-w-0">
            <span class="min-w-0 text-[0.85rem] text-[#101010]" id="twr-04-fl">Colour palette</span>
            <span class="min-h-11 flex-1 basis-40 flex items-center px-3.5 py-2 bg-white text-[#101010] font-twr04-mono text-[0.82rem] twr04-well" role="status" aria-labelledby="twr-04-fl">256 Colour</span>
          </div>
          <div class="flex flex-wrap gap-2">
            <button class="min-h-11 min-w-11 px-4.5 py-2 font-inherit text-[0.9rem] cursor-pointer border-0 bg-twr04-face text-[#101010] twr04-raised active:twr04-sunken active:pt-[calc(0.5rem+1px)] active:ps-[calc(1.125rem+1px)] active:pb-[calc(0.5rem-1px)] active:pe-[calc(1.125rem-1px)] focus-visible:outline-2 focus-visible:outline-dotted focus-visible:outline-[#000] focus-visible:outline-offset-[-6px]" type="button">OK</button>
            <button class="min-h-11 min-w-11 px-4.5 py-2 font-inherit text-[0.9rem] cursor-pointer border-0 bg-twr04-face text-[#101010] twr04-raised active:twr04-sunken active:pt-[calc(0.5rem+1px)] active:ps-[calc(1.125rem+1px)] active:pb-[calc(0.5rem-1px)] active:pe-[calc(1.125rem-1px)] focus-visible:outline-2 focus-visible:outline-dotted focus-visible:outline-[#000] focus-visible:outline-offset-[-6px]" type="button">Cancel</button>
            <button class="min-h-11 min-w-11 px-4.5 py-2 font-inherit text-[0.9rem] cursor-pointer border-0 bg-twr04-face text-[#101010] twr04-raised active:twr04-sunken active:pt-[calc(0.5rem+1px)] active:ps-[calc(1.125rem+1px)] active:pb-[calc(0.5rem-1px)] active:pe-[calc(1.125rem-1px)] focus-visible:outline-2 focus-visible:outline-dotted focus-visible:outline-[#000] focus-visible:outline-offset-[-6px]" type="button">Apply</button>
          </div>
        </div>
      </div>
    </article>
  </div>
</section>
@import "tailwindcss";

@theme {
  --color-twr04-face: #c0c0c0;
  --color-twr04-hilite: #ffffff;
  --color-twr04-light: #dfdfdf;
  --color-twr04-shadow: #808080;
  --color-twr04-dark: #000000;
  --color-twr04-titlea: #000080;
  --color-twr04-titleb: #1084d0;
  --color-twr04-panel: #d8d8d0;
  --color-twr04-bg: #008080;
  --color-twr04-ink: #101214;
  --color-twr04-ink: oklch(0.18 0.006 240);
  --color-twr04-ink2: #3d4348;
  --color-twr04-ink2: oklch(0.38 0.01 240);
  --font-twr04-sans: system-ui, -apple-system, 'Segoe UI', Tahoma, Arial, sans-serif;
  --font-twr04-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

.twr-04 {
  --twr-04-b: 2px;
}
/* A repeated VALUE becomes an @theme token; a repeated DECLARATION BLOCK becomes
   an @utility. These register in the utility layer, so active:, hover: and
   breakpoint variants compose with them exactly like built-ins — which @apply
   would not allow. */

@utility twr04-raised {
  box-shadow: inset var(--twr-04-b) var(--twr-04-b) 0 0 var(--color-twr04-hilite), inset calc(var(--twr-04-b) * -1) calc(var(--twr-04-b) * -1) 0 0 var(--color-twr04-dark), inset calc(var(--twr-04-b) * 2) calc(var(--twr-04-b) * 2) 0 0 var(--color-twr04-light), inset calc(var(--twr-04-b) * -2) calc(var(--twr-04-b) * -2) 0 0 var(--color-twr04-shadow);
}

@utility twr04-sunken {
  box-shadow: inset var(--twr-04-b) var(--twr-04-b) 0 0 var(--color-twr04-dark), inset calc(var(--twr-04-b) * -1) calc(var(--twr-04-b) * -1) 0 0 var(--color-twr04-hilite), inset calc(var(--twr-04-b) * 2) calc(var(--twr-04-b) * 2) 0 0 var(--color-twr04-shadow), inset calc(var(--twr-04-b) * -2) calc(var(--twr-04-b) * -2) 0 0 var(--color-twr04-light);
}
/* A well is sunken against white rather than face grey, so the tone pairs differ. */

@utility twr04-well {
  box-shadow: inset var(--twr-04-b) var(--twr-04-b) 0 0 var(--color-twr04-shadow), inset calc(var(--twr-04-b) * -1) calc(var(--twr-04-b) * -1) 0 0 var(--color-twr04-hilite), inset calc(var(--twr-04-b) * 2) calc(var(--twr-04-b) * 2) 0 0 var(--color-twr04-dark), inset calc(var(--twr-04-b) * -2) calc(var(--twr-04-b) * -2) 0 0 var(--color-twr04-light);
}

.twr-04:has(#twr-04-theme:checked) {
  --color-twr04-bg: #0a2c2c;
  --color-twr04-bg: oklch(0.26 0.045 195);
  --color-twr04-panel: #cfcfc7;
}

Setup — do this once per project

Skip this if your project already runs Tailwind v4.

1Load Tailwind
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>

Compiles in the browser — perfect for a CodePen or a quick test, not for production.

2Add the stylesheetRequiredthe @theme block is what makes the custom utilities exist
@import "tailwindcss";

@theme {
  --color-twr04-face: #c0c0c0;
  --color-twr04-hilite: #ffffff;
  --color-twr04-light: #dfdfdf;
  --color-twr04-shadow: #808080;
  --color-twr04-dark: #000000;
  --color-twr04-titlea: #000080;
  --color-twr04-titleb: #1084d0;
  --color-twr04-panel: #d8d8d0;
  --color-twr04-bg: #008080;
  --color-twr04-ink: #101214;
  --color-twr04-ink: oklch(0.18 0.006 240);
  --color-twr04-ink2: #3d4348;
  --color-twr04-ink2: oklch(0.38 0.01 240);
  --font-twr04-sans: system-ui, -apple-system, 'Segoe UI', Tahoma, Arial, sans-serif;
  --font-twr04-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

.twr-04 {
  --twr-04-b: 2px;
}
/* A repeated VALUE becomes an @theme token; a repeated DECLARATION BLOCK becomes
   an @utility. These register in the utility layer, so active:, hover: and
   breakpoint variants compose with them exactly like built-ins — which @apply
   would not allow. */

@utility twr04-raised {
  box-shadow: inset var(--twr-04-b) var(--twr-04-b) 0 0 var(--color-twr04-hilite), inset calc(var(--twr-04-b) * -1) calc(var(--twr-04-b) * -1) 0 0 var(--color-twr04-dark), inset calc(var(--twr-04-b) * 2) calc(var(--twr-04-b) * 2) 0 0 var(--color-twr04-light), inset calc(var(--twr-04-b) * -2) calc(var(--twr-04-b) * -2) 0 0 var(--color-twr04-shadow);
}

@utility twr04-sunken {
  box-shadow: inset var(--twr-04-b) var(--twr-04-b) 0 0 var(--color-twr04-dark), inset calc(var(--twr-04-b) * -1) calc(var(--twr-04-b) * -1) 0 0 var(--color-twr04-hilite), inset calc(var(--twr-04-b) * 2) calc(var(--twr-04-b) * 2) 0 0 var(--color-twr04-shadow), inset calc(var(--twr-04-b) * -2) calc(var(--twr-04-b) * -2) 0 0 var(--color-twr04-light);
}
/* A well is sunken against white rather than face grey, so the tone pairs differ. */

@utility twr04-well {
  box-shadow: inset var(--twr-04-b) var(--twr-04-b) 0 0 var(--color-twr04-shadow), inset calc(var(--twr-04-b) * -1) calc(var(--twr-04-b) * -1) 0 0 var(--color-twr04-hilite), inset calc(var(--twr-04-b) * 2) calc(var(--twr-04-b) * 2) 0 0 var(--color-twr04-dark), inset calc(var(--twr-04-b) * -2) calc(var(--twr-04-b) * -2) 0 0 var(--color-twr04-light);
}

.twr-04:has(#twr-04-theme:checked) {
  --color-twr04-bg: #0a2c2c;
  --color-twr04-bg: oklch(0.26 0.045 195);
  --color-twr04-panel: #cfcfc7;
}
3Fonts used by this demooptional — skip if you have your own type stack
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500&display=swap">

What changed in the port

Which parts became utilities, which stayed CSS, and why.

  • The webfonts load as <link> tags in setup, not as an @import in the stylesheet — Tailwind emits user @import rules after its own layers, where the browser drops them.
  • This is the collection's @utility demo. Three named utilities replace nine copies of a four-layer shadow, and because they register in the utility layer, active:twr04-sunken works with no extra rule.
  • @apply would have produced a plain class with no variant support — the distinction worth carrying away from this port.
  • The pressed state's 1px content travel stays in the markup as four active: padding utilities, because that part genuinely is per-element and belongs where you can see it.
  • The bevel unit is a plain custom property on the section, read inside the utilities with calc(). Setting it per-element ([--twr-04-b:1px]) rescales any subtree.
  • System-metric colours are exact sRGB hex with no oklch twin: they are hardware values, and converting them drifts the look.
  • Hit areas are size-11 / min-h-11 everywhere while the bevel geometry stays period-correct — the two are independent because the shadow is unit-driven rather than size-driven.
Paste this into ChatGPT, Claude, Cursor, or any coding assistant. The block below is pre-framed with everything the AI needs to integrate this demo into your project — markup, styles, scoping notes, and the source URL. Hit Copy and paste straight into your chat.
Here's a working CSS demo from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Tailwind One Bit Bevel Borders with Box Shadow
Source: https://codefronts.com/design-styles/tailwind-retro-ui/tailwind-one-bit-bevel-borders-with-box-shadow/

Every raised or sunken control of the 16-bit desktop era is the same object: four box-shadow insets in a fixed order &mdash; outer light, outer dark, inner light, inner dark &mdash; with the order reversed for the pressed state. This is the demo where a four-layer shadow is too long to keep repeating in a class list, so it becomes a real named utility with @utility, and active:twr04-sunken gets the pressed state for free.
## HTML
```html
<section class="twr-04 relative block w-full min-h-svh box-border bg-twr04-bg text-twr04-ink font-twr04-sans" aria-labelledby="twr-04-title">
  <h2 class="absolute size-px overflow-hidden [clip-path:inset(50%)] whitespace-nowrap" id="twr-04-title">One-bit bevel border states</h2>

  <div class="absolute top-4 right-4 z-6">
    <input class="peer absolute inset-0 size-11 m-0 opacity-0 cursor-pointer" type="checkbox" id="twr-04-theme">
    <label class="grid place-items-center size-11 cursor-pointer bg-twr04-face text-[#101010] twr04-raised peer-focus-visible:outline-2 peer-focus-visible:outline-dotted peer-focus-visible:outline-[#000] peer-focus-visible:outline-offset-[-6px]" for="twr-04-theme">
      <svg class="size-5" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><circle cx="12" cy="12" r="8" fill="none" stroke="currentColor" stroke-width="1.6"/><path d="M12 4a8 8 0 0 0 0 16Z" fill="currentColor"/></svg>
      <span class="absolute size-px overflow-hidden [clip-path:inset(50%)] whitespace-nowrap">Toggle dark surround</span>
    </label>
  </div>

  <div class="grid grid-cols-[minmax(0,1fr)] gap-5 max-w-[70rem] mx-auto px-[clamp(0.85rem,0.5rem+2vw,2rem)] pt-[clamp(3.5rem,3rem+3vw,5rem)] pb-16">
    <header class="grid gap-1.5 min-w-0">
      <p class="m-0 font-twr04-mono text-[0.68rem] tracking-[0.14em] uppercase text-[#d7f0f0]">Windows 95 &middot; system metrics, 3D objects</p>
      <h3 class="m-0 min-w-0 text-balance text-[clamp(1.3rem,1rem+1.9vw,2.1rem)] font-bold leading-tight tracking-[-0.02em] text-white [text-shadow:1px_1px_0_rgba(0,0,0,0.45)]">Four insets, one fixed order</h3>
    </header>

    <div class="grid grid-cols-[minmax(0,1fr)] gap-5 lg:grid-cols-[minmax(0,1.4fr)_minmax(0,1fr)]">
      <article class="min-w-0 grid content-start gap-3.5 p-4 bg-twr04-panel twr04-raised" aria-labelledby="twr-04-g1">
        <h4 class="m-0 text-[0.78rem] tracking-[0.1em] uppercase text-twr04-ink2" id="twr-04-g1">States</h4>
        <div class="grid gap-4 grid-cols-[repeat(auto-fit,minmax(min(100%,11rem),1fr))]">
          <div class="min-w-0 grid justify-items-start gap-2">
            <button class="min-h-11 min-w-11 px-4.5 py-2 font-inherit text-[0.9rem] cursor-pointer border-0 bg-twr04-face text-[#101010] twr04-raised active:twr04-sunken active:pt-[calc(0.5rem+1px)] active:ps-[calc(1.125rem+1px)] active:pb-[calc(0.5rem-1px)] active:pe-[calc(1.125rem-1px)] focus-visible:outline-2 focus-visible:outline-dotted focus-visible:outline-[#000] focus-visible:outline-offset-[-6px]" type="button">Raised</button>
            <p class="m-0 min-w-0 [overflow-wrap:anywhere] font-twr04-mono text-[0.66rem] leading-snug text-twr04-ink2">default &middot; light outer top-left</p>
          </div>
          <div class="min-w-0 grid justify-items-start gap-2">
            <button class="min-h-11 min-w-11 px-4.5 py-2 font-inherit text-[0.9rem] cursor-pointer border-0 bg-twr04-face text-[#101010] twr04-sunken focus-visible:outline-2 focus-visible:outline-dotted focus-visible:outline-[#000] focus-visible:outline-offset-[-6px]" type="button" aria-pressed="true">Pressed</button>
            <p class="m-0 min-w-0 [overflow-wrap:anywhere] font-twr04-mono text-[0.66rem] leading-snug text-twr04-ink2">order reversed &middot; caption offset 1px</p>
          </div>
          <div class="min-w-0 grid justify-items-start gap-2">
            <div class="min-h-11 min-w-0 flex items-center px-3.5 py-2 text-[0.9rem] bg-white text-[#101010] twr04-well">Sunken well</div>
            <p class="m-0 min-w-0 [overflow-wrap:anywhere] font-twr04-mono text-[0.66rem] leading-snug text-twr04-ink2">reversed, no caption offset</p>
          </div>
          <div class="min-w-0 grid justify-items-start gap-2">
            <button class="min-h-11 min-w-11 px-4.5 py-2 font-inherit text-[0.9rem] cursor-not-allowed border-0 bg-twr04-face text-twr04-shadow twr04-raised [text-shadow:1px_1px_0_var(--color-twr04-hilite)]" type="button" disabled>Disabled</button>
            <p class="m-0 min-w-0 [overflow-wrap:anywhere] font-twr04-mono text-[0.66rem] leading-snug text-twr04-ink2">etched caption &middot; shadow + highlight</p>
          </div>
        </div>
      </article>

      <article class="min-w-0 grid content-start gap-3.5 p-4 bg-twr04-panel twr04-raised" aria-labelledby="twr-04-g2">
        <h4 class="m-0 text-[0.78rem] tracking-[0.1em] uppercase text-twr04-ink2" id="twr-04-g2">Exploded edge</h4>
        <div class="grid gap-1.5 min-w-0">
          <div class="min-w-0 flex items-center gap-2.5 [overflow-wrap:anywhere] font-twr04-mono text-[0.72rem] px-2.5 py-2.5 bg-twr04-face text-[#101010] [box-shadow:inset_0_3px_0_0_var(--color-twr04-hilite),inset_3px_0_0_0_var(--color-twr04-hilite)]"><span class="flex-none grid place-items-center size-[22px] bg-[#101010] text-twr04-face text-[0.7rem]">1</span> inset 1px 1px 0 #ffffff</div>
          <div class="min-w-0 flex items-center gap-2.5 [overflow-wrap:anywhere] font-twr04-mono text-[0.72rem] px-2.5 py-2.5 bg-twr04-face text-[#101010] [box-shadow:inset_0_-3px_0_0_var(--color-twr04-dark),inset_-3px_0_0_0_var(--color-twr04-dark)]"><span class="flex-none grid place-items-center size-[22px] bg-[#101010] text-twr04-face text-[0.7rem]">2</span> inset -1px -1px 0 #000000</div>
          <div class="min-w-0 flex items-center gap-2.5 [overflow-wrap:anywhere] font-twr04-mono text-[0.72rem] px-2.5 py-2.5 bg-twr04-face text-[#101010] [box-shadow:inset_0_3px_0_0_var(--color-twr04-light),inset_3px_0_0_0_var(--color-twr04-light)]"><span class="flex-none grid place-items-center size-[22px] bg-[#101010] text-twr04-face text-[0.7rem]">3</span> inset 2px 2px 0 #dfdfdf</div>
          <div class="min-w-0 flex items-center gap-2.5 [overflow-wrap:anywhere] font-twr04-mono text-[0.72rem] px-2.5 py-2.5 bg-twr04-face text-[#101010] [box-shadow:inset_0_-3px_0_0_var(--color-twr04-shadow),inset_-3px_0_0_0_var(--color-twr04-shadow)]"><span class="flex-none grid place-items-center size-[22px] bg-[#101010] text-twr04-face text-[0.7rem]">4</span> inset -2px -2px 0 #808080</div>
        </div>
        <p class="m-0 min-w-0 text-[0.8rem] leading-normal text-pretty text-twr04-ink2">Painted first to last, top to bottom. Later layers sit underneath.</p>
      </article>
    </div>

    <article class="min-w-0 grid content-start gap-3.5 p-4 bg-twr04-panel twr04-raised" aria-labelledby="twr-04-g3">
      <h4 class="m-0 text-[0.78rem] tracking-[0.1em] uppercase text-twr04-ink2" id="twr-04-g3">Applied &mdash; a dialog built only from insets</h4>
      <div class="min-w-0 p-[3px] bg-twr04-face twr04-raised">
        <div class="flex items-center justify-between gap-2 min-w-0 m-[3px] py-1.5 pe-1.5 ps-2.5 [background:linear-gradient(90deg,var(--color-twr04-titlea),var(--color-twr04-titleb))]">
          <span class="min-w-0 overflow-hidden text-ellipsis whitespace-nowrap text-white text-[0.85rem] font-bold">Display Properties</span>
          <span class="flex flex-none gap-[3px]">
            <button class="grid place-items-center size-11 p-0 border-0 cursor-pointer font-inherit text-[0.8rem] leading-none bg-twr04-face text-[#101010] twr04-raised active:twr04-sunken focus-visible:outline-2 focus-visible:outline-dotted focus-visible:outline-[#000] focus-visible:outline-offset-[-7px]" type="button" aria-label="Minimise"><span aria-hidden="true">_</span></button>
            <button class="grid place-items-center size-11 p-0 border-0 cursor-pointer font-inherit text-[0.8rem] leading-none bg-twr04-face text-[#101010] twr04-raised active:twr04-sunken focus-visible:outline-2 focus-visible:outline-dotted focus-visible:outline-[#000] focus-visible:outline-offset-[-7px]" type="button" aria-label="Maximise"><span aria-hidden="true">&#9633;</span></button>
            <button class="grid place-items-center size-11 p-0 border-0 cursor-pointer font-inherit text-[0.8rem] leading-none bg-twr04-face text-[#101010] twr04-raised active:twr04-sunken focus-visible:outline-2 focus-visible:outline-dotted focus-visible:outline-[#000] focus-visible:outline-offset-[-7px]" type="button" aria-label="Close"><span aria-hidden="true">&#215;</span></button>
          </span>
        </div>
        <div class="grid gap-3.5 min-w-0 px-3 pt-4 pb-3.5">
          <p class="m-0 min-w-0 text-[0.88rem] leading-normal text-pretty text-[#101010]">The bevel unit is a single custom property. Every control below shares it.</p>
          <div class="flex flex-wrap items-center gap-2.5 min-w-0">
            <span class="min-w-0 text-[0.85rem] text-[#101010]" id="twr-04-fl">Colour palette</span>
            <span class="min-h-11 flex-1 basis-40 flex items-center px-3.5 py-2 bg-white text-[#101010] font-twr04-mono text-[0.82rem] twr04-well" role="status" aria-labelledby="twr-04-fl">256 Colour</span>
          </div>
          <div class="flex flex-wrap gap-2">
            <button class="min-h-11 min-w-11 px-4.5 py-2 font-inherit text-[0.9rem] cursor-pointer border-0 bg-twr04-face text-[#101010] twr04-raised active:twr04-sunken active:pt-[calc(0.5rem+1px)] active:ps-[calc(1.125rem+1px)] active:pb-[calc(0.5rem-1px)] active:pe-[calc(1.125rem-1px)] focus-visible:outline-2 focus-visible:outline-dotted focus-visible:outline-[#000] focus-visible:outline-offset-[-6px]" type="button">OK</button>
            <button class="min-h-11 min-w-11 px-4.5 py-2 font-inherit text-[0.9rem] cursor-pointer border-0 bg-twr04-face text-[#101010] twr04-raised active:twr04-sunken active:pt-[calc(0.5rem+1px)] active:ps-[calc(1.125rem+1px)] active:pb-[calc(0.5rem-1px)] active:pe-[calc(1.125rem-1px)] focus-visible:outline-2 focus-visible:outline-dotted focus-visible:outline-[#000] focus-visible:outline-offset-[-6px]" type="button">Cancel</button>
            <button class="min-h-11 min-w-11 px-4.5 py-2 font-inherit text-[0.9rem] cursor-pointer border-0 bg-twr04-face text-[#101010] twr04-raised active:twr04-sunken active:pt-[calc(0.5rem+1px)] active:ps-[calc(1.125rem+1px)] active:pb-[calc(0.5rem-1px)] active:pe-[calc(1.125rem-1px)] focus-visible:outline-2 focus-visible:outline-dotted focus-visible:outline-[#000] focus-visible:outline-offset-[-6px]" type="button">Apply</button>
          </div>
        </div>
      </div>
    </article>
  </div>
</section>
```
## CSS
```css
@import "tailwindcss";

@theme {
  --color-twr04-face: #c0c0c0;
  --color-twr04-hilite: #ffffff;
  --color-twr04-light: #dfdfdf;
  --color-twr04-shadow: #808080;
  --color-twr04-dark: #000000;
  --color-twr04-titlea: #000080;
  --color-twr04-titleb: #1084d0;
  --color-twr04-panel: #d8d8d0;
  --color-twr04-bg: #008080;
  --color-twr04-ink: #101214;
  --color-twr04-ink: oklch(0.18 0.006 240);
  --color-twr04-ink2: #3d4348;
  --color-twr04-ink2: oklch(0.38 0.01 240);
  --font-twr04-sans: system-ui, -apple-system, 'Segoe UI', Tahoma, Arial, sans-serif;
  --font-twr04-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

.twr-04 {
  --twr-04-b: 2px;
}
/* A repeated VALUE becomes an @theme token; a repeated DECLARATION BLOCK becomes
   an @utility. These register in the utility layer, so active:, hover: and
   breakpoint variants compose with them exactly like built-ins — which @apply
   would not allow. */

@utility twr04-raised {
  box-shadow: inset var(--twr-04-b) var(--twr-04-b) 0 0 var(--color-twr04-hilite), inset calc(var(--twr-04-b) * -1) calc(var(--twr-04-b) * -1) 0 0 var(--color-twr04-dark), inset calc(var(--twr-04-b) * 2) calc(var(--twr-04-b) * 2) 0 0 var(--color-twr04-light), inset calc(var(--twr-04-b) * -2) calc(var(--twr-04-b) * -2) 0 0 var(--color-twr04-shadow);
}

@utility twr04-sunken {
  box-shadow: inset var(--twr-04-b) var(--twr-04-b) 0 0 var(--color-twr04-dark), inset calc(var(--twr-04-b) * -1) calc(var(--twr-04-b) * -1) 0 0 var(--color-twr04-hilite), inset calc(var(--twr-04-b) * 2) calc(var(--twr-04-b) * 2) 0 0 var(--color-twr04-shadow), inset calc(var(--twr-04-b) * -2) calc(var(--twr-04-b) * -2) 0 0 var(--color-twr04-light);
}
/* A well is sunken against white rather than face grey, so the tone pairs differ. */

@utility twr04-well {
  box-shadow: inset var(--twr-04-b) var(--twr-04-b) 0 0 var(--color-twr04-shadow), inset calc(var(--twr-04-b) * -1) calc(var(--twr-04-b) * -1) 0 0 var(--color-twr04-hilite), inset calc(var(--twr-04-b) * 2) calc(var(--twr-04-b) * 2) 0 0 var(--color-twr04-dark), inset calc(var(--twr-04-b) * -2) calc(var(--twr-04-b) * -2) 0 0 var(--color-twr04-light);
}

.twr-04:has(#twr-04-theme:checked) {
  --color-twr04-bg: #0a2c2c;
  --color-twr04-bg: oklch(0.26 0.045 195);
  --color-twr04-panel: #cfcfc7;
}
```

How this works

The bevel is four edges, not a border. A raised control has a bright outer highlight and a softer inner light on the top-left, a mid grey inner shadow and a hard black outer shadow on the bottom-right. The second tone on each side is what makes the edge read as chiselled metal rather than a drawn line, and it is the detail most reproductions leave out.

Order is the mechanism. box-shadow paints the first layer on top, so the list reads outermost edge inwards. Swap any two and the wider inset overpaints the narrower one, collapsing the edge into a flat two-tone frame.

This is the demo where arbitrary utilities stop being the answer. Written inline, one bevel is a 300-character token, and it appears on buttons, system buttons, panels, wells and the window frame. Tailwind v4 has a first-class answer — @utility, which registers a real utility that variants can modify:

@utility twr04-raised {
  box-shadow:
    inset var(--twr-04-b) var(--twr-04-b) 0 0 var(--color-twr04-hilite),
    inset calc(var(--twr-04-b)*-1) calc(var(--twr-04-b)*-1) 0 0 var(--color-twr04-dark),
    inset calc(var(--twr-04-b)*2) calc(var(--twr-04-b)*2) 0 0 var(--color-twr04-light),
    inset calc(var(--twr-04-b)*-2) calc(var(--twr-04-b)*-2) 0 0 var(--color-twr04-shadow);
}

Pressed is the same list, mirrored — and that is now a variant, not a modifier class. The CSS version needs .rt-04__btn:active plus a --pressed class for the statically-pressed specimen. Here it is active:twr04-sunken on the button and plain twr04-sunken on the specimen: one utility, two ways in. Sunken wells use the same utility with the tone pairs reordered for white-on-grey, no caption offset — the difference between “pressed right now” and “recessed by design”.

Why not @apply? In v4 @apply still exists but is the wrong tool here: it inlines other utilities into a class, so you get a class that cannot take variants. @utility registers in the utility layer, which is why active:, hover: and breakpoints compose with it. The rule of thumb: a repeated value becomes an @theme token; a repeated declaration block becomes an @utility.

Why border-style: outset is not a substitute. Engines derive its two tones from border-color with an unspecified darkening rule, so results differ between browsers, it can only express one tone per side, and it occupies layout space — so raised-to-pressed transitions reflow the content.

Make it yours

  • Set --twr-04-b: 1px on the section for pixel-exact period reproduction, or 3px for a chunky variant that survives a phone screen. Both bevel utilities read it.
  • Recolour the whole system through the five system-metric @theme entries; a Windows 98 &ldquo;Storm&rdquo; or &ldquo;Eggplant&rdquo; scheme is a five-value edit.
  • Add a third @utility twr04-flat with only the outer pair for scrollbar-arrow-scale controls where the inner tones would read as mud.
  • Reverse the light source by swapping the first two layers inside the utility — every control follows, which is the point of naming it.
  • Change --color-twr04-face alone to theme controls while keeping the bevel geometry identical.
  • Push the highlight to #fffdf5 and the shadow to #7d7a6f for an amber-tinted CRT rendering of the same chrome.

Gotchas — read before shipping

  • Do not build these as @apply classes. @apply produces a plain class that variants cannot modify, so you lose active: — use @utility, which registers in the utility layer.
  • Reordering the four shadows silently destroys the effect: the wider inset paints over the narrower one and the two-tone edge disappears. Keep the outer pair first inside the utility.
  • border-style: outset renders inconsistently across engines, cannot express the inner tone pair, and takes up layout space.
  • The authentic 16px close box fails SC 2.5.8. Keep the bevel and scale the hit area to size-11 — the visual is unaffected because the bevel is unit-driven.
  • The era's 1px dotted focus rectangle in black on a #c0c0c0 face is about 2.6:1. Keep the dotted style, thicken to 2px, and use a negative outline-offset so it lands inside the bevel.
  • The Windows 95 palette must stay exact sRGB hex. Converting #c0c0c0 to oklch and back drifts it, and the whole look depends on those five values being right.

Browser support

ChromeSafariFirefoxEdge
111+16.4+128+111+

Multi-layer inset box-shadow has been Baseline since 2011 and is the entire mechanism, so the bevels themselves render essentially everywhere. The floor is Tailwind v4's generated sheet (Chrome 111+, Safari 16.4+, Firefox 128+) and the @utility directive, which is a v4 build-time feature and costs nothing at runtime. The Windows 95 palette is exact sRGB hex and is never colour-converted.

Techniques used in this demo

Utilitiesfirst-class utility or variant

HTML & JSno Tailwind involved

Search CodeFronts

Loading…