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

저는 데스크톱과 태블릿 모두에서 사용되는 웹 사이트를 작성하고 있습니다. 데스크톱에서 방문 할 때 화면의 클릭 가능한 영역이 :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.



답변

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

  • 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 가 실행되고 클릭 이벤트가 실행되지 않고 (예 : 사용자가 스크롤하거나 확대 / 축소 된) 마우스로 링크를 따라 가려는 경우 (예 : 마우스와 터치 인터페이스가 모두있는 장치에서) 작동하지 않습니다. ).

추가 읽기


답변

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

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

: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로 적용하면 마우스 이벤트에 구체적으로 바인딩 할 수 있고 / 또는 다시 화면 크기에 따라 몇 가지 가정을 할 수 있으며 최악의 경우 “문제”가 일부 마우스를 사용하는 사용자는 호버 효과를 놓칩니다.


답변

터치시 나타나지 않아야하는 호버 효과가있는 데스크톱 / 모바일 / 태블릿 사이트 인 최근 프로젝트를 위해 다음 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();


답변

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

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

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

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

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

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


답변

내 해결책은 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;
}


답변

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

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

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

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


답변

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

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

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

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

       #buttonOne{
            height: 44px;
        }


        #buttonOne:hover{
            display:none;
        }
}