Element States

Back

Loading concept...

State Variants: Making Elements React to What’s Happening 🎭

Imagine you have a box of crayons. Some crayons are brand new, some are broken, and some are your favorite colors. Wouldn’t it be cool if you could make things look different based on what’s happening to them right now?

That’s exactly what State Variants do in Tailwind CSS! They let you change how things look based on their current “mood” or “situation.”


🎯 What We’ll Learn

Think of your webpage as a playground. Different things happen there:

  • A button gets clicked
  • A text box is empty (nobody typed anything yet)
  • A form has a mistake
  • Something is turned off (disabled)
  • A parent element has something special happening to its children

Let’s explore each one like we’re on an adventure!


👶 Child State Variants: When Parents Watch Their Kids

The Big Idea

Imagine you’re a parent at a playground. When YOUR child does something special, you want to react! In Tailwind, a parent element can change its own style based on what happens to its children.

How It Works

We use group and group-* to make this magic happen!

<div class="group">
  <button class="group-hover:text-blue-500">
    Hover over parent to change me!
  </button>
</div>

🎨 Real Example: Card with Glowing Effect

<div class="group bg-white p-4 rounded-lg">
  <h3 class="group-hover:text-purple-600">
    Card Title
  </h3>
  <p class="group-hover:text-gray-700">
    When you hover the card, we both change!
  </p>
</div>

More Child State Variants

Variant What It Does
group-focus Child reacts when something in group is focused
group-active Child reacts when group is being clicked
group-disabled Child reacts when group is disabled

🧠 Simple Analogy

Think of it like a family photo. When Mom smiles (the parent), everyone else in the photo smiles too (the children)!


📭 Empty State: When Nothing Is There

The Big Idea

What if you have a lunchbox but there’s no food inside? That’s the empty state! In web pages, we can style things differently when they have nothing inside them.

How It Works

Use empty: to target elements with no content:

<div class="empty:bg-gray-100 empty:p-8">
  <!-- If this is empty, it gets gray background -->
</div>

🎨 Real Example: Empty Cart Message

<ul class="empty:text-center empty:text-gray-400
           empty:before:content-['Nothing_here_yet!']">
  <!-- Items will go here -->
</ul>

When Is Something “Empty”?

Empty ✅ Not Empty ❌
<div></div> <div>Hello</div>
<span></span> <span> </span> (even a space counts!)
No children Has any child element

🧠 Simple Analogy

It’s like a cookie jar. When it’s empty, you put a “Please refill me!” sign on it. When it has cookies, you don’t need the sign!


✏️ Input State Variants: What’s Happening to the Text Box?

The Big Idea

Text boxes and input fields are like little helpers waiting for you to type. They have different “moods” depending on what you’re doing with them:

  • Are you typing in it? (focus)
  • Did you type the wrong thing? (invalid)
  • Is it the right format? (valid)
  • Is there already something in it? (placeholder-shown)

Focus State: “I’m Being Used Right Now!”

<input class="focus:border-blue-500
              focus:ring-2 focus:ring-blue-200"
       type="text">

When you click on the input, it gets a blue border and a glowing ring!

Valid & Invalid States

<input type="email"
       class="valid:border-green-500
              invalid:border-red-500"
       required>
  • Type a proper email → green border
  • Type gibberish → red border

Placeholder-Shown State

This targets inputs when the placeholder text is still visible (meaning user hasn’t typed anything):

<input class="placeholder-shown:border-gray-300
              not-placeholder-shown:border-blue-500"
       placeholder="Type something...">

All Input State Variants

Variant When It Happens
focus User clicked into the field
focus-visible Focused using keyboard (tab)
focus-within Anything inside is focused
valid Input passes validation
invalid Input fails validation
placeholder-shown Placeholder is visible
autofill Browser auto-filled this
read-only Can see but can’t edit

🧠 Simple Analogy

Think of an input like a spotlight on a stage. When the actor (cursor) steps into it, the spotlight glows brighter (focus). If the actor says their lines correctly (valid), the audience claps. If they mess up (invalid), they get a red X!


📝 Form State Variants: The Whole Form’s Mood

The Big Idea

Sometimes you want to style things based on what’s happening to the entire form, not just one input. Is the form being submitted? Are there errors? Is everything optional or required?

Required Fields

<input type="text" required
       class="required:border-l-4
              required:border-l-red-500">

This adds a red left border to show “Hey, you MUST fill this in!”

Optional Fields

<input type="text"
       class="optional:border-l-4
              optional:border-l-gray-300">

Optional fields get a subtle gray indicator.

In-Range and Out-of-Range

For number inputs with min/max values:

<input type="number" min="1" max="10"
       class="in-range:bg-green-50
              out-of-range:bg-red-50">
  • Type 5 → light green background (in range!)
  • Type 15 → light red background (too high!)

All Form State Variants

Variant What It Checks
required Field is marked as required
optional Field is NOT required
in-range Number is within min/max
out-of-range Number is outside min/max
checked Checkbox/radio is checked
indeterminate Checkbox is in “maybe” state

🧠 Simple Analogy

Think of a form like a checklist for a birthday party. Some items are MUST HAVE (cake, balloons) - those are required. Others are nice to have (extra napkins) - those are optional. The form helps everyone know what’s important!


🚫 Disabled Styling Patterns: When Things Are Turned Off

The Big Idea

Sometimes buttons and inputs need to be “turned off” - like a light switch. When something is disabled, users can see it but can’t use it. We need to make this SUPER CLEAR so nobody gets confused!

Basic Disabled Style

<button disabled
        class="disabled:opacity-50
               disabled:cursor-not-allowed">
  Can't Click Me
</button>

This makes the button:

  • 50% see-through (faded)
  • Shows a “not allowed” cursor (🚫)

Complete Disabled Pattern

Here’s the full recipe for disabled elements:

<button disabled
        class="bg-blue-500 text-white
               disabled:bg-gray-300
               disabled:text-gray-500
               disabled:cursor-not-allowed
               disabled:opacity-60
               disabled:shadow-none">
  Submit
</button>

Disabled Input Fields

<input disabled
       class="disabled:bg-gray-100
              disabled:text-gray-400
              disabled:border-gray-200
              disabled:cursor-not-allowed"
       value="You can't edit this">

Peer Disabled: Style Siblings When One Is Disabled

<input type="checkbox" disabled class="peer">
<label class="peer-disabled:text-gray-400
              peer-disabled:line-through">
  This label fades when checkbox is disabled
</label>

Group Disabled Pattern

<fieldset disabled class="group">
  <button class="group-disabled:opacity-50">
    I fade when fieldset is disabled
  </button>
</fieldset>

🧠 Simple Analogy

Think of disabled elements like a vending machine that’s out of order. The snacks are still visible through the glass (you can see them), but when you push the button, nothing happens (you can’t use them). The “Out of Order” sign (disabled styling) tells everyone not to even try!


🔄 Putting It All Together

Here’s a complete form that uses ALL these state variants:

<form class="group space-y-4">
  <!-- Required email with validation -->
  <input type="email" required
         placeholder="Enter email"
         class="w-full p-3 border rounded
                required:border-l-4
                required:border-l-red-400
                placeholder-shown:border-gray-300
                focus:border-blue-500
                focus:ring-2
                valid:border-green-500
                invalid:border-red-500
                disabled:bg-gray-100
                disabled:cursor-not-allowed">

  <!-- Empty message area -->
  <div class="empty:bg-gray-50
              empty:p-4
              empty:text-gray-400
              empty:text-center">
    <!-- Messages appear here -->
  </div>

  <!-- Submit button -->
  <button type="submit"
          class="px-6 py-2 bg-blue-500
                 text-white rounded
                 group-invalid:opacity-50
                 group-invalid:cursor-not-allowed
                 disabled:bg-gray-300">
    Submit
  </button>
</form>

📊 Quick Reference Flow

graph LR A["Element States"] --> B["Child States"] A --> C["Empty State"] A --> D["Input States"] A --> E["Form States"] A --> F["Disabled States"] B --> B1["group-hover"] B --> B2["group-focus"] B --> B3["group-active"] C --> C1["empty:"] D --> D1["focus"] D --> D2["valid/invalid"] D --> D3["placeholder-shown"] E --> E1["required/optional"] E --> E2["in-range/out-of-range"] E --> E3["checked"] F --> F1["disabled:"] F --> F2["peer-disabled"] F --> F3["group-disabled"]

🎉 What You Learned Today!

You’re now a State Variant expert! You can:

  1. 👶 Child States - Make children react when parents do something
  2. 📭 Empty State - Style empty containers differently
  3. ✏️ Input States - Show focus, valid, invalid, and placeholder states
  4. 📝 Form States - Handle required, optional, and range checking
  5. 🚫 Disabled States - Make disabled elements obviously unusable

Remember: State variants are like giving your elements superpowers to react to what’s happening around them. They make your website feel alive and responsive!


💡 Pro Tips

  1. Combine states: You can chain them! focus:invalid:border-red-600
  2. Use peer and group: They’re powerful for connected elements
  3. Always style disabled: Never leave users guessing what’s clickable
  4. Test your forms: Try all the states to make sure they look right

Now go make your forms and elements come alive! 🚀

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.