owzim
owzim

Reputation: 925

Custom group "states" in tailwind css

There are essentially just two states for groups out-of-the-box: hover and focus

Simplified examples:

<div class="group">
  <p class="group-hover:text-gray-900">foo</p>
  <p class="group-hover:text-gray-500">bar</p>
</div>
<a class="group">
  <span class="group-focus:text-gray-900">foo</span>
  <span class="group-focus:text-gray-500">bar</span>
</a>

Ho to add custom states, so this is possible:

<a class="group">
  <span class="group-foo-state:text-gray-900">foo</span>
  <span class="group-foo-state:text-gray-500">bar</span>
</a>

and with the custom state foo-state active

<a class="group foo-state">
  <span class="group-foo-state:text-gray-900">foo</span>
  <span class="group-foo-state:text-gray-500">bar</span>
</a>

Essentially mimicking the CSS cascade.

Upvotes: 4

Views: 6326

Answers (1)

Ihar Aliakseyenka
Ihar Aliakseyenka

Reputation: 14293

You can write plugin or use same arbitrary variants since Tailwind 3.1.

To support the group-* and peer-* versions of your own custom modifiers, register them as separate variants using the special :merge directive to ensure the .group and .peer classes only appear once in the final selector - link

// tailwind.config.js

const plugin = require('tailwindcss/plugin')

/** @type {import('tailwindcss').Config} */
module.exports = {
  theme: {
    extend: {
      // ...
    },
  },
  plugins: [
    plugin(function({ addVariant }) {
      addVariant('group-with-foo', ':merge(.group).foo &') // custom CSS
      addVariant('group-no-foo', ':merge(.group):not(.foo) &')
    })
  ],
}

addVarinat function is what creates new variant. First argument - variant name, should be unique. Second - any valid CSS as string (or function which should return string or an array of strings).

& sign points to an element with THIS custom variant. Your plugin SHOULD have either & or starts with @ symbol otherwise it will not be valid.

<a class="group">
  <span class="group-with-foo:bg-red-500">
    Parent has NOT `foo` class therefore I'm NOT red
  </span>
  <span class="group-no-foo:bg-red-500">
    Parent has NOT `foo` class but it doesn't matter (it has `group` though)
  </span>
</a>

<hr>

<a class="group foo">
  <span class="group-with-foo:bg-red-500">
    It is red because parent has BOTH `group` and `foo` class
  </span>
  <span class="group-no-foo:bg-red-500">
    Parent has `foo` class therefore I'm not red
  </span>
</a>

If you need to use arbitrary variants you need to pass same CSS as seconda argument, but instead of spaces you should use _. If your class has _ sign, it must be escaped as \_

<a class="group">
  <span class="[.group.foo_&]:bg-red-500">
    It is red because parent has BOTH `group` and `foo` class
  </span>
  <span class="[.group:not(.foo)_&]:bg-red-500">
    Parent has `foo` class therefore I'm not red
  </span>
</a>

DEMO

Upvotes: 7

Related Questions