user19485937
user19485937

Reputation:

TailwindCSS - is there a way to not write multiple times the same prefix? like `hover:` for example

The problem:

class="hover:bg-blue-400 hover:-translate-y-2 hover:-translate-x-2 hover:scale-110 hover:shadow-2xl hover:shadow-blue-400 hover:text-white"

here you see, there is the same prefix repetition.
hover:foo hover:bar hover:hello hover:world hover:something hover:another

I want to know if is there a way to not write multiple times the hover: prefix?


The idea:

is do something like:

hover:(class class class class class)

with brackets or something like that, so all the classes inside the () will be like one class and automatically added to the hover:

I think this idea there is in tailwind but I don't know the syntax for that.


if is possible this solution needs to work also with all the other prefixes

enter image description here


simple example demo:

// not important, only for deleting the console.warn() 
console.clear();
<script src="https://cdn.tailwindcss.com"></script>

<body class="flex h-screen">
  <button class="m-auto p-4 rounded-md  bg-blue-200 transition hover:bg-blue-400 hover:-translate-y-2 hover:-translate-x-2 hover:scale-110 hover:shadow-2xl hover:shadow-blue-400 hover:text-white">
     hello world
   </button>
</body>


I saw all the docs, that is not talking about this concept: https://tailwindcss.com/docs/hover-focus-and-other-states#hover-focus-and-active

if there is someone experienced in this thing, it will be helpful!

Upvotes: 2

Views: 2912

Answers (3)

Laaouatni Anas
Laaouatni Anas

Reputation: 3827

like he said @diego in the comment, this is technically not possible with tailwind only.


tailwind framework alternative

maybe you use a tailwind framework like windiCSS https://windicss.org/features/variant-groups.html

Note: Windi CSS is Sunsetting

that have this functionality:

<div class="hover:(bg-gray-400 font-medium) bg-white font-light"/>

javascript vanilla (simple script)

want tailwind only?

so I think that maybe we can create a simple JS script to solve this problem.

enter image description here

twHover();

function twHover() {
  // get only the elements that have the hover attribute
  let hoverEls = document.querySelectorAll("[data-hover]");

  // loop through the elements that have the hover attribute
  hoverEls.forEach((el) => {
    // we get the string inside the attribute
    // and then make it into a array
    let twHoverClasses = `${el.dataset.hover}`.split(" ");

    // loop through the classes inside the element's attributes
    twHoverClasses.forEach((className) => {
      // add the class for you `hover:className`
      el.classList.add(`hover:${className}`);
    });
  });
}
<script src="https://cdn.tailwindcss.com"></script>

<body class="flex h-screen">
  <!-- original -->
  <button class="m-auto p-4 rounded-md  bg-blue-200 transition hover:bg-blue-400 hover:-translate-y-2 hover:-translate-x-2 hover:scale-110 hover:shadow-2xl hover:shadow-blue-40 hover:text-white">original</button>
  <!-- with script -->
  <button data-hover="bg-blue-400 -translate-y-2 -translate-x-2 scale-110 shadow-2xl shadow-blue-40 text-white" class="m-auto p-4 rounded-md  bg-blue-200 transition">with script</button>
</body>


want more from the JS script?

  • also :focus, :lg, :sm, and so on.

use this:

// this can be any preudo class that tailwind can have
twPseudo("focus");
// if there is nothing as parameter, we use hover
twPseudo();

function twPseudo(pseudo = "hover") {
  // get only the elements that have the hover attribute
  let hoverEls = document.querySelectorAll(`[data-${pseudo}]`);

  // loop through the elements that have the hover attribute
  hoverEls.forEach((el) => {
    // we get the string inside the attribute
    // and then make it into a array
    let twHoverClasses = `${el.dataset[pseudo]}`.split(" ");

    // loop through the classes inside the element's attributes
    twHoverClasses.forEach((className) => {
      // add the class for you `hover:className`
      el.classList.add(`${pseudo}:${className}`);
    });
  });
}
<script src="https://cdn.tailwindcss.com"></script>

<body class="grid grid-cols-2 place-items-center h-screen">
  <!-- original -->
  <div>
    <h2 class="text-3xl font-bold text-blue-500 mb-4">original</h2>

    <!-- hover -->
    <button class="m-auto p-4 rounded-md bg-blue-200 transition hover:bg-blue-400 hover:-translate-y-2 hover:-translate-x-2 hover:scale-110 hover:shadow-2xl hover:shadow-blue-40 hover:text-white">hover</button>

    <!-- focus -->
    <button class="m-auto p-4 rounded-md bg-blue-200 transition focus:bg-blue-400 focus:-translate-y-2 focus:-translate-x-2 focus:scale-110 focus:shadow-2xl focus:shadow-blue-40 focus:text-white">focus</button>
  </div>

  <!-- with script -->
  <div>
    <h2 class="text-3xl font-bold text-blue-500  mb-4">with script</h2>

    <!-- hover -->
    <button data-hover="bg-blue-400 -translate-y-2 -translate-x-2 scale-110 shadow-2xl shadow-blue-40 text-white" class="m-auto p-4 rounded-md bg-blue-200 transition">hover</button>

    <!-- focus -->
    <button data-focus="bg-blue-400 -translate-y-2 -translate-x-2 scale-110 shadow-2xl shadow-blue-40 text-white" class="m-auto p-4 rounded-md bg-blue-200 transition">focus</button>
  </div>
</body>

enter image description here

also make sure to put the script code at the end of the page or inside a DomContentLoaded event


advantages:

  • less repetitive characters to type

enter image description here

more than 25 chars saved (only in your example)

  • multiple line attribute

enter image description here

As you can see you can write your classes in one line,
and the hover logic in another line. making it easy to debug.

  • works out of the box.
    just copy and paste, and call the function.
    with the correct parameter (focus, sm, lg, xl, 2xl) or without any parameter (will be hover)
// just call it at the end of the page
twPseudo();

Upvotes: 4

Blind Spot
Blind Spot

Reputation: 191

For people using react who stumble upon the question, there is a better approach for the following:

const pseudoJoin = (selector, str) => {
  return selector+":"+str.split(" ").join(" "+selector+":")
}

Now you can call it anywhere like:

<div className=`${pseudoJoin('hover','classes you want on hover')} some more classes`>Hello World!</div>

Or when you are using classnames framework:

<div className={ classnames(
   pseudoJoin('hover', 'classes you want on hover'),
  "Other classes here"
)}>Hello World!</div>

Upvotes: -1

Gabe
Gabe

Reputation: 2646

You can just create a new class in a <style> block in your page or template. And then use @apply to use the needed tailwind classes. Like:

<style>
.mybutton {
    @apply m-auto p-4 rounded-md  bg-blue-200 transition
}

.mybutton:hover {
    @apply bg-blue-400 -translate-y-2 -translate-x-2 scale-110 shadow-2xl shadow-blue-400 text-white
}
</style>

Now, if you set the mybutton class on the button, the hover will also work.

You can also add these classes to the main css file of your project. This is not the preferred way of tailwind, though. See Tailwind documentation.

Upvotes: 3

Related Questions