Is this possible? Short of converting all my hover styles into mouseover listeners is it possible to stop a touch device from triggering the CSS hover state?
I have an application that must work on both touch and pointer input, it works great but certain styles applied on hover just don't make sense on touch devices because they tend to retain the hover state indefinitely after a user has tapped an object.
Things to take into account:
Device width bears no correlation with touch enabled devices to me,
the touch screens we are using here are desktop size monitors.
I don't want to force a user to input via touch on a multi-input
device.
I had solved this problem following the approach shared in the link in the comments above. If you're not using it, consider using Modernizr in this scenario. Would like to hear some other approaches as well...
As user, Blender mentions, you can check against touch events like so:
html.touch {
/* Touch Device ~ No Hovers */
}
html.no-touch {
/* Not a Touch is disabled */
}
html.no-touch .element:hover {
opacity:.5;
}
My solution is to add hover-active css class to the HTML tag,
and use it on the beginning of all the CSS selectors with :hover
and remove that class on the first touchstart event.
http://codepen.io/Bnaya/pen/EoJlb
JS:
(function () {
'use strict';
if (!('addEventListener' in window)) {
return;
}
var htmlElement = document.querySelector('html');
function touchStart () {
document.querySelector('html').classList.remove('hover-active');
htmlElement.removeEventListener('touchstart', touchStart);
}
htmlElement.addEventListener('touchstart', touchStart);
}());
HTML:
<html class="hover-active">
CSS:
.hover-active .mybutton:hover {
box-shadow: 1px 1px 1px #000;
}
Related
Just testing out a recent Three.js tutorial # https://tympanus.net/Tutorials/StickyImageEffect/ and I've discovered a few issues that have stumped me while attempting to debug.
Firstly, while testing on an iPad and a couple Smartphones hyperlinks are seemingly active but unresponsive to touch & tap. It seems the "sticky" effect/three.js has total control over the viewport and will not allow touch based devices access to links.
What would need to be augmented to allow the selecting of links and in the process also ignore the triggering of the "sticky" effect when doing so?
Secondly, when viewing on an iPad in landscape orientation there is a small gap at the top of the viewport.
Would this at all be related to the cursor, which is not in use on touch devices?
I would search through the code looking for 'touchstart' and seeing if preventDefault is called. It is.
One solution might be to add your own touchstart handler for <a> tags
Let's test
document.querySelector('#outer').addEventListener('touchstart', (e) => {
e.preventDefault();
});
#outer {
padding: 2em;
background: #EEE;
}
<div id="outer">
is this link touchable
</div>
The code above seems to prevent the link from working.
Adding our own event handler to the links themselves and tell them not to propagate. That way they won't be passed on to the element containing them, the that is calling preventDefault and preventing the default thing (following the link) from happening
document.querySelector('#outer').addEventListener('touchstart', (e) => {
e.preventDefault();
});
document.querySelectorAll('a').forEach((elem) => {
elem.addEventListener('touchstart', stopPropagation);
elem.addEventListener('touchmove', stopPropagation);
elem.addEventListener('touchend', stopPropagation);
});
function stopPropagation(e) {
e.stopPropagation();
}
#outer {
padding: 2em;
background: #EEE;
}
<div id="outer">
is this link touchable
</div>
It seems to work for me.
No idea about the gap. Don't have an iPad to repo and it doesn't seem to repo in the iPad emulation of the Chrome Devtools
i'm currently sitting on an interesting problem:
I have a input type range, rotated by 270deg using the css transform property.
On desktop browsers this works fine but on mobile devices, when i try to use the range fader, the screen is scrolling instead.
My first attempt to fix this was using the inputs focus and blur events to disable the scrolling function of the page, but these events don't seem to be triggered on mobile devices.
Has anyone already dealt with this problem?
I made a plunkr to reproduce the problem:
https://embed.plnkr.co/FrdJZqeB8zqQxjN7zS8u/
If you are not on a mobile browser, just enable the device browser in the top left of the chrome inspector
Thanks
Edit: The -webkit-appearance: slider-vertical; css property is not an option for me because i need css styles applied to my fader: <input type="range"> style not applies to thumb when it is vertical
Edit:
Found a solution that works for me, as thepio proposed:
var element = document.getElementById('range-input');
element.addEventListener('touchmove', function(event){
//event.preventDefault();
});
Interestingly this works only without the event.preventDefault() line
Why not use a vertical slider instead?
input[type=range] {
-webkit-appearance: slider-vertical;
width: 5px;
height: 200px;
}
<input type="range" orient="vertical" id="range-input">
I have a menu that needs to pop up when it is hovered over (and collapse when the cursor is moved outside). However, on touch devices I want it to expand and collapse on 'click', since hover events aren't very useful.
To do that, I use :hover selector, and a backup .clicked class that is applied on touch events. The touchstart handler toggles the .clicked class and uses preventDefault to block the default action (which sets the :hover flag).
It works fine in Chrome's mobile simulator, but on my iPhone the menu ends up having both :hover and .clicked. Why is that happening?
Here's a fiddle: http://jsfiddle.net/rgLodhjg/1/
// html
<div class="test">
</div>
// css
.test {
width: 200px;
height: 100px;
border: 1px solid black;
}
.test:hover:before {
content: "hover";
}
.test.clicked:after {
content: "clicked";
}
// js
$(".test").on("touchstart", function(e) {
$(this).toggleClass("clicked");
e.preventDefault();
return false;
});
You can try this and it will work on iOS9 (I'm not sure about iOS8 and older):
#media (hover: hover) {
.test:hover:before {
content: "hover";
}
}
To support older iOS systems you can use mq4-hover-shim.
You can also use the solution provided by #Simon_Weaver in this post.
By default, hovers are activated on first "tap" in safari. Try leaving the default hover functionality and tapping it, the hover behavior should happen.
I am sitting with an issue where CSS styles don't get removed from an anchor tag when the css class is removed via AJAX, it only happens on a mobile device. This doesn't happen when using a desktop browser.
Have a look here using a mobile device.
You will note that the filters turn red when you select them, but deselecting them doesn't remove the red.
The code that is used there:
$('.tagsContainer .tagsContainerA').click(function () {
vm.alphabet("");
clearAlphabet();
$('.pagination.alphabet .alphabetAll').addClass('currentPage');
if ($(this).hasClass('selected')) {
$(this).removeClass('selected');
}
else {
$(this).addClass('selected');
}
return false;
});
Any ideas what could be causing this on a mobile device?
The problem has to do with the hover, not the click function.
This happens because the hover is triggered in mobile while the element is focused also.
Just add this to your css:
#media screen and (max-width: 768px) {
.places-filter .places-tags li:hover {
background-color: #d1d1d1;
background: #d1d1d1;
}
}
This way you will 'disable' the hover function and only have the click one in mobile.
Another solution is placing the hover effect only in screens bigger than X amount.
Is this CSS or javascript? I just need the div to change to display:none if it comes within say 20px of another div. Thanks
Try this
https://github.com/brandonaaron/jquery-overlaps
//Listen to the event that will be triggered on window resize:
window.onresize = function(event)
{
// test if one element overlaps another
if($('#div1').overlaps('#div2'))
{
//Do stuff, like hide one of the overlapping divs
$('#div1').hide();
}
}
Based on your comment:
Yes it is so that if the user makes their browser window small my site
does not look crowded
Instead of answering the question you asked, Here's an answer to the question you didn't ask:
How to resize/position/cssify page elements based on browser size?
There is a new-ish application of css and javascript called Responsive Web Design. Responsive Design allows you to specify different css rules to apply based on different elements. For a great example of this technique, resize your browser around on The Boston Globe's website. They just integrated this technique sometime this week.
Here's an example of the css that would implement this:
#media screen and (min-width: 480px) {
.content {
float: left;
}
.social_icons {
display: none
}
// and so on...
}
example from http://thinkvitamin.com/design/beginners-guide-to-responsive-web-design/
Here is a boilerplate to get you going.
You can add an event handler that gets fired when the window is resized. You could do this with javascript or jquery. jquery makes it easy:
window.onresize = function(event) {
var h=$(window).height();
var w=$(window).width();
if(h<400 && w < 300){
//hide divs
$('#yourdivid1').hide();
}
}
Hope this helps