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 &#39;group&#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:
- When hovering (
hover:) - On medium screens (
md:) - In dark mode (
dark:) - 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! ✨
