如何防止触摸设备上按钮的粘滞悬停效果
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何防止触摸设备上按钮的粘滞悬停效果相关的知识,希望对你有一定的参考价值。
我创建了一个带有前一个和下一个按钮的旋转木马,它们始终可见。这些按钮具有悬停状态,它们变为蓝色。在触控设备(如iPad)上,悬停状态是粘性的,因此按下按钮后按钮会保持蓝色。我不希望这样。
- 我可以为每个按钮添加一个
no-hover
类ontouchend
,并使我的CSS像这样:button:not(.no-hover):hover { background-color: blue; }
但这可能对性能非常不利,并且不能正确处理Chromebook Pixel(同时具有触摸屏和鼠标)等设备。 - 我可以在
touch
上添加一个documentElement
类,并使我的CSS像这样:html:not(.touch) button:hover { background-color: blue; }
但是这也无法在具有触摸和鼠标的设备上正常工作。
我更喜欢的是删除悬停状态ontouchend
。但这似乎不太可能。聚焦另一个元素不会消除悬停状态。手动点击另一个元素,但我似乎无法在javascript中触发它。
我发现的所有解决方案似乎都不完美。有完美的解决方案吗?
您可以通过暂时从DOM中删除链接来删除悬停状态。见http://testbug.handcraft.com/ipad.html
在CSS中你有:
:hover {background:red;}
在JS中你有:
function fix()
{
var el = this;
var par = el.parentNode;
var next = el.nextSibling;
par.removeChild(el);
setTimeout(function() {par.insertBefore(el, next);}, 0)
}
然后在你的HTML中你有:
<a href="#" ontouchend="this.onclick=fix">test</a>
将此JS代码添加到您的页面:
document.body.className = 'ontouchstart' in document.documentElement ? '' : 'hover';
现在在你的CSS之前每次悬停添加像这样的悬停类:
.hover .foo:hover {}
如果设备是触摸的,则body类将为空,否则其类将悬停并应用规则!
我可以为每个按钮添加一个无悬停类ontouchend,并使我的CSS像> this:button:not(.no-hover):hover {background-color:blue;但这可能对性能非常不利,并且无法正确处理Chromebook Pixel(同时具有触摸屏和鼠标)等设备。
这是正确的起点。下一步:对以下事件应用/删除nohover类(使用jQuery演示)
buttonelement
.on("touchend touchcancel",function(){$(this).addClass("nohover")})
.on("touchstart mouseover",function({$(this).removeClass("nohover")});
注意:如果您希望将其他类应用于buttonelement,则CSS中的not(.nohover)将不再按预期工作。比你必须添加一个单独的定义与默认值和!important标签来覆盖悬停样式:.nohover {background-color:white!important}
这甚至可以正确处理Chromebook Pixel(同时具有触摸屏和鼠标)等设备!我不认为,这是一个主要的性能杀手......
一个对我有用的解决方案:
html {
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
将此代码添加到样式表中。
我想摆脱点击链接时ios Safari上出现的灰色背景。但它似乎做得更多。现在点击一个按钮(带有:hover
伪类!)立即打开!我只是在iPad上测试过,我不知道它是否适用于其他设备。
我想我找到了一个类似问题的优雅(最小js)解决方案:
使用jQuery,您可以使用.mouseover()
触发悬停在body(或任何其他元素)上
所以我只是将这个处理程序附加到元素的ontouchend
事件中,如下所示:
var unhover = function() {
$("body").mousover();
};
.hoverable {
width: 100px;
height: 100px;
background: teal;
cursor: pointer;
}
.hoverable:hover {
background: pink;
}
<div class="hoverable" ontouchend={unhover}></div>
这是我在研究其余答案后到目前为止所提出的。它应该能够支持仅触摸,仅鼠标或混合用户。
为悬停效果创建单独的悬停类。默认情况下,将此悬停类添加到我们的按钮。
我们不希望检测触摸支持的存在并从一开始就禁用所有悬停效果。正如其他人所提到的,混合设备越来越受欢迎;人们可能有触摸支持,但想要使用鼠标,反之亦然。因此,仅在用户实际触摸按钮时删除悬停类。
接下来的问题是,如果用户想要在触摸按钮后返回使用鼠标怎么办?要解决这个问题,我们需要找到一个适当的时机来添加我们已删除的悬停类。
但是,我们无法在删除它后立即将其添加回来,因为悬停状态仍处于活动状态。我们可能也不想破坏和重新创建整个按钮。
所以,我想过使用忙等待算法(使用setInterval)来检查悬停状态。一旦停用悬停状态,我们就可以添加回悬停类并停止忙等待,使我们回到用户可以使用鼠标或触摸的原始状态。
我知道忙碌的等待不是很好,但我不确定是否有适当的事件。我考虑过将它添加回mouseleave事件,但它不是很强大。例如,当触摸按钮后弹出警报时,鼠标位置会移动但不会触发mouseleave事件。
var button = document.getElementById('myButton');
button.ontouchstart = function(e) {
console.log('ontouchstart');
$('.button').removeClass('button-hover');
startIntervalToResetHover();
};
button.onclick = function(e) {
console.log('onclick');
}
var intervalId;
function startIntervalToResetHover() {
// Clear the previous one, if any.
if (intervalId) {
clearInterval(intervalId);
}
intervalId = setInterval(function() {
// Stop if the hover class already exists.
if ($('.button').hasClass('button-hover')) {
clearInterval(intervalId);
intervalId = null;
return;
}
// Checking of hover state from
// http://stackoverflow.com/a/8981521/2669960.
var isHovered = !!$('.button').filter(function() {
return $(this).is(":hover");
}).length;
if (isHovered) {
console.log('Hover state is active');
} else {
console.log('Hover state is inactive');
$('.button').addClass('button-hover');
console.log('Added back the button-hover class');
clearInterval(intervalId);
intervalId = null;
}
}, 1000);
}
.button {
color: green;
border: none;
}
.button-hover:hover {
background: yellow;
border: none;
}
.button:active {
border: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id='myButton' class='button button-hover'>Hello</button>
您可以在:active
状态下设置背景颜色,并为:focus
提供defaut背景。
如果你通过onfocus/ontouch
设置背景颜色,一旦:focus
状态消失,颜色样式仍然存在。
您需要重置onblur
以便在焦点丢失时恢复defaut bg。
这对我有用:将悬停样式放在一个新类中
.fakehover {background: red}
然后在需要时添加/删除类
$(".someclass > li").on("mouseenter", function(e) {
$(this).addClass("fakehover");
});
$(".someclass > li").on("mouseleave", function(e) {
$(this).removeClass("fakehover");
});
重复touchstart和touchend事件。或者您喜欢的任何事件以获得所需的结果,例如我希望在触摸屏上切换悬停效果。
根据Darren Cooks的答案,如果你将手指放在另一个元素上,这个答案也会有效。
见Find element finger is on during a touchend event
jQuery(function() {
FastClick.attach(document.body);
});
// Prevent sticky hover effects for buttons on touch devices
// From https://stackoverflow.com/a/17234319
//
//
// Usage:
// <a href="..." touch-focus-fix>..</a>
//
// Refactored from a directive for better performance and compability
jQuery(document.documentElement).on('touchend', function(event) {
'use strict';
function fix(sourceElement) {
var el = $(sourceElement).closest('[touch-focus-fix]')[0];
if (!el) {
return;
}
var par = el.parentNode;
var next = el.nextSibling;
par.removeChild(el);
par.insertBefore(el, next);
}
fix(event.target);
var changedTouch = event.originalEvent.changedTouches[0];
// http://www.w3.org/TR/2011/WD-touch-events-20110505/#the-touchend-event
if (!changedTouch) {
return;
}
var touchTarget = document.elementFromPoint(changedTouch.clientX, changedTouch.clientY);
if (touchTarget && touchTarget !== event.target) {
fix(touchTarget);
}
});
你可以试试这种方式。
JavaScript的:
var isEventSupported = function (eventName, elementName) {
var el = elementName ? document.createElement(elementName) : window;
eventName = 'on' + eventName;
var isSupported = (eventName in el);
if (!isSupported && el.setAttribute) {
el.setAttribute(eventName, 'return;');
isSupported = typeof el[eventName] == 'function';
}
el = null;
return isSupported;
};
if (!isEventSupported('touchstart')) {
$('a').addClass('with-hover');
}
CSS:
a.with-hover:hover {
color: #fafafa;
}
到目前为止我在我的项目中做的是恢复触摸设备上的:hover
更改:
.myhoveredclass {
以上是关于如何防止触摸设备上按钮的粘滞悬停效果的主要内容,如果未能解决你的问题,请参考以下文章