Advanced Selectors

Back

Loading concept...

Tailwind CSS Advanced Selectors: The Magic Wands of Styling 🪄

Imagine you have a box of crayons. But these aren’t ordinary crayons—they’re magic crayons that only color things when special conditions happen. That’s what Tailwind’s advanced selectors are! They let you style elements based on what’s happening around them.


The Big Picture

Think of your webpage like a family dinner table. Sometimes you want to change someone’s plate color based on:

  • What their sibling (brother/sister) is doing
  • What their parent is doing
  • Whether they have something special on their plate
  • Whether they don’t have something

Tailwind’s advanced selectors give you this superpower!


1. Pseudo-element Variants

What Are They?

Pseudo-elements are like invisible helpers that appear before or after your element. You can’t see them in your HTML, but they’re there!

<div class="before:content-['Hello!']
            before:text-red-500
            after:content-['đź‘‹']
            after:ml-2">
  Welcome
</div>

This shows: Hello! Welcome đź‘‹

Common Pseudo-elements

Variant What It Does
before: Adds invisible element at start
after: Adds invisible element at end
first-letter: Styles the first letter
first-line: Styles the first line
placeholder: Styles placeholder text
selection: Styles highlighted text

Real Example: Fancy Quote

<blockquote class="before:content-['"']
                  before:text-4xl
                  before:text-blue-500
                  after:content-['"']
                  after:text-4xl">
  Learning is fun!
</blockquote>

2. Group Modifier

The Family Connection

Imagine a family photo. When Mom smiles, everyone’s shirt changes color! That’s the group modifier.

The parent gets the group class, and children react to the parent’s state.

<div class="group bg-white
            hover:bg-blue-500">
  <p class="text-black
            group-hover:text-white">
    I change when parent hovers!
  </p>
</div>

How It Works

graph TD A["Parent with &&#35;39;group&&#35;39;"] --> B["Child 1"] A --> C["Child 2"] A --> D["Child 3"] style A fill:#3b82f6,color:#fff B --> E["Uses group-hover:"] C --> F["Uses group-focus:"] D --> G["Uses group-active:"]

Named Groups

When you have multiple groups, give them names!

<div class="group/card">
  <div class="group/button">
    <span class="group-hover/card:text-blue-500
                 group-hover/button:text-red-500">
      Different reactions!
    </span>
  </div>
</div>

3. Peer Modifier

The Sibling Connection

If group is about parent-child, peer is about siblings (brothers and sisters).

When your sibling does something, YOU change!

<input class="peer"
       type="checkbox">

<label class="peer-checked:text-green-500
              peer-checked:font-bold">
  I turn green when checked!
</label>

Important Rule

The peer element must come BEFORE the element that reacts to it in your HTML.

graph LR A["peer element"] --> B["peer-*: element"] style A fill:#10b981,color:#fff style B fill:#f59e0b,color:#fff

Named Peers

Just like groups, peers can have names!

<input class="peer/email" type="email">
<input class="peer/password" type="password">

<p class="peer-invalid/email:text-red-500">
  Email is invalid
</p>
<p class="peer-invalid/password:text-red-500">
  Password is invalid
</p>

4. Has Selector

The “Do I Have This?” Question

The has- selector is like asking: “Do I have a child that’s doing something special?”

<div class="has-[:checked]:bg-green-100
            has-[:checked]:border-green-500">
  <input type="checkbox">
  <span>Check me!</span>
</div>

When the checkbox is checked, the parent div changes!

Real-World Example

<form class="has-[:invalid]:border-red-500
             has-[:invalid]:bg-red-50">
  <input type="email" required>
  <button>Submit</button>
</form>

If any input is invalid, the whole form gets a red border!


5. Not Selector

The “Except This” Rule

Sometimes you want to style everything except certain things.

<button class="not-[:disabled]:bg-blue-500
               not-[:disabled]:hover:bg-blue-600
               disabled:bg-gray-300">
  Click Me
</button>

How to Read It

Selector Meaning
not-[:disabled] When NOT disabled
not-[:first-child] When NOT first child
not-[:empty] When NOT empty

6. Arbitrary Variants

Your Custom Rules!

What if Tailwind doesn’t have the selector you need? Make your own!

Use square brackets [...] to write any CSS selector:

<ul class="[&>li]:pl-4
           [&>li]:border-l-2">
  <li>Item 1</li>
  <li>Item 2</li>
</ul>

Breakdown

Arbitrary Variant What It Means
[&>li] Direct child li elements
[&_p] Any descendant p elements
[@media(min-width:900px)] Custom media query
[&:nth-child(3)] Third child

Real Example

<div class="[&:not(:first-child)]:mt-4">
  <p>First (no margin)</p>
  <p>Second (has margin)</p>
  <p>Third (has margin)</p>
</div>

7. Stacking Variants

Combining Powers!

You can stack multiple variants together. They apply from left to right:

<button class="group-hover:focus:text-white">
  Hover parent + focus me!
</button>

How Stacking Works

graph LR A["dark:"] --> B["md:"] --> C["hover:"] D["Result: dark mode + medium screen + hovering"] style A fill:#1e293b,color:#fff style B fill:#3b82f6,color:#fff style C fill:#f59e0b,color:#fff

Examples

<!-- Dark mode + hover -->
<button class="dark:hover:bg-gray-700">
  Dark hover button
</button>

<!-- Medium screen + focus + disabled -->
<input class="md:focus:disabled:bg-gray-100">

<!-- Group hover + first child -->
<div class="group-hover:first:text-blue-500">

Reading Order

Read stacked variants right to left:

dark:md:hover:text-white means:

  1. When hovering (hover:)
  2. On medium screens (md:)
  3. In dark mode (dark:)
  4. Make text white

8. Open State Variant

For Things That Open & Close

The open: variant styles elements when they’re in an open state. Perfect for:

  • <details> elements
  • <dialog> elements
<details class="open:bg-blue-100
               open:ring-2
               open:ring-blue-500">
  <summary class="cursor-pointer
                  p-4">
    Click to expand
  </summary>
  <p class="p-4">
    Hidden content revealed!
  </p>
</details>

How It Looks

graph TD A["Closed State"] -->|Click| B["Open State"] A --> C["Normal styling"] B --> D["open: styling applied"] style B fill:#3b82f6,color:#fff

Dialog Example

<dialog class="open:animate-fade-in
               open:backdrop:bg-black/50">
  <p>Modal content here!</p>
</dialog>

Quick Summary

Selector Purpose Example
before: / after: Add pseudo content before:content-['→']
group-*: React to parent state group-hover:text-blue-500
peer-*: React to sibling state peer-checked:bg-green-100
has-[]: Check for child state has-[:focus]:ring-2
not-[]: Style when NOT matching not-[:disabled]:cursor-pointer
[&...] Custom arbitrary selector [&>*]:p-2
variant:variant: Stack multiple conditions dark:hover:text-white
open: Style open state open:rotate-180

You Did It! 🎉

You now understand the advanced selectors in Tailwind CSS. These are your magic wands for creating dynamic, responsive, and smart styles without writing custom CSS.

Remember:

  • Group = Parent controls children
  • Peer = Sibling controls sibling
  • Has = Parent checks children
  • Not = Style the opposite
  • Stack = Combine conditions
  • Open = For expandable elements

Now go make something amazing! ✨

Loading story...

Story - Premium Content

Please sign in to view this story and start learning.

Upgrade to Premium to unlock full access to all stories.

Stay Tuned!

Story is coming soon.

Story Preview

Story - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.