Pure TailwindMIT licensed

Tailwind Drawn Border Input

Four background layers, one per edge, animating from zero to full length on a staggered delay chain — the stroke draws around the field on focus. No keyframes, no SVG, no @property: only background-size moves.

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

<div class="tif-06 grid min-h-svh w-full place-items-center bg-tif06-bg px-6 py-14 font-tif06-sans" aria-label="Drawn border input demo">
  <label class="grid w-full max-w-70 gap-1.5">
    <span class="text-[11px] tracking-[0.08em] text-tif06-mut uppercase">Project name</span>
    <input type="text" name="tif06-project" placeholder="My next big idea…" required
      class="w-full rounded-lg border border-tif06-edge bg-tif06-field bg-[linear-gradient(90deg,var(--color-tif06-acc),var(--color-tif06-acc)),linear-gradient(0deg,var(--color-tif06-acc),var(--color-tif06-acc)),linear-gradient(90deg,var(--color-tif06-acc),var(--color-tif06-acc)),linear-gradient(0deg,var(--color-tif06-acc),var(--color-tif06-acc))] bg-no-repeat px-3.5 py-2.5 text-sm text-tif06-ink outline-none transition-[background-size,border-color] duration-350 ease-linear [background-position:0_0,100%_0,100%_100%,0_100%] [background-size:0_2px,2px_0,0_2px,2px_0] placeholder:text-tif06-mut focus:border-transparent focus:[background-size:100%_2px,2px_100%,100%_2px,2px_100%] focus:[transition-delay:0s,0.35s,0.7s,1.05s] motion-reduce:focus:[transition-delay:0s]">
  </label>
</div>
@import "tailwindcss";

@theme {
  --color-tif06-bg: #12121a;
  --color-tif06-bg: oklch(0.19 0.015 285);
  --color-tif06-field: #1a1a22;
  --color-tif06-field: oklch(0.23 0.015 285);
  --color-tif06-edge: #2a2a36;
  --color-tif06-edge: oklch(0.31 0.017 285);
  --color-tif06-ink: #f0eeff;
  --color-tif06-ink: oklch(0.95 0.02 290);
  --color-tif06-mut: #b8b6d4;
  --color-tif06-mut: oklch(0.77 0.03 290);
  --color-tif06-acc: #fbbf24;
  --color-tif06-acc: oklch(0.84 0.16 85);
  --font-tif06-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}

.tif-06 {
  width: 100%;
}

.tif-06 ::selection {
  background: var(--color-tif06-acc);
  color: #12121a;
}

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-tif06-bg: #12121a;
  --color-tif06-bg: oklch(0.19 0.015 285);
  --color-tif06-field: #1a1a22;
  --color-tif06-field: oklch(0.23 0.015 285);
  --color-tif06-edge: #2a2a36;
  --color-tif06-edge: oklch(0.31 0.017 285);
  --color-tif06-ink: #f0eeff;
  --color-tif06-ink: oklch(0.95 0.02 290);
  --color-tif06-mut: #b8b6d4;
  --color-tif06-mut: oklch(0.77 0.03 290);
  --color-tif06-acc: #fbbf24;
  --color-tif06-acc: oklch(0.84 0.16 85);
  --font-tif06-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}

.tif-06 {
  width: 100%;
}

.tif-06 ::selection {
  background: var(--color-tif06-acc);
  color: #12121a;
}
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=Plus+Jakarta+Sans:wght@400;500;600;700&display=swap">

What changed in the port

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

  • The four gradients now read var(--color-tif06-acc) instead of a hard-coded hex repeated eight times — one token edit retints the whole sweep.
  • transition-delay as a focus-state arbitrary property puts the stagger on the element, which is the only way to see at a glance that it matches the duration.
  • The original had no reduced-motion path; motion-reduce:focus:[transition-delay:0s] keeps the stroke but drops the parade.
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 Drawn Border Input
Source: https://codefronts.com/components/tailwind-css-input-fields/tailwind-drawn-border-input/

Four background layers, one per edge, animating from zero to full length on a staggered delay chain — the stroke draws around the field on focus. No keyframes, no SVG, no @property: only background-size moves.
## HTML
```html
<div class="tif-06 grid min-h-svh w-full place-items-center bg-tif06-bg px-6 py-14 font-tif06-sans" aria-label="Drawn border input demo">
  <label class="grid w-full max-w-70 gap-1.5">
    <span class="text-[11px] tracking-[0.08em] text-tif06-mut uppercase">Project name</span>
    <input type="text" name="tif06-project" placeholder="My next big idea…" required
      class="w-full rounded-lg border border-tif06-edge bg-tif06-field bg-[linear-gradient(90deg,var(--color-tif06-acc),var(--color-tif06-acc)),linear-gradient(0deg,var(--color-tif06-acc),var(--color-tif06-acc)),linear-gradient(90deg,var(--color-tif06-acc),var(--color-tif06-acc)),linear-gradient(0deg,var(--color-tif06-acc),var(--color-tif06-acc))] bg-no-repeat px-3.5 py-2.5 text-sm text-tif06-ink outline-none transition-[background-size,border-color] duration-350 ease-linear [background-position:0_0,100%_0,100%_100%,0_100%] [background-size:0_2px,2px_0,0_2px,2px_0] placeholder:text-tif06-mut focus:border-transparent focus:[background-size:100%_2px,2px_100%,100%_2px,2px_100%] focus:[transition-delay:0s,0.35s,0.7s,1.05s] motion-reduce:focus:[transition-delay:0s]">
  </label>
</div>
```
## CSS
```css
@import "tailwindcss";

@theme {
  --color-tif06-bg: #12121a;
  --color-tif06-bg: oklch(0.19 0.015 285);
  --color-tif06-field: #1a1a22;
  --color-tif06-field: oklch(0.23 0.015 285);
  --color-tif06-edge: #2a2a36;
  --color-tif06-edge: oklch(0.31 0.017 285);
  --color-tif06-ink: #f0eeff;
  --color-tif06-ink: oklch(0.95 0.02 290);
  --color-tif06-mut: #b8b6d4;
  --color-tif06-mut: oklch(0.77 0.03 290);
  --color-tif06-acc: #fbbf24;
  --color-tif06-acc: oklch(0.84 0.16 85);
  --font-tif06-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}

.tif-06 {
  width: 100%;
}

.tif-06 ::selection {
  background: var(--color-tif06-acc);
  color: #12121a;
}
```

How this works

The sweep is four sizes and four delays. Each edge is a layer sized 0 2px or 2px 0 and pinned to a corner; focus grows each to full and offsets it by one duration:

class="focus:[background-size:100%_2px,2px_100%,100%_2px,2px_100%]
  focus:[transition-delay:0s,0.35s,0.7s,1.05s]"

Arbitrary properties are the right answer. A four-value background-size list is not a scale value, and Tailwind rightly has no utility for it. What the port buys is adjacency: the resting sizes, the focused sizes and the delay chain are three classes apart instead of three rule blocks apart, so it is obvious when they stop matching.

Make it yours

  • Colour: the four linear-gradient stops. A two-stop gradient per edge gives a subtle shift as the stroke travels.
  • Speed: scale duration-350 and the four delays proportionally — they are one mechanism.
  • Weight: the 2px track in both background-size lists.
  • Rest state: rounded-lg and border-tif06-edge carry the whole unfocused look.

Gotchas — read before shipping

  • The delays must equal the duration. Change one and the corners either overlap or leave gaps.
  • Radii above about 10px let the flat stroke cut the corner; keep rounded-lg or clip with a wrapper.
  • Background layers paint over the border, so a coloured focus border-color still shows at the corners — hence focus:border-transparent.

Browser support

ChromeSafariFirefoxEdge
111+16.4+128+111+

Only background-size is animated, so no @property is needed; the floor is Tailwind v4's sheet.

Techniques used in this demo

Utilitiesfirst-class utility or variant

Theme tokensset in @theme, used by a utility

Search CodeFronts

Loading…