Search code examples
radio-buttontailwind-css

TailwindCSS - Change Label When Radio Button Checked


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>

Solution

  • 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