Published on

Tailwind CSS: Combining focus-within and focus-visible Effectively

Authors
  • Name
    Ripal & Zalak
    Twitter

Tailwind CSS: How to Combine focus-within and focus-visible

When working with interactive elements in Tailwind CSS, you may want to style a container (e.g., a div) when an inner element (like a button) is focused, but only for keyboard focus (not mouse clicks). While focus-within covers all types of focus, we need to combine it with focus-visible for accessibility and keyboard-specific styles.

Unfortunately, there’s no native focus-within-visible pseudo-class in CSS. But there are workarounds using Tailwind's utilities and modern CSS techniques.


Problem

Here’s the scenario:

  • A div container should be styled when a nested button is focused.
  • The focus should only apply for keyboard users (focus-visible), not mouse clicks.

Solution 1: Use :has with :focus-visible

Modern browsers support the :has selector, which allows us to check if a child element matches a condition (e.g., :focus-visible). You can implement this in Tailwind CSS using arbitrary variants.

<div
  class="rounded-lg bg-green-100 px-20 py-20 [&:has(:focus-visible)]:ring-4 [&:has(:focus-visible)]:ring-blue-300"
>
  <button class="bg-green-200 px-6 py-3 focus:outline-none">Focusable Button</button>
</div>

Explanation:

  • [&:has(:focus-visible)] is an arbitrary variant in Tailwind that applies the style when any child element matches :focus-visible.
  • In this example, the div gets a blue ring when its child button is keyboard-focused.

Note: Check browser support for the :has selector on Can I Use.


Solution 2: Use peer and absolute Positioning

If :has isn’t an option, you can achieve similar functionality using Tailwind's peer utility.

<div class="flex h-screen items-center justify-center">
  <div class="relative rounded-lg bg-green-100 px-20 py-20">
    <button class="peer relative z-[1] bg-green-200 px-6 py-3 focus:outline-none">
      Focusable Button
    </button>
    <div
      class="absolute inset-0 z-[0] rounded-lg peer-focus-visible:ring-4 peer-focus-visible:ring-blue-300"
    ></div>
  </div>
</div>

Explanation:

  • The button is marked as a peer.
  • The div with peer-focus-visible styles the container when the button is keyboard-focused.
  • Setting z-index ensures the button remains interactive and the div is styled correctly.

Try this example on Tailwind Play.


FAQs

1. Can I use focus-within and focus-visible directly together?

No, CSS doesn’t support focus-within-visible natively. You’ll need to use alternatives like :has or peer utilities in Tailwind CSS.

2. What if my browser doesn’t support :has?

You can use the peer approach, which works universally without requiring modern browser features like :has.

3. Why is peer-focus-visible better for accessibility?

peer-focus-visible ensures that styles are only applied during keyboard focus, improving the user experience for keyboard and assistive technology users.

4. How do I debug Tailwind focus states?

Use browser dev tools to inspect elements and toggle focus states manually. Tailwind's JIT mode also makes it easier to see applied classes in real-time.