21 / 24
All 24 in 24 Tailwind CSS Radio Buttons
- 01Tailwind Radio Button Cards (Selectable Cards)
- 02Tailwind Pill Radio Toggle (Segmented Control)
- 03Tailwind Radio Button with Icon and Description
- 04Tailwind Dark Mode Glowing Radio Button
- 05Accessible Tailwind Radio Button (appearance-none)
- 06Tailwind Radio Group with Badges
- 07Tailwind Animated Radio Button (Concentric Ripple)
- 08Tailwind Sliding Pill Radio Switch
- 09Tailwind 3D Sphere Radio Buttons
- 10Tailwind Ink Splash Radio Animation
- 11Tailwind Star Rating Radio Buttons
- 12Tailwind 3D Tilt Card Radio Selector
- 13Minimal Checkmark Radio Button in Tailwind
- 14Tailwind Color Swatch Radio Picker
- 15Tailwind Segmented Control Bar (View Switcher)
- 16Tailwind Neon Cyberpunk Radio Buttons
- 17Tailwind Pricing Plan Radio Cards
- 18Tailwind Liquid Wave Fill Radio Button
- 19Tailwind Image Radio Button Selector (Arch Mask)
- 20Tailwind Animated Gradient Border Radio Cards
- 21Tailwind Avatar Radio Picker (Profile Selector)
- 22Tailwind Stacked Radio List (Payment Method)
- 23Tailwind 3D Push Button Radio (Tactile Keys)
- 24Tailwind Pulsing Glow Radio Button (Status Picker)
Tailwind Avatar Radio Picker (Profile Selector)
The "who's watching?" screen as a proper form control: profile photos where the active one scales up, gains a bright ring and full colour while the rest rest slightly dimmed. The double ring is ring-3 ring-trb21-acc ring-offset-4 ring-offset-trb21-bg; the sprung lift is motion-safe:. An "Add profile" tile shows how to mix an action into the row without joining the radio group.
Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time
Untitled UI React · Affiliate link
The code
<section class="trb-21 w-full min-h-svh grid place-items-center bg-trb21-bg px-6 py-14 font-trb21-sans text-trb21-ink" aria-label="User profile avatar selector demo">
<fieldset>
<legend class="text-center text-[30px] font-extrabold tracking-[-0.025em]">Who's watching?</legend>
<div class="mt-9 flex flex-wrap justify-center gap-8">
<label class="group relative grid cursor-pointer justify-items-center gap-3"><input type="radio" name="trb-21" value="amara" class="sr-only" checked><img class="size-[92px] rounded-full object-cover brightness-80 saturate-70 ring-trb21-acc ring-offset-trb21-bg transition-[scale,filter,box-shadow] duration-350 ease-trb21-spring group-hover:brightness-100 group-hover:saturate-100 group-has-checked:shadow-trb21-lift group-has-checked:ring-3 group-has-checked:ring-offset-4 group-has-checked:brightness-100 group-has-checked:saturate-100 group-has-focus-visible:outline-3 group-has-focus-visible:outline-offset-[10px] group-has-focus-visible:outline-white motion-safe:group-has-checked:scale-112" src="https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=300&q=80&auto=format&fit=crop" alt="Amara" loading="lazy"><span class="text-[15px] font-semibold text-trb21-mut transition-colors group-has-checked:text-white">Amara</span></label>
<label class="group relative grid cursor-pointer justify-items-center gap-3"><input type="radio" name="trb-21" value="jonas" class="sr-only"><img class="size-[92px] rounded-full object-cover brightness-80 saturate-70 ring-trb21-acc ring-offset-trb21-bg transition-[scale,filter,box-shadow] duration-350 ease-trb21-spring group-hover:brightness-100 group-hover:saturate-100 group-has-checked:shadow-trb21-lift group-has-checked:ring-3 group-has-checked:ring-offset-4 group-has-checked:brightness-100 group-has-checked:saturate-100 group-has-focus-visible:outline-3 group-has-focus-visible:outline-offset-[10px] group-has-focus-visible:outline-white motion-safe:group-has-checked:scale-112" src="https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=300&q=80&auto=format&fit=crop" alt="Jonas" loading="lazy"><span class="text-[15px] font-semibold text-trb21-mut transition-colors group-has-checked:text-white">Jonas</span></label>
<label class="group relative grid cursor-pointer justify-items-center gap-3"><input type="radio" name="trb-21" value="sofia" class="sr-only"><img class="size-[92px] rounded-full object-cover brightness-80 saturate-70 ring-trb21-acc ring-offset-trb21-bg transition-[scale,filter,box-shadow] duration-350 ease-trb21-spring group-hover:brightness-100 group-hover:saturate-100 group-has-checked:shadow-trb21-lift group-has-checked:ring-3 group-has-checked:ring-offset-4 group-has-checked:brightness-100 group-has-checked:saturate-100 group-has-focus-visible:outline-3 group-has-focus-visible:outline-offset-[10px] group-has-focus-visible:outline-white motion-safe:group-has-checked:scale-112" src="https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=300&q=80&auto=format&fit=crop" alt="Sofia" loading="lazy"><span class="text-[15px] font-semibold text-trb21-mut transition-colors group-has-checked:text-white">Sofia</span></label>
<label class="group relative grid cursor-pointer justify-items-center gap-3"><input type="radio" name="trb-21" value="mateo" class="sr-only"><img class="size-[92px] rounded-full object-cover brightness-80 saturate-70 ring-trb21-acc ring-offset-trb21-bg transition-[scale,filter,box-shadow] duration-350 ease-trb21-spring group-hover:brightness-100 group-hover:saturate-100 group-has-checked:shadow-trb21-lift group-has-checked:ring-3 group-has-checked:ring-offset-4 group-has-checked:brightness-100 group-has-checked:saturate-100 group-has-focus-visible:outline-3 group-has-focus-visible:outline-offset-[10px] group-has-focus-visible:outline-white motion-safe:group-has-checked:scale-112" src="https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=300&q=80&auto=format&fit=crop" alt="Mateo" loading="lazy"><span class="text-[15px] font-semibold text-trb21-mut transition-colors group-has-checked:text-white">Mateo</span></label>
<div class="grid justify-items-center gap-3"><button type="button" class="grid size-[92px] cursor-pointer place-items-center rounded-full border-2 border-dashed border-white/25 text-trb21-mut transition-colors hover:border-white/60 hover:text-white focus-visible:outline-3 focus-visible:outline-offset-4 focus-visible:outline-white" aria-label="Add profile"><svg class="size-7" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M12 5v14M5 12h14"/></svg></button><span aria-hidden="true" class="text-[15px] font-semibold text-trb21-mut">Add</span></div>
</div>
</fieldset>
</section><section class="trb-21 w-full min-h-svh grid place-items-center bg-trb21-bg px-6 py-14 font-trb21-sans text-trb21-ink" aria-label="User profile avatar selector demo">
<fieldset>
<legend class="text-center text-[30px] font-extrabold tracking-[-0.025em]">Who's watching?</legend>
<div class="mt-9 flex flex-wrap justify-center gap-8">
<label class="group relative grid cursor-pointer justify-items-center gap-3"><input type="radio" name="trb-21" value="amara" class="sr-only" checked><img class="size-[92px] rounded-full object-cover brightness-80 saturate-70 ring-trb21-acc ring-offset-trb21-bg transition-[scale,filter,box-shadow] duration-350 ease-trb21-spring group-hover:brightness-100 group-hover:saturate-100 group-has-checked:shadow-trb21-lift group-has-checked:ring-3 group-has-checked:ring-offset-4 group-has-checked:brightness-100 group-has-checked:saturate-100 group-has-focus-visible:outline-3 group-has-focus-visible:outline-offset-[10px] group-has-focus-visible:outline-white motion-safe:group-has-checked:scale-112" src="https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=300&q=80&auto=format&fit=crop" alt="Amara" loading="lazy"><span class="text-[15px] font-semibold text-trb21-mut transition-colors group-has-checked:text-white">Amara</span></label>
<label class="group relative grid cursor-pointer justify-items-center gap-3"><input type="radio" name="trb-21" value="jonas" class="sr-only"><img class="size-[92px] rounded-full object-cover brightness-80 saturate-70 ring-trb21-acc ring-offset-trb21-bg transition-[scale,filter,box-shadow] duration-350 ease-trb21-spring group-hover:brightness-100 group-hover:saturate-100 group-has-checked:shadow-trb21-lift group-has-checked:ring-3 group-has-checked:ring-offset-4 group-has-checked:brightness-100 group-has-checked:saturate-100 group-has-focus-visible:outline-3 group-has-focus-visible:outline-offset-[10px] group-has-focus-visible:outline-white motion-safe:group-has-checked:scale-112" src="https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=300&q=80&auto=format&fit=crop" alt="Jonas" loading="lazy"><span class="text-[15px] font-semibold text-trb21-mut transition-colors group-has-checked:text-white">Jonas</span></label>
<label class="group relative grid cursor-pointer justify-items-center gap-3"><input type="radio" name="trb-21" value="sofia" class="sr-only"><img class="size-[92px] rounded-full object-cover brightness-80 saturate-70 ring-trb21-acc ring-offset-trb21-bg transition-[scale,filter,box-shadow] duration-350 ease-trb21-spring group-hover:brightness-100 group-hover:saturate-100 group-has-checked:shadow-trb21-lift group-has-checked:ring-3 group-has-checked:ring-offset-4 group-has-checked:brightness-100 group-has-checked:saturate-100 group-has-focus-visible:outline-3 group-has-focus-visible:outline-offset-[10px] group-has-focus-visible:outline-white motion-safe:group-has-checked:scale-112" src="https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=300&q=80&auto=format&fit=crop" alt="Sofia" loading="lazy"><span class="text-[15px] font-semibold text-trb21-mut transition-colors group-has-checked:text-white">Sofia</span></label>
<label class="group relative grid cursor-pointer justify-items-center gap-3"><input type="radio" name="trb-21" value="mateo" class="sr-only"><img class="size-[92px] rounded-full object-cover brightness-80 saturate-70 ring-trb21-acc ring-offset-trb21-bg transition-[scale,filter,box-shadow] duration-350 ease-trb21-spring group-hover:brightness-100 group-hover:saturate-100 group-has-checked:shadow-trb21-lift group-has-checked:ring-3 group-has-checked:ring-offset-4 group-has-checked:brightness-100 group-has-checked:saturate-100 group-has-focus-visible:outline-3 group-has-focus-visible:outline-offset-[10px] group-has-focus-visible:outline-white motion-safe:group-has-checked:scale-112" src="https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=300&q=80&auto=format&fit=crop" alt="Mateo" loading="lazy"><span class="text-[15px] font-semibold text-trb21-mut transition-colors group-has-checked:text-white">Mateo</span></label>
<div class="grid justify-items-center gap-3"><button type="button" class="grid size-[92px] cursor-pointer place-items-center rounded-full border-2 border-dashed border-white/25 text-trb21-mut transition-colors hover:border-white/60 hover:text-white focus-visible:outline-3 focus-visible:outline-offset-4 focus-visible:outline-white" aria-label="Add profile"><svg class="size-7" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M12 5v14M5 12h14"/></svg></button><span aria-hidden="true" class="text-[15px] font-semibold text-trb21-mut">Add</span></div>
</div>
</fieldset>
</section>@import "tailwindcss";
@theme {
--color-trb21-bg: #101014;
--color-trb21-bg: oklch(0.18 0.006 285);
--color-trb21-ink: #f2f2f5;
--color-trb21-ink: oklch(0.96 0.004 285);
--color-trb21-mut: #9c9ca8;
--color-trb21-mut: oklch(0.7 0.012 285);
--color-trb21-acc: #f36f5c;
--color-trb21-acc: oklch(0.7 0.16 30);
--shadow-trb21-lift: 0 16px 34px -12px oklch(0 0 0 / 0.8);
--ease-trb21-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
--font-trb21-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}
/* 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. */
.trb-21 {
width: 100%;
min-height: 100svh;
}@import "tailwindcss";
@theme {
--color-trb21-bg: #101014;
--color-trb21-bg: oklch(0.18 0.006 285);
--color-trb21-ink: #f2f2f5;
--color-trb21-ink: oklch(0.96 0.004 285);
--color-trb21-mut: #9c9ca8;
--color-trb21-mut: oklch(0.7 0.012 285);
--color-trb21-acc: #f36f5c;
--color-trb21-acc: oklch(0.7 0.16 30);
--shadow-trb21-lift: 0 16px 34px -12px oklch(0 0 0 / 0.8);
--ease-trb21-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
--font-trb21-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}
/* 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. */
.trb-21 {
width: 100%;
min-height: 100svh;
}Setup — do this once per project
Skip this if your project already runs Tailwind v4.
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
<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.
npm install tailwindcss @tailwindcss/vite
npm install tailwindcss @tailwindcss/vite// vite.config.js ("type": "module" in package.json)
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [tailwindcss()],
})// vite.config.js ("type": "module" in package.json)
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [tailwindcss()],
})Any v4 setup works — Vite, PostCSS or the CLI. Nothing in this demo is bundler-specific.
@import "tailwindcss";
@theme {
--color-trb21-bg: #101014;
--color-trb21-bg: oklch(0.18 0.006 285);
--color-trb21-ink: #f2f2f5;
--color-trb21-ink: oklch(0.96 0.004 285);
--color-trb21-mut: #9c9ca8;
--color-trb21-mut: oklch(0.7 0.012 285);
--color-trb21-acc: #f36f5c;
--color-trb21-acc: oklch(0.7 0.16 30);
--shadow-trb21-lift: 0 16px 34px -12px oklch(0 0 0 / 0.8);
--ease-trb21-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
--font-trb21-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}
/* 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. */
.trb-21 {
width: 100%;
min-height: 100svh;
}@import "tailwindcss";
@theme {
--color-trb21-bg: #101014;
--color-trb21-bg: oklch(0.18 0.006 285);
--color-trb21-ink: #f2f2f5;
--color-trb21-ink: oklch(0.96 0.004 285);
--color-trb21-mut: #9c9ca8;
--color-trb21-mut: oklch(0.7 0.012 285);
--color-trb21-acc: #f36f5c;
--color-trb21-acc: oklch(0.7 0.16 30);
--shadow-trb21-lift: 0 16px 34px -12px oklch(0 0 0 / 0.8);
--ease-trb21-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
--font-trb21-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}
/* 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. */
.trb-21 {
width: 100%;
min-height: 100svh;
}<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..800&display=swap">
<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..800&display=swap">What changed in the port
Which parts became utilities, which stayed CSS, and why.
- The double
box-shadowring becamering-3+ring-offset-4; the depth shadow composes alongside it asshadow-trb21-lift. filter:saturate(.7) brightness(.8)became two filter utilities, each undone independently on hover and check.- UI upgrade from the CSS original: the "+ Add" tile the original only described is now built — a real
<button>outside the radio group, with its own focus ring. - UI upgrade: names rose from
#84848f(5.2:1) to 7.3:1, and focus rings clear the accent ring with a 10px offset instead of colliding with it.
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 Avatar Radio Picker (Profile Selector)
Source: https://codefronts.com/components/tailwind-css-radio-buttons/tailwind-avatar-radio-picker-profile-selector/
The "who's watching?" screen as a proper form control: profile photos where the active one scales up, gains a bright ring and full colour while the rest rest slightly dimmed. The double ring is ring-3 ring-trb21-acc ring-offset-4 ring-offset-trb21-bg; the sprung lift is motion-safe:. An "Add profile" tile shows how to mix an action into the row without joining the radio group.
## HTML
```html
<section class="trb-21 w-full min-h-svh grid place-items-center bg-trb21-bg px-6 py-14 font-trb21-sans text-trb21-ink" aria-label="User profile avatar selector demo">
<fieldset>
<legend class="text-center text-[30px] font-extrabold tracking-[-0.025em]">Who's watching?</legend>
<div class="mt-9 flex flex-wrap justify-center gap-8">
<label class="group relative grid cursor-pointer justify-items-center gap-3"><input type="radio" name="trb-21" value="amara" class="sr-only" checked><img class="size-[92px] rounded-full object-cover brightness-80 saturate-70 ring-trb21-acc ring-offset-trb21-bg transition-[scale,filter,box-shadow] duration-350 ease-trb21-spring group-hover:brightness-100 group-hover:saturate-100 group-has-checked:shadow-trb21-lift group-has-checked:ring-3 group-has-checked:ring-offset-4 group-has-checked:brightness-100 group-has-checked:saturate-100 group-has-focus-visible:outline-3 group-has-focus-visible:outline-offset-[10px] group-has-focus-visible:outline-white motion-safe:group-has-checked:scale-112" src="https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=300&q=80&auto=format&fit=crop" alt="Amara" loading="lazy"><span class="text-[15px] font-semibold text-trb21-mut transition-colors group-has-checked:text-white">Amara</span></label>
<label class="group relative grid cursor-pointer justify-items-center gap-3"><input type="radio" name="trb-21" value="jonas" class="sr-only"><img class="size-[92px] rounded-full object-cover brightness-80 saturate-70 ring-trb21-acc ring-offset-trb21-bg transition-[scale,filter,box-shadow] duration-350 ease-trb21-spring group-hover:brightness-100 group-hover:saturate-100 group-has-checked:shadow-trb21-lift group-has-checked:ring-3 group-has-checked:ring-offset-4 group-has-checked:brightness-100 group-has-checked:saturate-100 group-has-focus-visible:outline-3 group-has-focus-visible:outline-offset-[10px] group-has-focus-visible:outline-white motion-safe:group-has-checked:scale-112" src="https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=300&q=80&auto=format&fit=crop" alt="Jonas" loading="lazy"><span class="text-[15px] font-semibold text-trb21-mut transition-colors group-has-checked:text-white">Jonas</span></label>
<label class="group relative grid cursor-pointer justify-items-center gap-3"><input type="radio" name="trb-21" value="sofia" class="sr-only"><img class="size-[92px] rounded-full object-cover brightness-80 saturate-70 ring-trb21-acc ring-offset-trb21-bg transition-[scale,filter,box-shadow] duration-350 ease-trb21-spring group-hover:brightness-100 group-hover:saturate-100 group-has-checked:shadow-trb21-lift group-has-checked:ring-3 group-has-checked:ring-offset-4 group-has-checked:brightness-100 group-has-checked:saturate-100 group-has-focus-visible:outline-3 group-has-focus-visible:outline-offset-[10px] group-has-focus-visible:outline-white motion-safe:group-has-checked:scale-112" src="https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=300&q=80&auto=format&fit=crop" alt="Sofia" loading="lazy"><span class="text-[15px] font-semibold text-trb21-mut transition-colors group-has-checked:text-white">Sofia</span></label>
<label class="group relative grid cursor-pointer justify-items-center gap-3"><input type="radio" name="trb-21" value="mateo" class="sr-only"><img class="size-[92px] rounded-full object-cover brightness-80 saturate-70 ring-trb21-acc ring-offset-trb21-bg transition-[scale,filter,box-shadow] duration-350 ease-trb21-spring group-hover:brightness-100 group-hover:saturate-100 group-has-checked:shadow-trb21-lift group-has-checked:ring-3 group-has-checked:ring-offset-4 group-has-checked:brightness-100 group-has-checked:saturate-100 group-has-focus-visible:outline-3 group-has-focus-visible:outline-offset-[10px] group-has-focus-visible:outline-white motion-safe:group-has-checked:scale-112" src="https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=300&q=80&auto=format&fit=crop" alt="Mateo" loading="lazy"><span class="text-[15px] font-semibold text-trb21-mut transition-colors group-has-checked:text-white">Mateo</span></label>
<div class="grid justify-items-center gap-3"><button type="button" class="grid size-[92px] cursor-pointer place-items-center rounded-full border-2 border-dashed border-white/25 text-trb21-mut transition-colors hover:border-white/60 hover:text-white focus-visible:outline-3 focus-visible:outline-offset-4 focus-visible:outline-white" aria-label="Add profile"><svg class="size-7" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M12 5v14M5 12h14"/></svg></button><span aria-hidden="true" class="text-[15px] font-semibold text-trb21-mut">Add</span></div>
</div>
</fieldset>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-trb21-bg: #101014;
--color-trb21-bg: oklch(0.18 0.006 285);
--color-trb21-ink: #f2f2f5;
--color-trb21-ink: oklch(0.96 0.004 285);
--color-trb21-mut: #9c9ca8;
--color-trb21-mut: oklch(0.7 0.012 285);
--color-trb21-acc: #f36f5c;
--color-trb21-acc: oklch(0.7 0.16 30);
--shadow-trb21-lift: 0 16px 34px -12px oklch(0 0 0 / 0.8);
--ease-trb21-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
--font-trb21-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}
/* 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. */
.trb-21 {
width: 100%;
min-height: 100svh;
}
```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 Avatar Radio Picker (Profile Selector)
Source: https://codefronts.com/components/tailwind-css-radio-buttons/tailwind-avatar-radio-picker-profile-selector/
The "who's watching?" screen as a proper form control: profile photos where the active one scales up, gains a bright ring and full colour while the rest rest slightly dimmed. The double ring is ring-3 ring-trb21-acc ring-offset-4 ring-offset-trb21-bg; the sprung lift is motion-safe:. An "Add profile" tile shows how to mix an action into the row without joining the radio group.
## HTML
```html
<section class="trb-21 w-full min-h-svh grid place-items-center bg-trb21-bg px-6 py-14 font-trb21-sans text-trb21-ink" aria-label="User profile avatar selector demo">
<fieldset>
<legend class="text-center text-[30px] font-extrabold tracking-[-0.025em]">Who's watching?</legend>
<div class="mt-9 flex flex-wrap justify-center gap-8">
<label class="group relative grid cursor-pointer justify-items-center gap-3"><input type="radio" name="trb-21" value="amara" class="sr-only" checked><img class="size-[92px] rounded-full object-cover brightness-80 saturate-70 ring-trb21-acc ring-offset-trb21-bg transition-[scale,filter,box-shadow] duration-350 ease-trb21-spring group-hover:brightness-100 group-hover:saturate-100 group-has-checked:shadow-trb21-lift group-has-checked:ring-3 group-has-checked:ring-offset-4 group-has-checked:brightness-100 group-has-checked:saturate-100 group-has-focus-visible:outline-3 group-has-focus-visible:outline-offset-[10px] group-has-focus-visible:outline-white motion-safe:group-has-checked:scale-112" src="https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=300&q=80&auto=format&fit=crop" alt="Amara" loading="lazy"><span class="text-[15px] font-semibold text-trb21-mut transition-colors group-has-checked:text-white">Amara</span></label>
<label class="group relative grid cursor-pointer justify-items-center gap-3"><input type="radio" name="trb-21" value="jonas" class="sr-only"><img class="size-[92px] rounded-full object-cover brightness-80 saturate-70 ring-trb21-acc ring-offset-trb21-bg transition-[scale,filter,box-shadow] duration-350 ease-trb21-spring group-hover:brightness-100 group-hover:saturate-100 group-has-checked:shadow-trb21-lift group-has-checked:ring-3 group-has-checked:ring-offset-4 group-has-checked:brightness-100 group-has-checked:saturate-100 group-has-focus-visible:outline-3 group-has-focus-visible:outline-offset-[10px] group-has-focus-visible:outline-white motion-safe:group-has-checked:scale-112" src="https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=300&q=80&auto=format&fit=crop" alt="Jonas" loading="lazy"><span class="text-[15px] font-semibold text-trb21-mut transition-colors group-has-checked:text-white">Jonas</span></label>
<label class="group relative grid cursor-pointer justify-items-center gap-3"><input type="radio" name="trb-21" value="sofia" class="sr-only"><img class="size-[92px] rounded-full object-cover brightness-80 saturate-70 ring-trb21-acc ring-offset-trb21-bg transition-[scale,filter,box-shadow] duration-350 ease-trb21-spring group-hover:brightness-100 group-hover:saturate-100 group-has-checked:shadow-trb21-lift group-has-checked:ring-3 group-has-checked:ring-offset-4 group-has-checked:brightness-100 group-has-checked:saturate-100 group-has-focus-visible:outline-3 group-has-focus-visible:outline-offset-[10px] group-has-focus-visible:outline-white motion-safe:group-has-checked:scale-112" src="https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=300&q=80&auto=format&fit=crop" alt="Sofia" loading="lazy"><span class="text-[15px] font-semibold text-trb21-mut transition-colors group-has-checked:text-white">Sofia</span></label>
<label class="group relative grid cursor-pointer justify-items-center gap-3"><input type="radio" name="trb-21" value="mateo" class="sr-only"><img class="size-[92px] rounded-full object-cover brightness-80 saturate-70 ring-trb21-acc ring-offset-trb21-bg transition-[scale,filter,box-shadow] duration-350 ease-trb21-spring group-hover:brightness-100 group-hover:saturate-100 group-has-checked:shadow-trb21-lift group-has-checked:ring-3 group-has-checked:ring-offset-4 group-has-checked:brightness-100 group-has-checked:saturate-100 group-has-focus-visible:outline-3 group-has-focus-visible:outline-offset-[10px] group-has-focus-visible:outline-white motion-safe:group-has-checked:scale-112" src="https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=300&q=80&auto=format&fit=crop" alt="Mateo" loading="lazy"><span class="text-[15px] font-semibold text-trb21-mut transition-colors group-has-checked:text-white">Mateo</span></label>
<div class="grid justify-items-center gap-3"><button type="button" class="grid size-[92px] cursor-pointer place-items-center rounded-full border-2 border-dashed border-white/25 text-trb21-mut transition-colors hover:border-white/60 hover:text-white focus-visible:outline-3 focus-visible:outline-offset-4 focus-visible:outline-white" aria-label="Add profile"><svg class="size-7" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M12 5v14M5 12h14"/></svg></button><span aria-hidden="true" class="text-[15px] font-semibold text-trb21-mut">Add</span></div>
</div>
</fieldset>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-trb21-bg: #101014;
--color-trb21-bg: oklch(0.18 0.006 285);
--color-trb21-ink: #f2f2f5;
--color-trb21-ink: oklch(0.96 0.004 285);
--color-trb21-mut: #9c9ca8;
--color-trb21-mut: oklch(0.7 0.012 285);
--color-trb21-acc: #f36f5c;
--color-trb21-acc: oklch(0.7 0.16 30);
--shadow-trb21-lift: 0 16px 34px -12px oklch(0 0 0 / 0.8);
--ease-trb21-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
--font-trb21-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}
/* 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. */
.trb-21 {
width: 100%;
min-height: 100svh;
}
```How this works
Rings, not shadows. The original built a gap ring and an accent ring from two box-shadow spreads; ring-offset-4 paints the gap in the stage colour and ring-3 the accent, still composable with shadow-* for depth.
Faces are content. Every photo's alt is the person's name, and the visible caption matches, so the option announces as "Amara, radio button, checked". The Add tile is a real button — arrow keys never land on it.
Make it yours
- Accent:
--color-trb21-acc; keepring-offset-trb21-bgmatched to the stage. - Calmer: drop the
scale-112lift. - Size:
size-[92px]on each image and the Add tile.
Gotchas — read before shipping
ring-offset-*is a solid colour — change the stage colour and the offset must follow.- Filter the image, not the label, or captions dim too.
- Keep scale deltas ≤1.15 to avoid mid-animation blur on low-DPI screens.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.4+ | 128+ | 111+ |
Photos hotlink from Unsplash's free CDN. :has() drives state; degrades to plain radios.