TailwindCSS - Change Label When Radio Button Checked
Asked Answered
C

5

20

I see that the TailwindCSS checked: variant can be enabled to change the input element when checked, but how can I change the input's label when checked?

Here is the relevant Tailwind CSS docs.

Sample code below.

After enabling the variant in tailwind.config.js, putting checked:bg-green-300 in the div or the label doesn't work. It only works in the input.

<div>
  <label>
    <input checked type="radio" name="option1" id="option1" className="hidden" />
    <div>option1</div>
  </label>
  <label>
    <input checked type="radio" name="option2" id="option1" className="hidden" />
    <div>option2</div>
  </label>
</div>
Caligula answered 19/1, 2021 at 1:31 Comment(0)
P
54

EDIT: as version 2.2+ was released it has built-in support for sibling selector variants called peer (watch updates release)

This feature is only available in Just-in-Time mode.

<label>
    <input checked type="radio" name="option" id="option1" class="hidden peer" />
    <div class="peer-checked:bg-red-600">option1</div>
</label>

For versions bellow 2.2: You need to write your own plugin for adding a new variant. More info here

For example, let's name it label-checked

tailwind.config.js

const plugin = require('tailwindcss/plugin');

module.exports = {
    purge: [],
    darkMode: false, // or 'media' or 'class'
    theme: {},
    variants: {
        extend: {
            backgroundColor: ['label-checked'], // you need add new variant to a property you want to extend
        },
    },
    plugins: [
        plugin(({ addVariant, e }) => {
            addVariant('label-checked', ({ modifySelectors, separator }) => {
                modifySelectors(
                    ({ className }) => {
                        const eClassName = e(`label-checked${separator}${className}`); // escape class
                        const yourSelector = 'input[type="radio"]'; // your input selector. Could be any
                        return `${yourSelector}:checked ~ .${eClassName}`; // ~ - CSS selector for siblings
                    }
                )
            })
        }),
    ],
};

This configuration should work for next cases (We extended backgroundColor, so it should work with bg-color classes):

1 - label is the wrapper, it's text should be wrapped in any selector (in this case div)

<label>
    <input checked type="radio" name="option1" id="option1" class="hidden" />
    <div class="label-checked:bg-red-600">option1</div>
</label>

2 - label after input

<input checked type="radio" name="option1" id="option1" class="hidden" />
<label for="option-1" class="label-checked:bg-red-600"></label>

DEMO - https://play.tailwindcss.com/SEQ4NRpPV3

Pecker answered 19/1, 2021 at 11:25 Comment(2)
This does not work if the sibling element has a default bg colorEnergy
@stifler97 It works. Or maybe I misunderstood you, need to see your codePecker
S
4

Use the peer class as per the tailwind 2.2.0

<input type="checkbox" name="themeToggler" id="themeToggler" class="peer" />
<label for="themeToggler" class="w-10 h-10 bg-gray-400 peer-checked:bg-red-400"></label>

DEMO

Sensorium answered 16/8, 2021 at 17:24 Comment(0)
R
2

Tailwind's peer class is the modern way to solve this.

You can add peer behavior by adding two classes to the HTML.

  1. Add the peer class to the HTML tag you want to observe the state for.
  2. Add the peer-checked class, followed by the desired behavior change, to a sibling element.

See a detailed example here

Roybn answered 20/11, 2021 at 8:24 Comment(0)
S
2

In Tailwind CSS 3.0 you can create custom radio button like this

<div class="p-3 h-screen w-full flex justify-center items-center bg-black">

<div class="w-full">
    <div class="flex">
        <p class="text-[20px] text-white">Which of the following is an asian country?</p>
    </div>
    <div class="md:grid grid-cols-12 gap-3 pb-4 w-full">
        <div className="col-span-6">
         <div class="w-full">
            <input id="default-radio-1" type="radio" value="" name="default-radio" class="peer opacity-0 w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600">
            <label for="default-radio-1" class="flex cursor-pointer  bg-gray-200 justify-center items-center h-10 w-full peer-checked:bg-rose-500 peer-checked:text-white text-[17px] text-sm font-medium text-gray-900 dark:text-gray-300">India</label>
         </div>
        </div>
        <div className="col-span-6">
            <div class="w-full">
            <input id="default-radio-2" type="radio" value="" name="default-radio" class="peer opacity-0 w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600">
            <label for="default-radio-2" class="flex cursor-pointer  bg-gray-200 justify-center items-center h-10 w-full peer-checked:bg-rose-500 peer-checked:text-white text-[17px] text-sm font-medium text-gray-900 dark:text-gray-300">Australia</label>
        </div>
        </div>
        <div className="col-span-6">
            <div class="w-full">
            <input id="default-radio-3" type="radio" value="" name="default-radio" class="peer opacity-0 w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600">
            <label for="default-radio-3" class="flex cursor-pointer  bg-gray-200 justify-center items-center h-10 w-full peer-checked:bg-rose-500 peer-checked:text-white text-[17px] text-sm font-medium text-gray-900 dark:text-gray-300">USA</label>
        </div>
        </div>
        <div className="col-span-6">
            <div class="w-full">
            <input id="default-radio-4" type="radio" value="" name="default-radio" class="peer opacity-0 w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600">
            <label for="default-radio-4" class="flex cursor-pointer bg-gray-200 justify-center items-center h-10 w-full peer-checked:bg-rose-500 peer-checked:text-white text-[17px] text-sm font-medium text-gray-900 dark:text-gray-300">Germany</label>
        </div>
        </div>
    </div>
</div>

Checkout this running example - https://bbbootstrap.com/snippets/custom-radio-button-91048657

Skulduggery answered 4/7, 2022 at 6:1 Comment(1)
Thank you! This worked for me nicely. Thanks for providing the example tooLaborious
E
0

Starting from TailwindCSS 3.4, you can now use has-* which utilizes CSS' :has() pseudo-selector. Here's an example how to use it:

<script src="https://cdn.tailwindcss.com/3.4.3"></script>

<div class="flex gap-2">
  <label class="bg-gray-100 border-gray-100 p-4 rounded has-[:checked]:text-green-500 has-[:checked]:bg-green-100 has-[:checked]:border-green-700">
    <input type="radio" name="option" id="option1" class="hidden" />
    <div>option1</div>
  </label>
  <label class="bg-gray-100 border-gray-100 p-4 rounded has-[:checked]:text-green-500 has-[:checked]:bg-green-100 has-[:checked]:border-green-700">
    <input type="radio" name="option" id="option1" class="hidden" />
    <div>option2</div>
  </label>
</div>
Eudemonics answered 5/4, 2024 at 15:4 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.