Touch device HTML element :hover state - javascript

There is a HTML button, with 3 backgrounds - each for normal, hover and clicked states. Of course, it works fine with non touch device. If the button is clicked on touch device, the :hover state is also triggered and stays until another element is touched.
Is it possible to programmatically remove :hover state from element after it was clicked or prevent it from activating on touch devices?
Sorry, but suggestions to a detect mouseover and mouseout events and add artificial classes are not accepted.
One possible solution is to add "no-touch" class to html element in advance and remove it if only touch device is detected. In that case, CSS selector "html.no-touch button:hover" will not match for touch device.
Do you know more elegant solutions you may suggest?

I would try to overwrite the :hover state in an additional style-sheet for handheld devices like:
<link rel="stylesheet" type="text/css" href="handheld.css" media="handheld">
and in handheld.css put something like:
#some_selector:hover {
background: none; /* if you are setting a background in the main css file for example */
}
However, I´m not sure if handheld and touch screen are completely the same, there might be devices that have a touch screen and are not qualified as a handheld.
Edit: It seems you cannot detect touch screen devices 100% reliably, also see this question.

Seems that this issue can be resolved by overwriting the :hover state for a given element in media query - see this question:
CSS hover not being ignored on touch screen devices

Related

Disable css hover when touch end in touch device

In pure JavaScript, How can I disable the hover effect (of a div or btn ...etc) when user's touch end in touchable devices?
I have some anchors and buttons with effects on hovering, but on touch devices the effect of touch remains visible even after the user takes his finger off the screen.
I don't want the hover effect to be completely removed from touch devices... but what I want is for the hover to end after I stop touching the element.
I tried to play with the touchend in JavaScript but it don't work.
Can anyone help?
:hover is for pointing devices. You shouldn't be trying to optimize it for other types. Here is a definition from mdn:
The :hover CSS pseudo-class matches when the user interacts with an element with a pointing device, but does not necessarily activate it. It is generally triggered when the user hovers over an element with the cursor (mouse pointer).
A wise thing to do to avoid this weird behavior for non-pointing devices, is to apply the hover effect only for those who support it with #media (pointer: fine), like so:
button {
/* Styles for all type of devices */
}
#media (pointer: fine) {
button {
/* Styles for pointing devices */
}
button:hover {
/* Hover effects for pointing devices */
color:red;
}
}

How to prevent mobile keyboard from covering html input

I have a simple web app with a few text inputs and the inputs toward the bottom of the page get covered up by the iPhone keyboard. This is a terrible user experience making it difficult for the user to see what text they are entering as well as selecting other elements on the page after they are done entering text.
Apple documents the behavior here: https://developer.apple.com/library/archive/documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/KeyboardManagement/KeyboardManagement.html
I've seen several posts about this problem and there are multiple solutions for iOS app development but no real solutions for web apps.
I don't have the resources to test on multiple devices and I don't have an android device so I don't know if this problem even occurs there.
Is there a cross platform solution for detecting when a keyboard is covering the UI, how much of the UI is being covered, and an approach to ensure the input is visible?
This answer is a hack; but it's the best solution I have come up with.
Adding a padding to the bottom of the page that is large enough for the keyboard enables content to be displayed as desired when the keyboard is visible.
Using some javascript listeners and a CSS class, this padding can be added only when the keyboard is displayed.
body.keyboard {
height: calc(100% + 500px); /* add padding for keyboard */
}
The following javascript will add and remove the CSS class when an input has focus, which is the closest I can get to figuring out when the keyboard is displayed.
// focus events don't bubble, must use capture phase
document.body.addEventListener("focus", event => {
const target = event.target;
switch (target.tagName) {
case "INPUT":
case "TEXTAREA":
case "SELECT":
document.body.classList.add("keyboard");
}
}, true);
document.body.addEventListener("blur", () => {
document.body.classList.remove("keyboard");
}, true);
It's also worth noting that iOS performs an annoying zoom if the input font size is less that 16px so this is also important.
input {
font-size: 16px !important;
}
Please let me know if you have a better solution.
What about this: stackoverflow: Scroll textfield up when keyboard popsup?
Even if you're not using jquery you could still bind the focus event and scroll the page using the window.scrollTo(0, document.body.scrollHeight); function and just scroll to the bottom. Because interestingly, the space is created, but not scrolled to.
If you want to go fancy, you can check for the window size in order to determine if and how much you want to scroll.
What you can do is hide the keyboard on any click event. So, figure out when you don't want to display a keyboard and when do you really want to show it.
So once figured, you can hide the keyboard like:
InputMethodManager manager = getSystemService(INPUT_METHOD_SERVICE);
manager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(),InputMethodManager.HIDE_NOT_ALWAYS);
Here's an answer that might help you: Scroll textfield up when keyboard popsup
In summary, you can make use of the visual viewport api and update the next render accordingly.
What I did is to scroll the elements into view when focused by touch.
There is no exact api or anything to know if the keyboard is open at all, or how much the keyboard covers (in chrome actually the keyboard reduces the viewport, not overlays on top), but looking at average mobiles, it covers roughly half of it.
As for the implementation, I use a kind of simple heuristic. You can go all-in if the device is a touch device see mobile device detection section here, but this doesn't necessarily cover laptops with touch screens. (and doing it based on resolution is a bad idea also)
I took this "touch device" approach one step forward, and listen on the touchstart event on form elements and set a variable something like hasTouchKeyboard, and then scroll element to top of page (or at least first half that is likely not covered) when focused if this variable is true.
The idea behind it is that the touchstart usually fires before the focused event, plus the real differentiator is that if the user touched the input field, then it is 100% that it is using a touch device AND actually used touch on it (that will likely trigger the keyboard), and not just focused it with mouse on a hybrid device.
It is definitely not bulletproof, but fairly simple and works well without any user agent magic or other crazy stuff.
For www.lokilist.com I needed a solution that worked without javascript for the text input used to enter a Session ID.
On the server, I used the "isMobileDevice()" PHP function found here:
https://stackoverflow.com/a/23874239/20094562
Then attached a css class with onfocus css only if the requesting browser was "mobile" (that function considers tablets as mobile, which is all the better for this purpose since we actually care about touch screens).
To summarize:
Detect touch screens based on user agent with isMobileDevice()
In your css, include a placeholder class like ".mobileTextInput".
Also include in your css the onfocus property of that class like ".mobileTextInput:focus". This is what will reposition your text input when selected.
If the user agent is a mobile device, add the mobileTextInput class to the text elements you want to move above the virtual keyboard.

Pure css for :hover only with mouse

:hovering on a touch screen can be an accessibility problem (dropdowns) or just muck up design elements (changing colour on a button press and not reverting due to the virtual hover).
So I've resolved to having different behaviour when an element is touched and when it is hovered with the mouse. This is easy enough to implement with Javascript and leveraging mousein and mouseout events, and adding a hover class where appropriate. There are two main problems with this:
It's Javascript based which has a number of implications. I wouldn't call not having hover functionality an accessibility issue, as there is a pointer cursor, though.
My main problem is that I will have to manually indicate which elements need the classes added outside of my CSS styling. This is extra work, adds an extra area to make mistakes and isn't semantically nice.
So my question is: is there any pure CSS way to detect if and only if the mouse has hovered over an element? One that doesn't respond to touches.
It is not sufficient to detect if a device is touch capable and remove hover functionality from them. Now that many devices have both mouse and touch, this will hinder a perfectly good mouse-enabled experience.
Method 1: Javascript
Why not start with the body having a .no-touch class on it, and then, using JS, detect the device, and remove the class if the device is mobile.
if(//Code to detect mobile)
$("body").removeClass("no-touch");
Then, in your CSS, code all :hover to be dependent on that parent class.
.no-touch a:hover
{
text-decoration: underline;
}
This will ensure that the hover styles are enabled by default if JS fails, as well as preventing the otherwise long process of delegating each and every element that you want to disable hover for.
The converse of this would be to add a class if the device is mobile, and then code the CSS to exclude the body that has that class:
body:not(.touch) a:hover
{
text-decoration: underline;
}
It's not perfect, as it still requires JS, but there is currently not a known purely-css way to detect touch events as opposed to mouse events, at least as I've been able to find through a somewhat extensive Google search.
Method 2: CSS Media Queries
The other option would be to use media queries, but this still leaves a lot to be desired, as devices continue to get better resolution; some tablets can have screen widths equivalent to some old monitors, and unfortunately, old technology dies very slowly.
This has the advantage of being purely CSS, but has its own pitfalls all the same.
You may have someone using an iPad in landscape # 1024x768 that would be considered a touch device, while an older gentleman is using a desktop on an old 3x2 lcd monitor that has the same resolution: 1024x768
Here's the code though, if you want it:
#media all and (min-width: 1024px)
{
a:hover
{
text-decoration: underline;
}
}
Solution with CSS only, without Javascript
Use media hover with media pointer will help you resolve this issue:
#media (hover: hover) and (pointer: fine) {
a:hover { color: red; }
}

Can't get this CSS transition to properly function on an iPhone

I'm currently working on a CSS transition and I'm struggling to find the proper Javascript to make it function properly on a mobile device.
http://seancrater.com/test/
In the section, "The Dirty Dozen Plus", the transition can be seen. I currently have
ontouchstart="this.classList.toggle('hover');
added to each of the DIVs but it currently requires you to hold down your finger on it from a mobile device to keep it on the transition state. I was wondering if anybody could give me some insight on how to make it a single click to make it stay in the transition state. I tried the pseudo :focus and it stopped it from functioning all together.
Thanks! -Sean
As others have stated, you'll need to avoid :hover.
The easiest way to address your issue is to update your CSS like so:
.top:hover,
.top.touched {
-webkit-transform:translateY(-150px);
-webkit-transition: all .5s;
}
And then add touched as a class to your elements on touchstart or touchend. My guess is you'll want to maintain which element currently is touched, so you can remove the transitioned state when a user scrolls or touches another element.
(EDIT: Updated fiddle to allow user to tap close the element)
http://jsfiddle.net/4n6Z4/1/
Shell, for easier testing on a smartphone:
http://fiddle.jshell.net/4n6Z4/1/show/
ontouchstart="this.classList.toggle('click'); There are no hover events in mobile. You need to turn your hover event into a click event for mobile phones. Use javascript to detect if it's a phone or not. Setup a constant var phone = false and if it's a phone and set it to true and if not it remains false. Then use it in your function that controls / or triggers that animation.
You cannot use :hover on mobile.
more info
As you know, :hover behavior doesn’t exist on touch screen devices. So
when you design a responsive website, you should carefully plan when
and where to use :hover interactions. Simple links that open some URL
will loose their :hover effect on some touch screen devices. On iOS
:hover is triggered before the click event, so you will see the hover
style for a brief moment before the page changes. Those are minor
things, they don’t affect the functionality of the site. The real
problem is a :hover that either hides or shows another element using
display or visibility CSS properties. This type of :hover will
transform into the double tap behavior on touch screens.
http://www.prowebdesign.ro/how-to-deal-with-hover-on-touch-screen-devices/

Android Element Selection Issues

I'm attempting to make my website tablet friendly and I'm facing a strange issue.
I am testing on an Android 4.0 tablet with Chrome 30.
I have a fixed modal popover screen. While this screen is on, we don't want to let the user scroll the background so touch events are prevented. However, in this window we have a scrollable area with overflow:scroll, therefore the touch event is not prevented if the touch start event is detected there. So far so good - Android responsibly scrolls the area as expected.
Problem is, if the user long-presses an element inside the scroll area for about half a second, and only then scrolls - the element where the touch started appears to be selected for a moment. That selection disappears after a bit. But, in case the user scrolls during that bit - the whole page scrolls instead of the scrollable area. It's as if the focus is changed. What's going on?
I tried to set CSS selection rules on the elements inside but it didn't help.
-webkit-touch-callout:none;
-webkit-user-select:none;
-khtml-user-select:none;
-moz-user-select:none;
-ms-user-select:none;
user-select:none;
Every other answer suggests to prevent the touch event which I can't because it's meant to be scrolled. Any ideas what's causing this?
OK, I got it.
Add cursor:default!important to the above CSS rules.
I DID come across such a solution but it failed on first try. In my case, the specificity of elements inside the scrollable area was too strong, rendering cursor:default useless and I didn't realize it. I apply this only to mobile devices by detecting the useragent, therefore I can afford dismissing the previous cursor attribute with !important as it won't affect any desktop clients. Sweet!
Still not sure why this worked. If anyone could supply information on how the cursor attribute affects Chrome on Android I will be grateful.

Categories

Resources