I would like to extend the peer-
modifier in Tailwind such that when I write this:
<div class="peer peer-hover:opacity-50"></div>
<div class="peer peer-hover:opacity-50"></div>
<div class="peer peer-hover:opacity-50"></div>
Then when I hover over any of those divs, the divs I’m not hovered over have a lowered opacity. By default, it only applies the opacity change to the siblings after the hovered element, but not the siblings before it. This can be fixed by adding the class has-[~_.peer:hover]:opacity-50
to all of those divs, which applies the opacity change to the siblings before the hovered element.
I would like to have the peer-mod:style
modifer automatically add the matching has-[~_.peer:mod]:style
, or create a new modifier that adds both, so that I don’t need to write both every time I need to use it. I also want it to work with any modifier, not just hover
. Is there a way I can write a custom plugin to make this work?
Here’s a demo to show what I’d like to achieve: https://play.tailwindcss.com/tKt6L7S447
<div class="absolute inset-0 flex flex-col items-center justify-center gap-10">
<div class="flex flex-col items-center gap-4">
<p class="text-xl">Default Peer Hover (Can only style subsequent siblings)</p>
<div class="flex items-center justify-center gap-12">
<div class="peer size-24 rounded-md bg-lime-400 transition-transform hover:scale-125 peer-hover:scale-50 peer-hover:opacity-50"></div>
<div class="peer size-24 rounded-md bg-lime-400 transition-transform hover:scale-125 peer-hover:scale-50 peer-hover:opacity-50"></div>
<div class="peer size-24 rounded-md bg-lime-400 transition-transform hover:scale-125 peer-hover:scale-50 peer-hover:opacity-50"></div>
<div class="peer size-24 rounded-md bg-lime-400 transition-transform hover:scale-125 peer-hover:scale-50 peer-hover:opacity-50"></div>
</div>
</div>
<div class="flex flex-col items-center gap-4">
<p class="text-xl">Better Peer Hover (Styles any sibling)</p>
<div class="flex items-center justify-center gap-12">
<div class="peer size-24 rounded-md bg-rose-300 transition-transform hover:scale-125 peer-hover:scale-50 has-[~_.peer:hover]:scale-50 peer-hover:opacity-50 has-[~_.peer:hover]:opacity-50"></div>
<div class="peer size-24 rounded-md bg-rose-300 transition-transform hover:scale-125 peer-hover:scale-50 has-[~_.peer:hover]:scale-50 peer-hover:opacity-50 has-[~_.peer:hover]:opacity-50"></div>
<div class="peer size-24 rounded-md bg-rose-300 transition-transform hover:scale-125 peer-hover:scale-50 has-[~_.peer:hover]:scale-50 peer-hover:opacity-50 has-[~_.peer:hover]:opacity-50"></div>
<div class="peer size-24 rounded-md bg-rose-300 transition-transform hover:scale-125 peer-hover:scale-50 has-[~_.peer:hover]:scale-50 peer-hover:opacity-50 has-[~_.peer:hover]:opacity-50"></div>
</div>
</div>
</div>
1
You can override core’s peer-*
variants with your own. Return an array value in the matchVariants()
callback to add multiple selectors at once:
require('tailwindcss/plugin')(({ matchVariant }) => {
matchVariant(
'peer',
(value) => [
`.peer${value} ~ &`,
`&:has(~ .peer${value})`
],
{
values: {
'hover': ':hover',
}
}
);
}),
tailwind.config = {
plugins: [
tailwind.plugin(({ matchVariant }) => {
matchVariant(
'peer',
(value) => [
`.peer${value} ~ &`,
`&:has(~ .peer${value})`
],
{
values: {
'hover': ':hover',
}
}
);
}),
],
}
<script src="https://cdn.tailwindcss.com/3.4.5"></script>
<div class="absolute inset-0 flex flex-col items-center justify-center gap-10">
<div class="flex flex-col items-center gap-4">
<p class="text-xl">Default Peer Hover (Can only style subsequent siblings)</p>
<div class="flex items-center justify-center gap-12">
<div class="peer size-24 rounded-md bg-lime-400 transition-transform hover:scale-125 peer-hover:scale-50 peer-hover:opacity-50"></div>
<div class="peer size-24 rounded-md bg-lime-400 transition-transform hover:scale-125 peer-hover:scale-50 peer-hover:opacity-50"></div>
<div class="peer size-24 rounded-md bg-lime-400 transition-transform hover:scale-125 peer-hover:scale-50 peer-hover:opacity-50"></div>
<div class="peer size-24 rounded-md bg-lime-400 transition-transform hover:scale-125 peer-hover:scale-50 peer-hover:opacity-50"></div>
</div>
</div>
</div>
This is a simplified version. In reality, you may wish to fully adapt Tailwind’s peer plugin code, but this is more complex.