Pure TailwindMIT licensed

Floating Tailwind Blockquote with Drop Shadow

A floating quote card on a five-layer, hue-tinted shadow ramp, with an elevation ruler showing e1–e3. The port promotes every shadow to a --shadow-tbq17-* theme token, so shadow-tbq17-rest and shadow-tbq17-e3 are real utilities, and keeps the performant hover: the heavier shadow lives on an after: layer whose opacity animates.

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="tbq-17 w-full min-h-svh grid place-items-center bg-linear-160 from-tbq17-top to-tbq17-bg px-5 py-16 font-tbq17-sans text-tbq17-ink" aria-label="Floating blockquote with layered drop shadow demo">
  <div class="grid w-full justify-items-center gap-9">
    <div class="flex flex-wrap items-center justify-center gap-[clamp(28px,4vw,52px)]">
      <figure class="group relative w-[min(100%,440px)] rounded-[20px] bg-tbq17-card px-8 pt-9 pb-6.5 shadow-tbq17-rest transition-[translate] duration-300 ease-[cubic-bezier(0.2,0.7,0.2,1)] after:pointer-events-none after:absolute after:inset-0 after:rounded-[inherit] after:opacity-0 after:shadow-tbq17-lift after:transition-opacity after:duration-300 hover:-translate-y-1.5 hover:after:opacity-100 motion-reduce:transition-none">
        <span aria-hidden="true" class="absolute -top-6 left-6 grid size-12 place-items-center rounded-[14px] bg-tbq17-acc pt-4 font-tbq17-serif text-[40px] leading-none text-white shadow-tbq17-tile transition-transform duration-300 group-hover:-rotate-6 motion-reduce:transition-none">“</span>
        <blockquote>
          <p class="mt-2 text-[16.5px] leading-[1.66] text-pretty">Depth is information. A shadow tells the eye what is interactive, what is modal, and what is furniture — before a single word is read.</p>
        </blockquote>
        <figcaption class="mt-4 text-[12.5px] text-tbq17-mut"><strong class="font-semibold text-tbq17-ink">Field Guide to Interface Light</strong> · ch. 3, Elevation</figcaption>
      </figure>
      <div aria-hidden="true" class="flex flex-col gap-4.5">
        <div class="grid h-13 w-40 place-items-center rounded-xl bg-tbq17-card font-tbq17-mono text-[10.5px] text-tbq17-mut shadow-tbq17-e1">e1 · resting</div>
        <div class="grid h-13 w-40 place-items-center rounded-xl bg-tbq17-card font-tbq17-mono text-[10.5px] text-tbq17-mut shadow-tbq17-e2">e2 · raised</div>
        <div class="grid h-13 w-40 place-items-center rounded-xl bg-tbq17-card font-tbq17-mono text-[10.5px] text-tbq17-mut shadow-tbq17-e3">e3 · floating</div>
      </div>
    </div>
    <p aria-hidden="true" class="rounded-full border border-black/9 bg-white px-3.5 py-2 font-tbq17-mono text-[11.5px] text-tbq17-mut">--shadow-tbq17-* tokens · after: opacity cross-fade · hue-tinted</p>
  </div>
</section>
@import "tailwindcss";

@theme {
  --color-tbq17-bg: #edf0f6;
  --color-tbq17-bg: oklch(0.955 0.008 255);
  --color-tbq17-top: #f2f5f9;
  --color-tbq17-top: oklch(0.97 0.006 250);
  --color-tbq17-card: #ffffff;
  --color-tbq17-card: oklch(1 0 0);
  --color-tbq17-ink: #1e242e;
  --color-tbq17-ink: oklch(0.26 0.02 260);
  --color-tbq17-mut: #5a616c;
  --color-tbq17-mut: oklch(0.49 0.02 260);
  --color-tbq17-acc: #3a61c4;
  --color-tbq17-acc: oklch(0.52 0.16 265);
  --font-tbq17-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
  --font-tbq17-serif: 'Newsreader', Georgia, serif;
  --font-tbq17-mono: 'JetBrains Mono', ui-monospace, monospace;
  --shadow-tbq17-rest: 0 1px 1px oklch(0.2 0.02 260 / 0.05), 0 2px 2px oklch(0.2 0.02 260 / 0.05), 0 4px 4px oklch(0.2 0.02 260 / 0.06), 0 8px 8px oklch(0.2 0.02 260 / 0.06), 0 16px 24px oklch(0.2 0.02 260 / 0.08);
  --shadow-tbq17-lift: 0 2px 2px oklch(0.2 0.02 260 / 0.06), 0 4px 4px oklch(0.2 0.02 260 / 0.06), 0 8px 8px oklch(0.2 0.02 260 / 0.07), 0 16px 16px oklch(0.2 0.02 260 / 0.07), 0 32px 44px oklch(0.2 0.02 260 / 0.12);
  --shadow-tbq17-e1: 0 1px 1px oklch(0.2 0.02 260 / 0.06), 0 2px 3px oklch(0.2 0.02 260 / 0.07);
  --shadow-tbq17-e2: 0 1px 1px oklch(0.2 0.02 260 / 0.05), 0 3px 4px oklch(0.2 0.02 260 / 0.06), 0 8px 12px oklch(0.2 0.02 260 / 0.08);
  --shadow-tbq17-e3: 0 1px 1px oklch(0.2 0.02 260 / 0.05), 0 4px 4px oklch(0.2 0.02 260 / 0.06), 0 8px 10px oklch(0.2 0.02 260 / 0.07), 0 20px 32px oklch(0.2 0.02 260 / 0.12);
  --shadow-tbq17-tile: 0 2px 3px oklch(0.2 0.02 260 / 0.15), 0 8px 16px oklch(0.2 0.02 260 / 0.2);
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities, so the
   stage is sized before the browser build compiles. */

.tbq-17 {
  width: 100%;
  min-height: 100svh;
}

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-tbq17-bg: #edf0f6;
  --color-tbq17-bg: oklch(0.955 0.008 255);
  --color-tbq17-top: #f2f5f9;
  --color-tbq17-top: oklch(0.97 0.006 250);
  --color-tbq17-card: #ffffff;
  --color-tbq17-card: oklch(1 0 0);
  --color-tbq17-ink: #1e242e;
  --color-tbq17-ink: oklch(0.26 0.02 260);
  --color-tbq17-mut: #5a616c;
  --color-tbq17-mut: oklch(0.49 0.02 260);
  --color-tbq17-acc: #3a61c4;
  --color-tbq17-acc: oklch(0.52 0.16 265);
  --font-tbq17-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
  --font-tbq17-serif: 'Newsreader', Georgia, serif;
  --font-tbq17-mono: 'JetBrains Mono', ui-monospace, monospace;
  --shadow-tbq17-rest: 0 1px 1px oklch(0.2 0.02 260 / 0.05), 0 2px 2px oklch(0.2 0.02 260 / 0.05), 0 4px 4px oklch(0.2 0.02 260 / 0.06), 0 8px 8px oklch(0.2 0.02 260 / 0.06), 0 16px 24px oklch(0.2 0.02 260 / 0.08);
  --shadow-tbq17-lift: 0 2px 2px oklch(0.2 0.02 260 / 0.06), 0 4px 4px oklch(0.2 0.02 260 / 0.06), 0 8px 8px oklch(0.2 0.02 260 / 0.07), 0 16px 16px oklch(0.2 0.02 260 / 0.07), 0 32px 44px oklch(0.2 0.02 260 / 0.12);
  --shadow-tbq17-e1: 0 1px 1px oklch(0.2 0.02 260 / 0.06), 0 2px 3px oklch(0.2 0.02 260 / 0.07);
  --shadow-tbq17-e2: 0 1px 1px oklch(0.2 0.02 260 / 0.05), 0 3px 4px oklch(0.2 0.02 260 / 0.06), 0 8px 12px oklch(0.2 0.02 260 / 0.08);
  --shadow-tbq17-e3: 0 1px 1px oklch(0.2 0.02 260 / 0.05), 0 4px 4px oklch(0.2 0.02 260 / 0.06), 0 8px 10px oklch(0.2 0.02 260 / 0.07), 0 20px 32px oklch(0.2 0.02 260 / 0.12);
  --shadow-tbq17-tile: 0 2px 3px oklch(0.2 0.02 260 / 0.15), 0 8px 16px oklch(0.2 0.02 260 / 0.2);
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities, so the
   stage is sized before the browser build compiles. */

.tbq-17 {
  width: 100%;
  min-height: 100svh;
}
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;800&family=Newsreader:ital,opsz,wght@0,6..72,400..700;1,6..72,400..700&family=JetBrains+Mono:wght@400;500;600;700&display=swap">

What changed in the port

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

  • Six hand-written shadow stacks became six --shadow-tbq17-* theme tokens, so the elevation scale is reusable as shadow-tbq17-e1…e3 anywhere on the page.
  • The original's --sh:0.2 0.02 260 channel trick (oklch(var(--sh)/.05)) doesn't survive token compilation cleanly, so the tokens spell out each colour.
  • UI upgrade from the CSS original: removed the non-functional tabindex="0" from the card; the hover lift stays as decoration.
  • UI upgrade: the quote tile tilts on hover (group-hover:-rotate-6), the glyph is Newsreader instead of Georgia, and caption/ruler copy darkened from 0.53 to 0.49.
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: Floating Tailwind Blockquote with Drop Shadow
Source: https://codefronts.com/snippets/tailwind-css-blockquotes/floating-tailwind-blockquote-drop-shadow/

A floating quote card on a five-layer, hue-tinted shadow ramp, with an elevation ruler showing e1–e3. The port promotes every shadow to a --shadow-tbq17-* theme token, so shadow-tbq17-rest and shadow-tbq17-e3 are real utilities, and keeps the performant hover: the heavier shadow lives on an after: layer whose opacity animates.
## HTML
```html
<section class="tbq-17 w-full min-h-svh grid place-items-center bg-linear-160 from-tbq17-top to-tbq17-bg px-5 py-16 font-tbq17-sans text-tbq17-ink" aria-label="Floating blockquote with layered drop shadow demo">
  <div class="grid w-full justify-items-center gap-9">
    <div class="flex flex-wrap items-center justify-center gap-[clamp(28px,4vw,52px)]">
      <figure class="group relative w-[min(100%,440px)] rounded-[20px] bg-tbq17-card px-8 pt-9 pb-6.5 shadow-tbq17-rest transition-[translate] duration-300 ease-[cubic-bezier(0.2,0.7,0.2,1)] after:pointer-events-none after:absolute after:inset-0 after:rounded-[inherit] after:opacity-0 after:shadow-tbq17-lift after:transition-opacity after:duration-300 hover:-translate-y-1.5 hover:after:opacity-100 motion-reduce:transition-none">
        <span aria-hidden="true" class="absolute -top-6 left-6 grid size-12 place-items-center rounded-[14px] bg-tbq17-acc pt-4 font-tbq17-serif text-[40px] leading-none text-white shadow-tbq17-tile transition-transform duration-300 group-hover:-rotate-6 motion-reduce:transition-none">“</span>
        <blockquote>
          <p class="mt-2 text-[16.5px] leading-[1.66] text-pretty">Depth is information. A shadow tells the eye what is interactive, what is modal, and what is furniture — before a single word is read.</p>
        </blockquote>
        <figcaption class="mt-4 text-[12.5px] text-tbq17-mut"><strong class="font-semibold text-tbq17-ink">Field Guide to Interface Light</strong> · ch. 3, Elevation</figcaption>
      </figure>
      <div aria-hidden="true" class="flex flex-col gap-4.5">
        <div class="grid h-13 w-40 place-items-center rounded-xl bg-tbq17-card font-tbq17-mono text-[10.5px] text-tbq17-mut shadow-tbq17-e1">e1 · resting</div>
        <div class="grid h-13 w-40 place-items-center rounded-xl bg-tbq17-card font-tbq17-mono text-[10.5px] text-tbq17-mut shadow-tbq17-e2">e2 · raised</div>
        <div class="grid h-13 w-40 place-items-center rounded-xl bg-tbq17-card font-tbq17-mono text-[10.5px] text-tbq17-mut shadow-tbq17-e3">e3 · floating</div>
      </div>
    </div>
    <p aria-hidden="true" class="rounded-full border border-black/9 bg-white px-3.5 py-2 font-tbq17-mono text-[11.5px] text-tbq17-mut">--shadow-tbq17-* tokens · after: opacity cross-fade · hue-tinted</p>
  </div>
</section>
```
## CSS
```css
@import "tailwindcss";

@theme {
  --color-tbq17-bg: #edf0f6;
  --color-tbq17-bg: oklch(0.955 0.008 255);
  --color-tbq17-top: #f2f5f9;
  --color-tbq17-top: oklch(0.97 0.006 250);
  --color-tbq17-card: #ffffff;
  --color-tbq17-card: oklch(1 0 0);
  --color-tbq17-ink: #1e242e;
  --color-tbq17-ink: oklch(0.26 0.02 260);
  --color-tbq17-mut: #5a616c;
  --color-tbq17-mut: oklch(0.49 0.02 260);
  --color-tbq17-acc: #3a61c4;
  --color-tbq17-acc: oklch(0.52 0.16 265);
  --font-tbq17-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
  --font-tbq17-serif: 'Newsreader', Georgia, serif;
  --font-tbq17-mono: 'JetBrains Mono', ui-monospace, monospace;
  --shadow-tbq17-rest: 0 1px 1px oklch(0.2 0.02 260 / 0.05), 0 2px 2px oklch(0.2 0.02 260 / 0.05), 0 4px 4px oklch(0.2 0.02 260 / 0.06), 0 8px 8px oklch(0.2 0.02 260 / 0.06), 0 16px 24px oklch(0.2 0.02 260 / 0.08);
  --shadow-tbq17-lift: 0 2px 2px oklch(0.2 0.02 260 / 0.06), 0 4px 4px oklch(0.2 0.02 260 / 0.06), 0 8px 8px oklch(0.2 0.02 260 / 0.07), 0 16px 16px oklch(0.2 0.02 260 / 0.07), 0 32px 44px oklch(0.2 0.02 260 / 0.12);
  --shadow-tbq17-e1: 0 1px 1px oklch(0.2 0.02 260 / 0.06), 0 2px 3px oklch(0.2 0.02 260 / 0.07);
  --shadow-tbq17-e2: 0 1px 1px oklch(0.2 0.02 260 / 0.05), 0 3px 4px oklch(0.2 0.02 260 / 0.06), 0 8px 12px oklch(0.2 0.02 260 / 0.08);
  --shadow-tbq17-e3: 0 1px 1px oklch(0.2 0.02 260 / 0.05), 0 4px 4px oklch(0.2 0.02 260 / 0.06), 0 8px 10px oklch(0.2 0.02 260 / 0.07), 0 20px 32px oklch(0.2 0.02 260 / 0.12);
  --shadow-tbq17-tile: 0 2px 3px oklch(0.2 0.02 260 / 0.15), 0 8px 16px oklch(0.2 0.02 260 / 0.2);
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities, so the
   stage is sized before the browser build compiles. */

.tbq-17 {
  width: 100%;
  min-height: 100svh;
}
```

How this works

Shadows are a design scale — so tokenise them. In v4, any --shadow-* entry in @theme becomes a utility:

@theme {
  --shadow-tbq17-rest: 0 1px 1px oklch(0.2 0.02 260 / 0.05), … 0 16px 24px …;
}
<figure class="shadow-tbq17-rest after:shadow-tbq17-lift after:opacity-0
  hover:after:opacity-100 hover:-translate-y-1.5">

Why the after: layer. Transitioning a five-layer box-shadow repaints a large blurred area every frame. Cross-fading a pre-rendered shadow on a pseudo-element only changes opacity, which the compositor handles.

Each layer doubles offset and blur (1, 2, 4, 8, 16px) at low alpha, and the shadow colour carries the page's blue hue instead of pure black, so the card looks lit rather than dirty.

Make it yours

  • Warmer light: change the shadow hue from 260 to 60 in the tokens.
  • Use the scale elsewhere: shadow-tbq17-e2 on any element.
  • Stronger float: raise hover:-translate-y-1.5 to -translate-y-3.

Gotchas — read before shipping

  • The after: layer needs pointer-events-none and rounded-[inherit] or it blocks clicks and shows square corners.
  • Tokens must be complete shadow values — --shadow-* can't reference the /opacity modifier.
  • Don't put tabindex="0" on a card just to make hover keyboard-reachable; if it isn't interactive it doesn't need focus.

Browser support

ChromeSafariFirefoxEdge
111+16.4+128+111+

Everything here is universal CSS; the floor is Tailwind v4's generated sheet.

Techniques used in this demo

Utilitiesfirst-class utility or variant

Search CodeFronts

Loading…