모바일 브라우저에서 호버 효과 비활성화


113

저는 데스크톱과 태블릿 모두에서 사용되는 웹 사이트를 작성하고 있습니다. 데스크톱에서 방문 할 때 화면의 클릭 가능한 영역이 :hover효과 (다른 배경색 등) 로 밝게 표시되기를 원합니다 . 태블릿을 사용하면 마우스가 없으므로 호버 효과를 원하지 않습니다.

문제는 내가 태블릿에서 무언가를 탭할 때 브라우저에 분명히 내가 탭한 위치로 이동 한 다음 그대로 두는 일종의 "보이지 않는 마우스 커서"가 있다는 것입니다. 그래서 방금 탭한 것은 다른 것을 탭할 때까지 호버 효과.

마우스를 사용할 때 호버 효과를 얻고 터치 스크린을 사용할 때는 어떻게 억제 할 수 있습니까?

누군가가 제안 할 생각이라면 사용자 에이전트 스니핑을 사용하고 싶지 않습니다. 동일한 장치에 터치 스크린과 마우스가 모두있을 수 있습니다 (현재는 흔하지 않을 수 있지만 앞으로는 훨씬 더 많음). 나는 장치에 관심이없고 현재 사용되고있는 방법 (마우스 또는 터치 스크린)에 관심이 있습니다.

난 이미 접선 시도 touchstart, touchmovetouchend이벤트 및 호출 preventDefault()억제은 "보이지 않는 마우스 커서"시간의 일부를 수행하는, 그들 모두에; 그러나 두 개의 다른 요소 사이를 빠르게 앞뒤로 두드리면 몇 번 탭하면 "마우스 커서"가 움직이기 시작하고 어쨌든 호버 효과가 켜집니다. 내가 preventDefault항상 영광스럽지 않은 것처럼 보입니다 . 필요한 경우가 아니면 세부 사항을 알려주지 않을 것입니다. 이것이 올바른 접근 방식인지 확신 할 수 없습니다. 더 간단한 방법이 있다면 나는 모두 귀입니다.


편집 : 이것은 bog-standard CSS로 재현 할 수 :hover있지만, 여기에 참조를위한 빠른 재현이 있습니다.

<style>
  .box { border: 1px solid black; width: 150px; height: 150px; }
  .box:hover { background: blue; }
</style>
<div class="box"></div>
<div class="box"></div>

상자 중 하나에 마우스를 가져 가면 파란색 배경이 표시됩니다. 그러나 상자 중 하나를 탭하면 파란색 배경도 표시됩니다. 이것이 제가 방지하려는 것입니다.

위의 작업을 수행하고 jQuery의 마우스 이벤트를 연결 하는 샘플도 여기에 게시했습니다 . 또한 화재 것이다 탭 이벤트를 참조하는 데 사용할 수 있습니다 mouseenter, mousemove하고 mouseleave.


7
@Blender, 질문을 읽었습니까? 사용자 에이전트 스니핑이 잘못된 선택 인 이유를 이미 설명했습니다.
Joe White

조, 이것에 대한 해결책을 찾았습니까?
Ismatjon 2014-07-02

나는 이런 종류의 질문을 찾고 있었는데, 그것을 발견해서 다행이다!
agpt

모바일뿐만 아니라 터치 지원 장치에서 마우스 오버를 비활성화하는 문제를 다루는이 질문도 참조하십시오. stackoverflow.com/questions/23885255/…
blade

답변:


83

나는 당신의 질문에서 당신의 호버 효과가 당신의 페이지의 내용을 변경한다는 것을 받아들입니다. 이 경우 내 조언은 다음과 같습니다.

  • touchstart및에 호버 효과를 추가합니다 mouseenter.
  • mouseleave, touchmove및 에서 마우스 오버 효과를 제거합니다 click.

또는 콘텐츠 변경이없는 페이지를 편집 할 수 있습니다.

배경

마우스를 시뮬레이션하기 위해 Webkit 모바일과 같은 브라우저는 사용자가 터치 스크린 (예 : iPad)에서 손가락을 뗀 경우 다음 이벤트를 발생시킵니다 (출처 : html5rocks.com의 Touch And Mouse ).

  1. touchstart
  2. touchmove
  3. touchend
  4. 300ms 지연, 브라우저는 이것이 두 번 탭이 아니라 한 번 탭인지 확인합니다.
  5. mouseover
  6. mouseenter
    • 참고 하십시오 경우 mouseover, mouseenter또는 mousemove이벤트 페이지 내용을 변경, 다음 이벤트가 실행되지 않습니다.
  7. mousemove
  8. mousedown
  9. mouseup
  10. click

단순히 웹 브라우저에 마우스 이벤트를 건너 뛰도록 지시하는 것은 불가능 해 보입니다.

더 나쁜 것은 마우스 오버 이벤트가 페이지 콘텐츠를 변경하는 경우 Safari 웹 콘텐츠 가이드-이벤트 처리 , 특히 One-Finger 이벤트의 그림 6.4에 설명 된대로 클릭 이벤트가 발생하지 않는다는 것 입니다. 정확히 "컨텐츠 변경"은 브라우저와 버전에 따라 다릅니다. iOS 7.0의 경우 배경색 변경은 콘텐츠 변경이 아닙니다 (또는 더 이상 변경되지 않습니까?).

솔루션 설명

요약하자면:

  • touchstart및에 호버 효과를 추가합니다 mouseenter.
  • mouseleave, touchmove및 에서 마우스 오버 효과를 제거합니다 click.

에 대한 작업이 없습니다 touchend.

이 명확하게 마우스 이벤트 작동 : mouseentermouseleave(약간의 버전을 개선 mouseover하고 mouseout) 해고하고, 추가하고 호버를 제거합니다.

사용자가 실제로 click링크 된 경우 호버 효과도 제거됩니다. 이렇게하면 사용자가 웹 브라우저에서 뒤로 버튼을 누르면 제거됩니다.

이것은 터치 이벤트에서도 작동합니다. 터치 스타트시 호버 효과가 추가됩니다. 터치 엔드에서 제거되지는 않습니다. 에 다시 추가 mouseenter되고 이로 인해 콘텐츠 변경이 발생하지 않으므로 (이미 추가됨) click이벤트도 실행되고 사용자가 다시 클릭 할 필요없이 링크를 따라갑니다!

브라우저가 touchstart이벤트 사이에 발생하는 300ms 지연은 click이 짧은 시간 동안 호버 효과가 표시되기 때문에 실제로 유용하게 사용됩니다.

사용자가 클릭을 취소하기로 결정한 경우 손가락을 움직여도 정상적으로 수행됩니다. 일반적으로 이것은 mouseleave이벤트가 발생 하지 않고 호버 효과가 제자리에 남아 있기 때문에 문제 입니다. 고맙게도에서 호버 효과를 제거하면 쉽게 해결할 수 있습니다 touchmove.

그게 다야!

예를 들어 FastClick 라이브러리 를 사용하여 300ms 지연을 제거 할 수 있지만 이는이 질문의 범위를 벗어납니다.

대체 솔루션

다음 대안에서 다음과 같은 문제를 발견했습니다.

  • 브라우저 감지 : 오류가 매우 발생하기 쉽습니다. 장치에 마우스 또는 터치가 있고 두 가지의 조합이 터치 디스플레이가 번식 할 때 점점 더 보편화 될 것이라고 가정합니다.
  • CSS 미디어 감지 : 내가 아는 유일한 CSS 전용 솔루션입니다. 여전히 오류가 발생하기 쉬우 며 장치에 마우스 또는 터치가 있다고 가정하지만 둘 다 가능합니다.
  • 클릭 이벤트 에뮬레이션 touchend: 사용자가 실제로 링크를 클릭 할 의도없이 스크롤 또는 확대 / 축소 만 원하더라도 링크를 잘못 따라갑니다.
  • 변수를 사용하여 마우스 이벤트 억제 : 이는 touchend해당 시점에서 상태 변경을 방지하기 위해 후속 마우스 이벤트에서 if 조건으로 사용되는 변수를 설정합니다 . 변수는 클릭 이벤트에서 재설정됩니다. 이 페이지에서 Walter Roman의 답변을 참조하십시오. 터치 인터페이스에서 호버 효과를 원하지 않는 경우 적합한 솔루션입니다. 안타깝게도 touchend다른 이유로 a 가 실행되고 클릭 이벤트가 실행되지 않고 (예 : 사용자가 스크롤하거나 확대 / 축소 된) 마우스로 링크를 따라 가려는 경우 (예 : 마우스와 터치 인터페이스가 모두있는 장치에서) 작동하지 않습니다. ).

추가 읽기


1
좋은 대답입니다. 나는 당신의 바이올린을 사용하여 내 자신의 솔루션을 만들기 시작했습니다. 그러나 때때로 터치 엔드가 필요합니다. (A하는 TouchMove가 실행되지 않을 때 - 즉 때 문서 자체 오프 사용자의 이동 ...)
Agamemnus

멋진 대답이 있지만 대부분의 경우 내가 사용하는 것이 좋습니다 것 touchend 대신touchstart사용자가 시도 할 때 즉시 트리거링 동작을 방지하기 위해 대부분의 경우에 스 와이프 스크롤 또는 페이지 아래로. 여전히 발생하지만, 방해 또는 혼동 가능성이 적습니다 것인가 (가 아닌 사용자가 일어난 알 필요가 무엇인가 레이블을 표시처럼의 뭔가 무해한 가정)
user56reinstatemonica8을

19

마우스를 사용할 때 호버 효과를 얻고 터치 스크린을 사용할 때는 어떻게 억제 할 수 있습니까?

터치 스크린에 대한 호버 효과를 억제하는 것이 아니라 마우스 이벤트에 대한 호버 효과를 추가하는 것으로 생각하지 않을 수도 있습니다.

:hoverCSS에 효과 를 유지하려면 미디어마다 다른 스타일을 지정할 수 있습니다.

@media screen { /* hover styles here */ } 

@media handheld { /* non-hover styles here */ }

불행히도 이것을 무시하고 화면 규칙을 사용하는 모바일 장치가 많이 있다는 점을 제외하고는. 다행히도 많은 최신 모바일 / 태블릿 브라우저가 더 멋진 미디어 쿼리를 지원합니다.

@media screen and (max-width:800px) { /* non-hover styles here */ }

따라서 "screen"또는 "handheld"부분이 무시 되더라도 "max-width"가 트릭을 수행합니다. 800 픽셀 미만의 화면을 가진 모든 것은 태블릿이나 휴대폰이어야하며 호버 효과를 사용하지 않아야한다고 가정 할 수 있습니다. 저해상도 장치에서 마우스를 사용하는 드문 사용자에게는 호버 효과가 나타나지 않지만 그렇지 않으면 사이트가 괜찮을 것입니다.

미디어 쿼리에 대한 추가 정보? 온라인에 대한 많은 기사가 있습니다-여기 하나가 있습니다 : http://www.alistapart.com/articles/return-of-the-mobile-stylesheet

호버 효과를 CSS에서 옮기고 JavaScript로 적용하면 마우스 이벤트에 구체적으로 바인딩 할 수 있고 / 또는 다시 화면 크기에 따라 몇 가지 가정을 할 수 있으며 최악의 경우 "문제"가 일부 마우스를 사용하는 사용자는 호버 효과를 놓칩니다.


마우스 이벤트에만 호버 효과를 추가하고 싶습니다. 그러나 터치 이벤트 마우스 이벤트를 에뮬레이트 합니다. 터치 이벤트를 연결하고 호출 preventDefault()하면 때때로 마우스 이벤트를 억제하지만 내 질문에서 말했듯이 신뢰할 수 없습니다.
Joe White

6
미디어 쿼리에 관해서는 Windows 8이 나오고 PC에 터치 스크린 마우스 가 모두 있으면 어떻게됩니까 ? 사용자가 마우스를 가져 가면 마우스 커서가 표시되고 마우스 오버 효과를 원합니다. 터치 스크린으로 탭하면 호버 효과를 원하지 않습니다. 하지만 터치와 마우스의 차이를 감지하는 신뢰할 수있는 방법을 찾지 못했습니다.
Joe White

아마도 브라우저 개발자는 터치와 마우스를 사용하는 장치에 더 많은 사용자가 있으면보다 일관된 탐지를 수행하도록 동기를 부여 할 것입니다. 하지만 지금은? 화면 크기를 기준으로 추측을 할 것이지만 다른 답변에는 다른 조언이 있습니다. 더 이상 도와 드릴 수 없어서 죄송합니다.
nnnnnn

9

터치시 나타나지 않아야하는 호버 효과가있는 데스크톱 / 모바일 / 태블릿 사이트 인 최근 프로젝트를 위해 다음 JS를 작성했습니다.

mobileNoHoverState모듈 아래 가변 가진다 preventMouseover(초기 선언 false로 설정 됨), true사용자가 발사 될 때 touchstart요소에 이벤트를 $target.

preventMouseover그런 다음 이벤트가 시작될 false때마다 다시 설정 mouseover되므로 사용자가 터치 스크린과 마우스를 모두 사용하는 경우 사이트가 의도 한대로 작동 할 수 있습니다.

에서 선언되는 순서 때문에 mouseover이후에 트리거되는 것을 알고 touchstart있습니다 init.

var mobileNoHoverState = function() {

    var hoverClass = 'hover',
        $target = $(".foo"), 
        preventMouseover = false;

    function forTouchstart() {
        preventMouseover = true;
    }

    function forMouseover() {
        if (preventMouseover === false) {
            $(this).addClass(hoverClass);
        } else {
            preventMouseover = false;
        }
    }

    function forMouseout() {
        $(this).removeClass(hoverClass);
    }

    function init() {
        $target.on({
            touchstart  : forTouchstart,
            mouseover   : forMouseover,
            mouseout    : forMouseout
        });                
    }

    return {
        init: init
    };
}();

그런 다음 모듈은 라인 아래로 더 인스턴스화됩니다.

mobileNoHoverState.init();

"preventMouseover는 mouseover 이벤트가 발생할 때마다 다시 true로 설정되므로 사용자가 터치 스크린과 마우스를 모두 사용하는 경우 사이트가 의도 한대로 작동 할 수 있습니다." -당신의 코드는 그렇게하지 않습니다. 내가 뭔가를 놓치고 있습니까?
Redtopia 2014

@Redtopia 헤드 업 주셔서 감사합니다! 빠진 코드로 답변을 업데이트했습니다.
Walter Roman

당신은 함수 선언 이후에 세미콜론이 필요하지 않습니다
나쵸 리브레

@nacholibre 적절한 세미콜론의 사용은 장소에 넣어왔다
월터 로마

6

css내 모든 견해에 무거운 자바 스크립트 솔루션을 뿌리는 것이 불쾌한 옵션처럼 보였기 때문에 나는 이것에 대한 순수한 솔루션을 정말로 원했습니다 . 마지막으로 @ media.hover 쿼리를 발견했습니다.이 쿼리는 "기본 입력 메커니즘이 사용자가 요소 위로 마우스를 가져갈 수 있는지 여부"를 감지 할 수 있습니다. 이것은 "호버링"이 입력 장치의 직접적인 기능보다 에뮬레이트 된 동작에 더 가까운 터치 장치를 피합니다.

예를 들어 링크가있는 경우 :

<a href="/" class="link">Home</a>

그런 다음 :hover장치가 다음과 같이 쉽게 지원할 때만 안전하게 스타일을 지정할 수 있습니다 css.

@media (hover: hover) {
  .link:hover { /* hover styles */ }
}

대부분의 최신 브라우저는 상호 작용 미디어 기능 쿼리를 지원하지만 IE 및 Firefox와 같은 일부 인기 브라우저는 지원 하지 않습니다. 제 경우에는 데스크톱에서 Chrome을 지원하고 모바일에서 Chrome 및 Safari를 지원할 계획 이었기 때문에 제대로 작동합니다.


Chrome devtools에서 기기를 에뮬레이션 할 때 작동하는 것처럼 보이는 멋진 솔루션입니다. 하지만 여전히 Chrome Android에서는 작동하지 않습니다. :-(
Sjeiti

이것이 가장 편리하고 올바른 해결책이라고 생각합니다. 곧 W3C 표준에 추가되기를 바랍니다.
GProst

5

내 해결책은 hover-active css 클래스를 HTML 태그에 추가하고 모든 CSS 선택기의 시작 부분에서 : hover로 사용하고 첫 번째 touchstart 이벤트에서 해당 클래스를 제거하는 것입니다.

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;
}

터치 이벤트를 수신하는 대신 'ontouchstart' in window. 예if ('ontouchstart' in window) document.querySelector('html').classList.remove('hover-active');
Yuval A.

@YuvalA. 내가 터치 이벤트를 기다리는 이유는 포인터와 터치를 지원하는 장치가 있고 사용자가 포인터를 사용하여 마우스 오버를 제거하고 싶지 않기 때문입니다. 사용자가 터치와 포인터를 사용할 가능성이 있지만 그것에 대해 할 일이별로 없습니다
Bnaya

2

동일한 문제를 해결하기 위해 내가 한 일은 기능 감지 ( 이 코드 와 같은 것을 사용)를 사용하여 onTouchMove가 정의되었는지 확인하고, 그렇다면 CSS 클래스 "touchMode"를 본문에 추가하고 그렇지 않으면 " desktopMode ".

그런 다음 일부 스타일 효과가 터치 장치에만 적용되거나 데스크톱에만 적용될 때마다 css 규칙이 적절한 클래스와 함께 추가됩니다.

.desktopMode .someClass:hover{ color: red }
.touchMode .mainDiv { width: 100%; margin: 0; /*etc.*/ }

편집하다 : 물론이 전략은 CSS에 몇 가지 추가 문자를 추가하므로 CSS 크기가 걱정된다면 touchMode 및 desktopMode 정의를 검색하여 다른 파일에 넣어 각 장치에 최적화 된 CSS를 제공 할 수 있습니다. 유형; 또는 찌르기 전에 클래스 이름을 훨씬 더 짧은 이름으로 변경할 수 있습니다.


2

맞아요, 비슷한 문제가 있었지만 미디어 쿼리와 간단한 CSS로 해결했습니다. 나는 여기서 몇 가지 규칙을 위반하고 있다고 확신하지만 그것은 나를 위해 일하고 있습니다.

나는 기본적으로 누군가가 만든 방대한 애플리케이션을 가져와 반응 형으로 만들어야했다. 그들은 jQueryUI를 사용하고 jQuery를 조작하지 말라고 요청했기 때문에 CSS 만 사용하도록 제한되었습니다.

터치 스크린 모드에서 버튼 중 하나를 눌렀을 때 버튼의 동작이 적용되기 전에 1 초 동안 호버 효과가 발생했습니다. 해결 방법은 다음과 같습니다.

@media only screen and (max-width:1024px) {

       #buttonOne{
            height: 44px;
        }


        #buttonOne:hover{
            display:none;
        }
}   

2

내 프로젝트에서 우리는 https://www.npmjs.com/package/postcss-hover-prefixhttps://modernizr.com/을 사용하여이 문제를 해결했습니다. 먼저 출력 css 파일을 postcss-hover-prefix. .no-touch모든 CSS hover규칙에 추가 됩니다.

const fs = require("fs");
const postcss = require("postcss");
const hoverPrfx = require("postcss-hover-prefix");

var css = fs.readFileSync(cssFileName, "utf8").toString();
postcss()
   .use(hoverPrfx("no-touch"))
   .process(css)
   .then((result) => {
      fs.writeFileSync(cssFileName, result);
   });

CSS

a.text-primary:hover {
  color: #62686d;
}

된다

.no-touch a.text-primary:hover {
  color: #62686d;
}

런타임에 다음 과 같은 태그에 ModernizrCSS 클래스를 자동으로 추가 html합니다.

<html class="wpfe-full-height js flexbox flexboxlegacy canvas canvastext webgl 
  no-touch 
  geolocation postmessage websqldatabase indexeddb hashchange
  history draganddrop websockets rgba hsla multiplebgs backgroundsize borderimage
  borderradius boxshadow textshadow opacity cssanimations csscolumns cssgradients
  cssreflections csstransforms csstransforms3d csstransitions fontface
  generatedcontent video audio localstorage sessionstorage webworkers
  applicationcache svg inlinesvg smil svgclippaths websocketsbinary">

이러한 CSS와 Modernizr의 사후 처리는 터치 장치에 대한 호버를 비활성화하고 다른 장치에 대해서는 활성화합니다. 실제로이 접근 방식은 Bootstrap 4에서 영감을 받아 동일한 문제를 해결하는 방법 : https://v4-alpha.getbootstrap.com/getting-started/browsers-devices/#sticky-hoverfocus-on-mobile


1

mouseLeave터치 스크린에서 요소를 터치 할 때마다 이벤트 를 트리거 할 수 있습니다 . 다음은 모든 <a>태그에 대한 솔루션입니다 .

function removeHover() {
    var anchors = document.getElementsByTagName('a');
    for(i=0; i<anchors.length; i++) {
        anchors[i].addEventListener('touchstart', function(e){
            $('a').mouseleave();
        }, false);
    }
}

JSHint는 "루프 내에서 함수를 만들지 마십시오"라고 말합니다.
NetOperator Wibby

해킹입니다. 좋은 습관으로 간주 할 수있는 재사용 가능한 코드가 아닙니다. @NetOperatorWibby
사이드 Kholov

좋은 습관으로 간주 할 수없는 코드를 게시하는 것은 실제로 도움이되지 않습니다. 그것은 칼에 상처를 입은 반창고를 두는 것과 같습니다.
NetOperator Wibby

1

Iv는 문제에 대한 두 가지 해결책을 찾았습니다. 이는 modernizr 또는 다른 것으로 터치를 감지하고 html 요소에 터치 클래스를 설정한다는 것을 의미합니다.

이것은 좋지만 잘 지원 되지는 않습니다 .

html.touch *:hover {
    all:unset!important;
}

하지만 이것은 아주 좋은 지원이 있습니다 .

html.touch *:hover {
    pointer-events: none !important;
}

나를 위해 완벽하게 작동합니다. 버튼을 터치하면 모든 호버 효과가 켜지지 만 마우스 이벤트의 초기 호버 효과로 버그가 발생하지 않습니다.

노터치 장치에서 터치 감지 modernizr가 최고의 작업을 수행했다고 생각합니다.

https://github.com/Modernizr/Modernizr/blob/master/feature-detects/touchevents.js

편집하다

이 문제에 대한 더 좋고 간단한 해결책을 찾았습니다.

클라이언트가 터치 장치인지 확인하는 방법


0

다소 이상한 문제처럼 들리므로 CSS를 보는 것이 도움이 될 수 있습니다. 그러나 어쨌든, 그것이 일어나고 다른 모든 것이 좋다면 호버 효과를 javascript로 바꿀 수 있습니다 (jquery도 사용할 수 있습니다). 간단히 mouseover 또는 더 나은 mouseenter 이벤트에 바인딩하고 이벤트가 발생하면 요소를 켜십시오.

여기에서 마지막 예제를 확인하십시오 : http://api.jquery.com/mouseover/ , 이벤트가 발생했을 때 기록하는 것과 유사한 것을 사용하여 거기에서 가져올 수 있습니다!


CSS에 특별한 것은 없습니다. 내 편집을 참조하십시오. 그리고 나는 이미 시도했다 mouseenter; 주사위가 없습니다. 탭하면 "보이지 않는 마우스 커서"가 이동하므로 mouseentermousemove( mouseleave다른 곳을 탭할 때) 트리거됩니다 .
Joe White

0

JavaScript를 사용하는 것이 만족 스러우면 페이지에서 Modernizr 를 사용할 수 있습니다 . 페이지가로드되면 비 터치 스크린 브라우저에는 html 태그에 '.no-touch'클래스가 추가되지만 터치 스크린 브라우저의 경우 html 태그에는 html 태그에 '.touch'클래스가 추가됩니다. .

그런 다음 mouseenter 및 mouseleave 리스너를 추가하기로 결정하기 전에 html 태그에 no-touch 클래스가 있는지 확인하는 경우입니다.

if($('html').hasClass('no-touch')){
    $('.box').on("mouseenter", function(event){
            $(this).css('background-color','#0000ff')
    });
    $('.box').on("mouseleave", function(event){
            $(this).css('background-color','')
    });
}

터치 스크린 장치의 경우 이벤트에 리스너가 없으므로 탭할 때 호버 효과가 없습니다.


그것은 CSS를 해달라고 사용 자바 스크립트 (JQuery와)과 함께 컴퓨터 전원의 자사의 폐기물을 수행 할 수 있습니다 때
사이먼 Dragsbæk

1
더 간단하지만 CSS에서 .touch및에 대한 별도의 규칙을 정의 할 수 .no-touch있습니다. OP가 모바일 s 를 피하려고하기 때문에 Modernizer와 함께 CSS에서 답변을 다시 작성 html.no-touch .box:hover {background-color: "#0000ff"}하고에 대한 아무것도 정의 html.touch .box:hover하지 않는 것이 트릭을 수행해야합니다 :hover.
Walter Roman

0

최근에 한 프로젝트에서 jQuery의 위임 된 이벤트 기능으로이 문제를 해결했습니다. jQuery 선택기를 사용하여 특정 요소를 찾고 마우스가 요소 위에있을 때 해당 요소에 CSS 클래스를 추가 / 제거합니다. Windows 8을 실행하는 터치 지원 노트북의 IE10을 포함하여 테스트 할 수있는 한 잘 작동하는 것 같습니다.

$(document).ready(
    function()
    {
        // insert your own selector here: maybe '.hoverable'?
        var selector = 'button, .hotspot';

        $('body')
            .on('mouseover', selector, function(){ $(this).addClass('mouseover');    })
            .on('mouseout',  selector, function(){ $(this).removeClass('mouseover'); })
            .on('click',     selector, function(){ $(this).removeClass('mouseover'); });
    }
);

편집 : 물론이 솔루션은 ": hover"선택기를 제거하기 위해 CSS를 변경하고 "hoverable"요소를 미리 고려할 것을 요구합니다.

페이지에 많은 요소 (예 : 수천 개)가있는 경우이 솔루션 은 페이지의 모든 요소 에서 세 가지 유형의 이벤트를 포착 하고 선택기가 일치하면 해당 작업을 수행 하기 때문에 약간 느려질 수 있습니다 . 나는 ".hover"를 쓴 CSS 리더가 ": hover"를 읽지 않기를 원했기 때문에 CSS 클래스를 "hover"대신 "mouseover"로 명명했습니다.


0

내 해결책은 다음과 같습니다. http://jsfiddle.net/agamemnus/g56aw709/-- 아래 코드.

": hover"를 ".hover"로 변환하기 만하면됩니다. 그게 다입니다! 이것과 나머지의 큰 차이점은 .NET과 같은 비단 수 요소 선택자에서도 작동한다는 것 .my_class > *:hover {입니다.

handle_css_hover_effects ()

function handle_css_hover_effects (init) {
 var init = init || {}
 var handle_touch_events = init.handle_touch_events || true
 var handle_mouse_events = init.handle_mouse_events || true
 var hover_class         = init.hover_class         || "hover"
 var delay_preferences   = init.delay_preferences   || {touch: {add: 500, remove: 500}}
 function default_handler (curobj, input_type, op) {
  var hovered_element_selector = "*" + ((op == "add") ? ":" : ("." + hover_class))
  var hovered_elements = Array.prototype.slice.call(document.body.querySelectorAll(hovered_element_selector))
  var modified_list = []
  while (true) {
   if ((curobj == null) || (curobj == document.documentElement)) break
   if (hovered_elements.indexOf(curobj) != -1) modified_list.push (curobj)
   curobj = curobj.parentNode
  }
  function do_hover_change () {modified_list.forEach (function (curobj) {curobj.classList[op](hover_class)})}
  if ((!delay_preferences[input_type]) || (!delay_preferences[input_type][op])) {
   do_hover_change ()
  } else {
   setTimeout (do_hover_change, delay_preferences[input_type][op])
  }
 }

 if (handle_mouse_events) {
  document.body.addEventListener ('mouseover' , function (evt) {var curobj = evt.target; default_handler (curobj, "mouse", "add")})
  document.body.addEventListener ('mouseout'  , function (evt) {var curobj = evt.target; default_handler (curobj, "mouse", "remove")})
  document.body.addEventListener ('click'     , function (evt) {var curobj = evt.target; default_handler (curobj, "mouse", "remove")})
 }

 if (handle_touch_events) {
  document.body.addEventListener ('touchstart', function (evt) {var curobj = evt.target; default_handler (curobj, "touch", "add")})
  document.body.addEventListener ('touchend'  , function (evt) {var curobj = evt.target; default_handler (curobj, "touch", "remove")})
  document.body.addEventListener ('touchmove',  function (evt) {
   var curobj = evt.target
   var hovered_elements = Array.prototype.slice.call(document.body.querySelectorAll("*:hover"))
   var lastobj = null
   evt = evt.changedTouches[0]
   var elements_at_point = get_elements_at_point (evt.pageX, evt.pageY)
   // Get the last element that isn't at the current point but is still hovered over, and remove only its hover attribute.
   while (true) {
    if ((curobj == null) || (curobj == document.documentElement)) break
    if ((hovered_elements.indexOf(curobj) != -1) && (elements_at_point.indexOf(curobj) == -1)) lastobj = curobj
    curobj = curobj.parentNode
   }
   if (lastobj == null) return
   if ((!delay_preferences.touch) || (!delay_preferences.touch.remove)) {
    lastobj.classList.remove(hover_class)
   } else {
    setTimeout (function () {lastobj.classList.remove(hover_class)}, delay_preferences.touch.remove)
   }

   function get_elements_at_point (x, y) {
    var el_list = [], pe_list = []
    while (true) {
     var curobj = document.elementFromPoint(x, y)
     if ((curobj == null) || (curobj == document.documentElement)) break
     el_list.push (curobj); pe_list.push (curobj.style.pointerEvents)
     curobj.style.pointerEvents = "none"
    }
    el_list.forEach (function (current_element, i) {current_element.style.pointerEvents = pe_list[i]})
    return el_list
   }
  })
 }
}

0

페이지에 Modernizr 를 포함 하고 대신 다음과 같이 호버 상태를 설정하십시오.

html.no-touchevents .box:hover {
    background: blue;
}

0

안녕하세요, 미래의 사람입니다. 아마도 pointer및 / 또는 hover미디어 쿼리 를 사용하고 싶을 것입니다 . handheld미디어 쿼리는 사용되지 않습니다.

/* device is using a mouse or similar */
@media (pointer: fine) {
  a:hover {
    background: red;
  }
}

-1

이 쉬운 2019 jquery 솔루션을 사용해보십시오.

  1. 이 플러그인을 헤드에 추가하십시오.

    src="https://code.jquery.com/ui/1.12.0/jquery-ui.min.js"

  2. 이것을 js에 추가하십시오.

    $("*").on("touchend", function(e) { $(this).focus(); }); //applies to all elements

  3. 이에 대한 몇 가지 제안 된 변형은 다음과 같습니다.

    $(":input, :checkbox,").on("touchend", function(e) {(this).focus);}); //specify elements
    
    $("*").on("click, touchend", function(e) { $(this).focus(); });  //include click event`
    
    css: body { cursor: pointer; } //touch anywhere to end a focus`

노트

  • 툴팁에 영향을주지 않도록 해당하는 경우 bootstrap.js 앞에 플러그인을 배치합니다.
  • Safari 또는 Chrome을 사용하여 iphone XR ios 12.1.12 및 ipad 3 ios 9.3.5에서만 테스트되었습니다.

참조 :

https://code.jquery.com/ui/

https://api.jquery.com/category/selectors/jquery-selector-extensions/

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.