TailwindCSS group-focus-within and group-has
An iMessage composer built with group-focus-within and group-has - tray collapse, icon crossfade, and conditional pickers, all CSS-only.
Tailwind's group-focus-within modifier styles children when any focusable element inside a named group receives focus. Combined with Tailwind v4's group-has-[...], you can target which element has focus - no JS needed.
This iMessage-style composer uses both patterns: group-focus-within/chat collapses the icon tray and crossfades the send button when anything is focused, while group-has-[.camera-btn:focus]/chat reveals a specific picker panel only when the Camera button holds focus.
Click the camera or gallery icon, then click the input:
group-focus-within/chat drives the tray collapse, button glow, and mic/send crossfade. group-has-[.camera-btn:focus]/chat and group-has-[.gallery-btn:focus]/chat conditionally reveal each picker - all CSS transitions, zero JS.
Pattern
<!-- Named group wraps the whole composer -->
<div class="group/chat">
<!-- Icon tray collapses when any input is focused -->
<div class="w-16 opacity-100
group-focus-within/chat:w-0
group-focus-within/chat:opacity-0">
<button class="camera-btn" />
<button class="gallery-btn" />
</div>
<!-- Picker appears when a specific button has focus -->
<div class="grid grid-rows-[0fr] opacity-0
group-has-[.camera-btn:focus]/chat:grid-rows-[1fr]
group-has-[.camera-btn:focus]/chat:opacity-100">
Camera picker…
</div>
</div>Newsletter
Stay updated with my latest articles and projects. No spam, no nonsense.