Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Only apply hover styles when supported (future) #8394

Merged
merged 2 commits into from May 20, 2022
Merged

Conversation

adamwathan
Copy link
Member

Alternate solution to #7939.

This PR changes how the hover variant works, so that hover styles are only applied on devices that properly support hover.

/* Old CSS */
.hover\:underline:hover {
  text-decoration-line: underline;
}

/* New CSS */
@media (hover: hover) and (pointer: fine) {
  .hover\:underline:hover {
    text-decoration-line: underline;
  }
}

This solves the "sticky hover" problem where tapping something that includes a hover style on mobile will persist that hover style until tapping elsewhere.

This is technically a breaking change because there are likely lots of people building things where they actually depend on hover styles taking effect on mobile on tap, like menus that open on hover.

Because of this, we are putting this change behind a future flag until v4. So by default, nothing will change and you will still get the old hover strategy, but you can opt-in to what will become the default in v4 using the hoverOnlyWhenSupported future flag:

// tailwind.config.js
module.exports = {
  future: {
    hoverOnlyWhenSupported: true,
  },
  // ...
}

If you ever need to use the old hover strategy in a one-off situation while relying on the new strategy more generally, you can still do this using the new arbitrary variants feature that will be shipping in the next release:

<!-- Uses @media (hover: hover) -->
<div class="hover:underline">...</div>

<!-- Uses only the :hover pseudo -->
<div class="[&:hover]:underline">...</div>

Again this will be a breaking change in v4, but only for evil people who were writing code like hidden group-hover:block. Until then, everything will work the same, and you can opt-in to this if you want to start using it now.

adamwathan and others added 2 commits May 20, 2022 11:10
Co-Authored-By: Andrew Brown <browner12@gmail.com>
@adamwathan adamwathan merged commit 128030f into master May 20, 2022
@adamwathan adamwathan deleted the hover-media branch May 20, 2022 15:20
@browner12
Copy link
Contributor

Are all the & additions relevant to this PR? or where they just some cleanup you tacked onto this?

@adamwathan
Copy link
Member Author

Had to make that change in order to make it work, because the new hover needs to specify the & explicitly inside of the format string. So easiest way to make that work was to force all of the internal variants to specify their & as well 👍🏻

@browner12
Copy link
Contributor

Thanks for taking care of this!

I'm definitely one of those evil people using hidden group-hover:block, but we are only using it on LG and up, so we're assuming (i know, i know) these devices have true hover. Below that we use a hamburger and accordion menu.

@kelvinz
Copy link

kelvinz commented May 22, 2022

Wow, I was waiting for this forever. Finally no more hacks to make hover work as intended.

@amrap030
Copy link

Not sure what I am doing wrong but I updated to 3.0.24 and adjusted the config but I still have sticky hover behavior on mobile.

@thecrypticace
Copy link
Contributor

@amrap030 This feature is going into v3.1 which has not yet been released. However, you can test it out today using our insiders build by running npm install tailwindcss@insiders

@ivoelbert
Copy link

We rolled our own way of doing this, but ended up needing a custom no-hover: to complete the picture. Still very nice!

@cossssmin
Copy link
Contributor

Will we be able to turn it off in v4? Or will we have to register our own hover: variant plugin?

It’s going to be a breaking change for Maizzle too and I swear I’m not evil, just that @media isn’t supported everywhere in HTML emails 🙈

@surjithctly
Copy link

surjithctly commented Feb 12, 2023

If I'm creating a hover effect, how do I render it only on hover-enabled devices?

// if hover enabled
<a class="opacity-0 hover:opacity-100"> ... </>

// otherwise do nothing
<a class=""> ... </>

is there any way we can target @media (hover: hover) and (pointer: fine) without writing plugins? similar to supports-[x:y] ?

EDIT: Nevermind.

I can see it is working:

[@media(hover:hover)]:opacity-0

@ShayanTheNerd
Copy link

Alternate solution to #7939.

This PR changes how the hover variant works, so that hover styles are only applied on devices that properly support hover.

/* Old CSS */
.hover\:underline:hover {
  text-decoration-line: underline;
}

/* New CSS */
@media (hover: hover) and (pointer: fine) {
  .hover\:underline:hover {
    text-decoration-line: underline;
  }
}

This solves the ...

@adamwathan Thank you so much. However, I would have really appreciated it if you had added it to the documentation or at least had mentioned it in the 3.1 version update. I've been using this technique so far

/** @type {import('tailwindcss').Config} */

export default {
   theme: {
      extend: {
         screens: {
	    support: { raw: '(hover: hover)' }, // check if hover is supported on the device
         },
      },
   },
};

Which doesn't let you use Max-width and dynamic breakpoints from version 3.2 and also requires you to prefix every hover class with support:.

Anyway, I just found a link to this pull request at a comment to a similar issue, tried it and everything worked just fine! Please add it to the documentation as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

10 participants