터치 장치의 버튼에 끈적임 호버 효과를 방지하는 방법


144

항상 표시되는 이전 및 다음 버튼으로 회전식 메뉴를 만들었습니다. 이 버튼은 호버 상태이며 파란색으로 바뀝니다. iPad와 같은 터치 장치에서는 호버 상태가 고정되어 있으므로 버튼을 탭한 후에도 파란색으로 유지됩니다. 나는 그것을 원하지 않습니다.

  • 각 버튼에 no-hover클래스 ontouchend를 추가하고 CSS를 다음과 같이 만들 수는 button:not(.no-hover):hover { background-color: blue; }있지만 성능에 좋지 않을 수 있으며 크롬 북 픽셀 (터치 스크린과 마우스가 모두있는)과 같은 기기를 올바르게 처리하지 못합니다.

  • touch클래스를 추가하고 documentElementCSS를 다음과 같이 만들 수 있습니다 . html:not(.touch) button:hover { background-color: blue; }그러나 터치와 마우스가 모두있는 장치에서는 제대로 작동하지 않습니다.

내가 선호하는 것은 호버 상태를 제거하는 것 ontouchend입니다. 그러나 가능하지 않은 것 같습니다. 다른 요소에 초점을 맞추더라도 호버 상태가 제거되지 않습니다. 다른 요소를 수동으로 두드리는 것이지만 JavaScript에서 트리거 할 수없는 것 같습니다.

내가 찾은 모든 솔루션이 불완전한 것처럼 보입니다. 완벽한 솔루션이 있습니까?

답변:


55

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>

3
@Chris 좋은 점은 ontouchend 이벤트에서 onclick 핸들러를 설정하도록 예제를 변경했습니다.
Sjoerd Visscher 2013 년

4
답에 최소한의 데모 코드를 추가하십시오. 감사! stackoverflow.com/help/how-to-answer
2540625

1
@SjoerdVisscher 붙여 넣었습니다. StackOverflow는 링크가 사라질 수 있으므로 코드가 답이되는 것을 좋아합니다. (이 경우에는 클릭 연결뿐만 아니라 소스를보고 문제가되는 비트를
Darren Cook

2
일부 장치에서 @KevinBorders yes는 요소의 제거와 다시 삽입 사이의 시간 지연이 매우 눈에.니다. 불행히도, 안드로이드 4.4 장치에서 setTimeout 없이이 작업을 수행 할 수 없다는 것을 알았습니다.
Rodney

1
이 아이디어는 흥미롭지 만, 약간 터치하여 모든 터치 장치에서 널리 지원되지는 않습니다. 이 같은 터치 지원 감지 및 순수 CSS를 기반으로 덜 침습적 솔루션을 선호 stackoverflow.com/a/39787268/885464
로렌조 Polidori에게

83

일단 CSS 미디어 쿼리 레벨 4가 구현되어, 당신은이 작업을 수행 할 수 있습니다 :

@media (hover: hover) {
    button:hover {
        background-color: blue;
    }
}

또는 영어로 : "브라우저가 올바른 / 진짜 / 실제 / 비 에뮬레이트 호버링을 지원하는 경우 (예 : 마우스와 같은 기본 입력 장치가있는 경우) button마우스를 올렸을 때이 스타일을 적용하십시오 ."

Media Queries Level 4의이 부분은 지금까지 최첨단 Chrome에서만 구현 되었으므로 이를 처리하기 위해 폴리 필작성했습니다 . 이를 사용하여 위의 미래형 CSS를 다음과 같이 변환 할 수 있습니다.

html.my-true-hover button:hover {
    background-color: blue;
}

( .no-touch기술 의 변형 ) 그런 다음 호버링 지원을 감지하는 동일한 폴리 필에서 클라이언트 측 JavaScript를 사용하여 my-true-hover클래스 의 존재 여부를 적절하게 토글 할 수 있습니다 .

$(document).on('mq4hsChange', function (e) {
    $(document.documentElement).toggleClass('my-true-hover', e.trueHover);
});

감사! 내 목적으로 이것은 대부분의 브라우저 caniuse.com/#search=media%20queries 에서 지원되는 것으로 보이며 훌륭하게 작동합니다. 감사합니다!
ragamufin

3
당신은 볼 필요가 caniuse.com/#feat=css-media-interaction 대신 당신은 파이어 폭스와 IE11에서 지원되지 않는 볼 :( 당신이 polyfill 필요하므로
CherryDT

... polyfill이 더 이상 지원되지 보인다 (REPO가 보관) 그리고 jQuery를 필요
amoebe

이것은 현재 모바일 브라우저에서 널리 지원되며 매력처럼 작동합니다. 나는 그것이 대답이되어야한다고 생각합니다.
Trevor Burnham

이것은 구현하기 가장 쉽고 최고의 답변입니다. Android 모바일 및 PC의 Firefox에서 작동합니다. 듀얼 터치 및 마우스 장치에 대해 잘 모르겠습니다.
HalfMens

28

완벽한 솔루션이없는 일반적인 문제입니다. 호버 동작은 마우스에 유용하며 대부분 터치하면 해 롭습니다. 문제는 크롬 북 픽셀 및 표면과 같이 터치와 마우스를 동시에 지원하는 기기입니다.

내가 찾은 가장 깨끗한 솔루션은 장치가 터치 입력을 지원하지 않는 경우에만 호버 동작을 활성화하는 것입니다.

var isTouch =  !!("ontouchstart" in window) || window.navigator.msMaxTouchPoints > 0;

if( !isTouch ){
    // add class which defines hover behavior
}

물론 지원할 수있는 장치에서 호버링을 잃게됩니다. 그러나 때로는 마우스 오버가 링크 자체보다 많은 영향을 미칩니다. 예를 들어 요소를 가리킬 때 메뉴를 표시하려고 할 수 있습니다. 이 방법을 사용하면 터치가 있는지 테스트하고 조건부로 다른 이벤트를 첨부 할 수 있습니다.

나는 이것을 iPhone, iPad, Chromebook Pixel, Surface 및 다양한 Android 기기에서 테스트했습니다. 일반적인 USB 터치 입력 (스타일러스 등)이 믹스에 추가 될 때 작동한다는 보장은 없습니다.


1
커뮤니티 wiki / Darren Cook의 답변과 달리, 이것은 나를 위해 일했습니다.
Jannik

1
좋은 대답입니다. 이것은 비슷한 솔루션입니다. stackoverflow.com/a/39787268/885464
Lorenzo Polidori

11

Modernizr 을 사용하면 터치가없는 장치를 위해 특히 호버를 대상으로 지정할 수 있습니다.

(참고 : 이것은 StackOverflow의 스 니펫 시스템에서 실행되지 않습니다. 대신 jsfiddle을 확인하십시오 )

/* this one is sticky */
#regular:hover, #regular:active {
  opacity: 0.5;
}

/* this one isn't */
html.no-touch #no-touch:hover, #no-touch:active {
  opacity: 0.5;
}

참고 :active이 필요하지 않습니다 함께 대상으로하는 .no-touch이 같은 모바일 및 데스크톱 모두에서 예상 작동하기 때문에.


이것은 최선의 답변입니다. IMO 그러나 예제가 올바르지 않습니다. 터치 및 비 터치 장치에 대해 동일한 호버 상태를 보여줍니다. 태그 .no-touch에있는 경우 호버 상태 만 적용해야합니다 html. 그렇지 않으면이 답변에 승인 스탬프가 표시됩니다.
morrisbret

2
문제는 이제 터치 스크린이있는 마우스 지원 장치가 도처에 있으므로 더 이상이 방법에 의존 할 수 없다는 것입니다. 그러나 나는 그것을 할 수있는 다른 방법을 많이 볼 수 없다 ... 이것은 상당히 딜레마이다
dudewad

Modernizr과 mobile-detect.js 와 같은 라이브러리 를 사용하여 전화 또는 태블릿인지 확인하는 한 가지 방법이 있다고 가정 합니다.
Gavin

당신은 구세주 남자 덕분에이 모바일 장치에 완벽하게 작동 많이 있습니다
Shivam

8
$("#elementwithhover").click(function() { 
  // code that makes element or parent slide or otherwise move out from under mouse. 

  $(this).clone(true).insertAfter($(this));
  $(this).remove();
});

click () 대신 on ()을 사용 하여이 답변을 향상시킬 수 있습니다. DOM에서 요소를 제거하고 다시 연결하면 클릭 이벤트가 손실됩니다. on으로 함수를 다시 작성하고 요소에 바인딩 한 다음 제거하고 추가했습니다. 예를 들면 다음과 같습니다.`$ ( 'body'). on ( 'click', '# elementwithhover', function () {// clone, insertafter, remove}); 변경하면 투표하겠습니다.
윌 라니

클론 true는 멈춤 호버가있는 요소를 대신하여 새 엘레 네트에서 클릭 이벤트를 유지합니다. 원래 요소는 복제 된 후 돔에서 제거됩니다.
Verard Sloggett

굉장 형제, 10 배
Kaloyan Stamatov

수정 사항을 검색하는 데 몇 시간이 걸리고 결국 수정 사항을 제공했습니다. 정말 감사합니다!
phil917

8

에서 모바일에 스티커 가져가 처리하는 4 가지 방법 : 여기에 동적으로 추가하거나 "제거하는 방법 can touch사용자의 현재 입력 유형에 따라 문서에"클래스. 사용자가 터치와 마우스 / 트랙 패드 사이를 전환 할 수있는 하이브리드 장치에서도 작동합니다.

<script>

;(function(){
    var isTouch = false //var to indicate current input type (is touch versus no touch) 
    var isTouchTimer 
    var curRootClass = '' //var indicating current document root class ("can-touch" or "")

    function addtouchclass(e){
        clearTimeout(isTouchTimer)
        isTouch = true
        if (curRootClass != 'can-touch'){ //add "can-touch' class if it's not already present
            curRootClass = 'can-touch'
            document.documentElement.classList.add(curRootClass)
        }
        isTouchTimer = setTimeout(function(){isTouch = false}, 500) //maintain "istouch" state for 500ms so removetouchclass doesn't get fired immediately following a touch event
    }

    function removetouchclass(e){
        if (!isTouch && curRootClass == 'can-touch'){ //remove 'can-touch' class if not triggered by a touch event and class is present
            isTouch = false
            curRootClass = ''
            document.documentElement.classList.remove('can-touch')
        }
    }

    document.addEventListener('touchstart', addtouchclass, false) //this event only gets called when input type is touch
    document.addEventListener('mouseover', removetouchclass, false) //this event gets called when input type is everything from touch to mouse/ trackpad
})();

</script>

이것이 내가 찾는 가장 좋은 방법이며, 타이머를 1000ms로 늘리면 길게 누를 수도 있습니다 ( 여기 참조) . 좋은 물건!
lowtechsun

8

호버를 지원하지 않는 장치의 호버 효과를 무시할 수 있습니다. 처럼:

.my-thing {
    color: #BADA55;
}

.my-thing:hover {
    color: hotpink;
}

@media (hover: none) {
    .my-thing {
        color: #BADA55;
    }
}

iOS 12에서 테스트 및 검증

이것을 지적하기위한 모자 팁 https://stackoverflow.com/a/50285058/178959


이것은 자바 스크립트 또는 DOM 조작이 필요없는 최신 솔루션이며 브라우저를 완벽하게 지원합니다 (IE 제외).
funkju

3

내 솔루션을 게시하려고했지만 누군가가 이미 게시했는지 확인한 결과 @Rodney가 거의 수행했음을 알았습니다. 그러나 그는 적어도 내 경우에는 그것을 불편하게 만드는 마지막 결정을 놓쳤다. 내 말은, 동일한 .fakeHover클래스 추가 / 제거 mouseentermouseleave이벤트 감지 를 취 했지만 그 자체 만으로도 "정품"과 거의 동일하게 작동합니다.:hover . 내 말은 : 당신이 당신의 테이블에있는 요소를 누를 때, 그것은 당신이 그것을 "잎"을 감지하지 않으므로 "가짜"상태를 유지합니다.

내가 한 것은 단순히 듣기 만 click했기 때문에 버튼을 "탭"하면 수동으로mouseleave .

Si 이것은 내 최종 코드입니다.

.fakeHover {
    background-color: blue;
}


$(document).on('mouseenter', 'button.myButton',function(){
    $(this).addClass('fakeHover');
});

$(document).on('mouseleave', 'button.myButton',function(){
    $(this).removeClass('fakeHover');
});

$(document).on('button.myButton, 'click', function(){
    $(this).mouseleave();
});

이런 식으로 hover마우스 버튼을 단순히 "호버링"할 때 마우스를 사용할 때 일반적인 기능 을 유지합니다 . 글쎄, 거의 모든 것 : 어떻게 든 유일한 단점은 마우스로 버튼을 클릭 한 후에는 상태가되지 않는다는 것입니다 hover. 클릭하고 버튼에서 포인터를 빠르게 가져간 경우와 유사합니다. 그러나 제 경우에는 그걸로 살 수 있습니다.


2

이것이 나머지 답변을 연구 한 후에 지금까지 생각해 낸 것입니다. 터치 전용, 마우스 전용 또는 하이브리드 사용자를 지원할 수 있어야합니다.

호버 효과에 대한 별도의 호버 클래스를 만듭니다. 기본적으로이 호버 클래스를 버튼에 추가하십시오.

우리는 터치 지원의 존재를 감지하고 처음부터 모든 호버 효과를 비활성화하고 싶지 않습니다. 다른 사람들이 언급했듯이 하이브리드 장치는 인기를 얻고 있습니다. 사람들은 터치 지원 기능을 가지고 있지만 마우스를 사용하고 싶거나 그 반대의 경우도 있습니다. 따라서 사용자가 실제로 버튼을 터치 한 경우 호버 클래스 만 제거하십시오.

다음 문제는 사용자가 버튼을 터치 한 후 마우스 사용으로 돌아가려면 어떻게해야합니까? 이를 해결하기 위해 제거한 호버 클래스를 다시 추가 할 수있는 적절한 순간을 찾아야합니다.

그러나 호버 상태가 여전히 활성 상태이므로 제거 후 즉시 다시 추가 할 수 없습니다. 우리는 전체 버튼을 파괴하고 다시 만들고 싶지 않을 수도 있습니다.

따라서 바쁜 대기 알고리즘 (setInterval 사용)을 사용하여 호버 상태를 확인하려고 생각했습니다. 호버 상태가 비활성화되면 호버 클래스를 다시 추가하고 통화 중 대기를 중지하여 사용자가 마우스 또는 터치를 사용할 수있는 원래 상태로 되돌릴 수 있습니다.

바쁜 대기가 그다지 좋지는 않지만 적절한 이벤트가 있는지 확실하지 않습니다. 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>

편집 : 내가 시도한 또 다른 접근법은 e.preventDefault()ontouchstart 또는 ontouchend 내 에서 전화하는 것입니다. 버튼을 터치하면 호버 효과가 중지되는 것처럼 보이지만 버튼 클릭 애니메이션을 중지하고 버튼을 터치 할 때 온 클릭 기능이 호출되는 것을 방지하므로 ontouchstart 또는 ontouchend 핸들러에서 수동으로 호출해야합니다. 매우 깨끗한 해결책은 아닙니다.


1

도움이되었습니다 : 링크

function hoverTouchUnstick() {
    // Check if the device supports touch events
    if('ontouchstart' in document.documentElement) {
        // Loop through each stylesheet
        for(var sheetI = document.styleSheets.length - 1; sheetI >= 0; sheetI--) {
            var sheet = document.styleSheets[sheetI];
            // Verify if cssRules exists in sheet
            if(sheet.cssRules) {
                // Loop through each rule in sheet
                for(var ruleI = sheet.cssRules.length - 1; ruleI >= 0; ruleI--) {
                    var rule = sheet.cssRules[ruleI];
                    // Verify rule has selector text
                    if(rule.selectorText) {
                        // Replace hover psuedo-class with active psuedo-class
                        rule.selectorText = rule.selectorText.replace(":hover", ":active");
                    }
                }
            }
        }
    }
}

전역 ontouchstart 이벤트 핸들러에서 hoverTouchUnstick ()을 한 번 호출해야합니다. 그리고이 솔루션은 완벽하게 작동합니다.
Jusid

1

이 JS 코드를 페이지에 추가하십시오.

document.body.className = 'ontouchstart' in document.documentElement ? '' : 'hover';

이제 모든 호버 전에 CSS에서 다음과 같이 호버 클래스를 추가하십시오.

.hover .foo:hover {}

장치가 터치되면 바디 클래스가 비어 있고 그렇지 않으면 클래스가 가리키고 규칙이 적용됩니다!


나를 위해 작동하지 않았지만 이것은 다음과 같이 작동했습니다 :document.body.className = 'ontouchstart' in window ? '' : 'hover';
drskullster

1

각 버튼마다 호버링 없음 클래스 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 (터치 스크린과 마우스 모두 포함)과 같은 기기도 올바르게 처리해야합니다. 그리고 나는 이것이 주요 성능 킬러라고 생각하지 않습니다 ...


1

나를 위해 일한 솔루션 :

html {
   -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}

이 코드를 스타일 시트에 추가하십시오.

링크를 클릭하면 iOS Safari에 나타나는 회색 배경을 제거하고 싶었습니다. 그러나 더 많은 것으로 보입니다. 이제 :hover의사 클래스가 있는 버튼을 클릭하면 바로 열립니다! 나는 iPad에서만 테스트했지만 다른 장치에서 작동하는지 모르겠습니다.


1

비슷한 문제에 대한 우아한 (최소 js) 솔루션을 찾았습니다.

jQuery를 사용하면 본문 (또는 다른 요소)에서 호버를 트리거 할 수 있습니다 .mouseover()

따라서이 핸들러를 요소의 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>

그러나 이것은 스 와이프 또는 다른 터치와 같은 다른 터치 이벤트가 트리거 된 후에 만 ​​요소에서 의사 호버 클래스를 제거합니다.


1
코드 스 니펫의 경우 사각형을 만진 후에도 여전히 분홍색으로 유지됩니다. 이 질문에서 제기 한 문제를 실제로 해결하지 못한 것 같습니까?
Kevin Lee

이 솔루션은 작동하지 않습니다. 먼저, 잘못된 메소드를 사용하여 이벤트를 호출했습니다 . .trigger () 를 사용해야합니다 . 둘째, 모바일 사파리에서 작동하지 않습니다.
xHocquet

1

나는 공유하고 싶은 좋은 해결책이 있습니다. 먼저 다음과 같이 사용자가 모바일에 있는지 감지해야합니다.

var touchDevice = /ipad|iphone|android|windows phone|blackberry/i.test(navigator.userAgent.toLowerCase());

그런 다음 추가하십시오.

if (!touchDevice) {
    $(".navbar-ul").addClass("hoverable");
}

그리고 CSS에서 :

.navbar-ul.hoverable li a:hover {
    color: #fff;
}

2
Windows 터치 스크린 PC와 같은 하이브리드 장치에서는 작동하지 않습니다.
cspolton

1

비슷한 문제를 겪었습니다. 응용 프로그램은 모든 화면 크기와 호환되었으며 데스크톱 화면 크기 에서 호버링 효과가 많이있었습니다. / 마우스 기반 장치 있었고 나중에 터치 기반 장치가 끈적 거리는 것으로 알려진 상태를 유발한다는 것을 깨달았습니다. 터치 기반 장치 사용자에게 앱이 제대로 작동하는 데 장애물이되었습니다.

앱에서 SCSS 를 사용하고있었습니다 . 터치 기반 기기를 관리하기 위해 믹스 인 을 정의했습니다 .

@mixin hover-support {
  @media not all and (pointer: coarse) {
    &:hover {
      @content;
    }
  }
}

그런 다음 모든 CSS 클래스를 아래 언급 된 스 니펫 아래에 배치했습니다.

   @include hover-support() {
    // Your css-classes or css that you want to apply on those devices that support hover.
   }

예를 들어 아이콘에 애니메이션을 적용하는 클래스가 있었고 CSS에서 볼 수 있듯이 아이콘 위에 마우스를 올려 놓으면 트리거되는 데 사용되었지만 터치 기반 장치에서는 스티커 호버 효과의 영향을 받아 @ 안에 배치했습니다. 호버를 지원 하는 장치에만 호버를 적용하려면 hover-support () 를 포함하십시오.

@include hover-support() {
  .animate-icon {
    -webkit-transition: all 0.2s;
    transition: all 0.2s;
    &:hover {
      transform: scale(1.3);
      filter: brightness(85%);
      cursor: pointer;
    }
  }
}

1

다음은 개발자가 CSS를 편집하거나 새로운 CSS 규칙을 작성하지 않아도되는 간단한 JavaScript 코드입니다. 나는 이것을 사용하여 Bootstrap 버튼에 썼지 class="btn"만 특정 클래스 이름을 가진 모든 버튼에서 작동합니다.

단계는 다음과 같습니다.

  1. 이것이 터치 장치인지 확인
  2. 그렇다면 모든 CSS 규칙을 반복하십시오. document.styleSheets
  3. .btn과 모두를 포함하는 규칙을 삭제:hover

모든 .btn :hoverCSS 규칙을 제거 하면 버튼에 시각적 호버 효과가 없습니다.

1 단계 : 터치 장치 감지

다음에 대한 미디어 쿼리를 확인하십시오 (hover: none).

    const hasMatchMedia = typeof window.matchMedia !== 'undefined';
    /**
     * determine if device is touch-capable
     * true - device is touch-capable
     * false - device is not touch-capable
     * null - unable to determine touch capability
     * @return {null|boolean}
     */
    const hasTouch = () => {
      if (hasMatchMedia) {
        return window.matchMedia('(hover: none)').matches;
      }
      return null;
    };

2 단계 :`btn` 및`: hover`가 포함 된 CSS 규칙 삭제

    /**
     * remove all CSS rules contaning both '.btn' and ':hover'
     * @return {number} count of rules deleted
     */
    function removeBtnHovers () {

      let rulesDeleted = 0;

      // recursively delete '.btn:hover' rules
      function recursiveDelete (rules, styleSheet) {

        if (typeof rules === 'undefined' ||
          typeof rules.length === 'undefined' ||
          rules.length <= 0) {
          return;
        }

        // iterate in reverse order,
        // deleting any rule containing both '.btn' and ':hover'
        const ruleLen = rules.length;
        for (let i = ruleLen - 1; i >= 0; i--) {
          const rule = rules[i];
          if (typeof rule.cssRules === 'undefined') {
            // a standard rule, evaluate it
            const cssText = rule.cssText;
            if (typeof cssText === 'string' &&
              cssText.includes('.btn') &&
              cssText.includes(':hover')) {
              styleSheet.deleteRule(i);
              rulesDeleted++;
            }
          } else {
            // rule contains cssRules, iterate over them
            recursiveDelete(rule.cssRules, rule);
          }
        }
      }

      // iterate over all style sheets in document
      for (const styleSheet of document.styleSheets) {
        let rules = styleSheet.cssRules;
        if (!rules) { continue; }
        recursiveDelete(rules, styleSheet);
      }
      return rulesDeleted;
    }

완전한 코드는 GitHubnpm에 있습니다.

terrymorse.com 에서 라이브 데모 .


마우스 / 트랙 패드가있는 터치 스크린 장치의 호버 효과도 제거되지 않습니까?
Jensei

@Jensei 가능합니다. 장치가 일치 @media (hover:none)하거나 사용자가 처음 화면을 터치하면 호버 규칙이 제거됩니다 . 라이브 데모 페이지에서 사용해 볼 수 있습니다.
terrymorse

0

:active상태에 배경색을 설정하고 기본 배경을 줄 수 :focus 있습니다.

via-color via를 설정 onfocus/ontouch하면 :focus상태가 사라지면 색상 스타일이 유지 됩니다. 초점을 잃었을 때 defaut bg를 복원하려면
재설정해야합니다 onblur.


그러나 마우스 사용자의 호버 효과를 유지하고 싶습니다.
Chris

: hover 및 : active는 동일한 CSS를 수신 할 수 있습니다. 문제에 초점이 있습니다. 실제로 onfocus를 통해 배경색을 설정하면 포커스가 사라지면 색상 스타일이 유지됩니다. 당신은 defaut에 BG 복원 할뿐만 아니라 onlur에 리셋 필요
G-Cyrillus

0

이것은 나를 위해 일했습니다 : 호버 스타일을 새로운 수업에 넣으십시오.

.fakehover {background: red}

그런 다음 필요에 따라 클래스를 추가 / 제거하십시오

$(".someclass > li").on("mouseenter", function(e) {
  $(this).addClass("fakehover");
});
$(".someclass > li").on("mouseleave", function(e) {
  $(this).removeClass("fakehover");
});

터치 스타트 및 터치 엔드 이벤트에 대해 반복하십시오. 또는 원하는 결과를 얻으려는 이벤트가 무엇이든, 예를 들어 터치 스크린에서 호버 효과를 전환하려고했습니다.


0

Darren Cooks의 답변에 따르면 다른 요소 위로 손가락을 움직여도 작동합니다.

터치 엔드 이벤트 중 요소 손가락 찾기를 참조하십시오.

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

Codepen Demo


0

이 방법으로 시도 할 수 있습니다.

자바 스크립트 :

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

0

지금까지 프로젝트에서 수행 한 작업은 :hover터치 장치 의 변경 사항 을 되 돌리는 것이 었습니다 .

.myhoveredclass {
    background-color:green;
}
.myhoveredclass:hover {
    background-color:red;
}
@media screen and (-webkit-min-device-pixel-ratio:0) {
    .myhoveredclass:hover, .myhoveredclass:active, .myhoveredclass:focus {
        background-color:green;
    }
}

데모 목적으로 만 모든 클래스 이름과 명명 된 색상 ;-)


0

이것은 2 단계로 완벽하게 작동합니다.

  1. 바디 태그를 다음과 같이 설정하십시오 <body ontouchstart="">. 나는이 "해킹"의 팬이 아니지만 iOS의 Safari가 터치에 즉시 반응 할 수 있습니다. 잘 모르겠지만 작동합니다.

  2. 다음과 같이 터치 가능한 클래스를 설정하십시오.

    // I did this in SASS, but this should work with normal CSS as well
    
    // Touchable class
    .example {
    
        // Default styles
        background: green;
    
        // Default hover styles 
        // (Think of this as Desktop and larger)
        &:hover {
            background: yellow;
        }
    
        // Default active styles
        &:active {
            background: red;
        }
    
        // Setup breakpoint for smaller device widths
        @media only screen and (max-width: 1048px) {
    
            // Important!
            // Reset touchable hover styles
            // You may want to use the same exact styles as the Default styles
            &:hover {
                background: green;
            }
    
            // Important!
            // Touchable active styles
            &:active {
                background: red;
            }
        }
    }

터치 가능한 클래스에서 애니메이션을 제거 할 수도 있습니다. Android Chrome은 iOS보다 약간 느린 것 같습니다.

또한 사용자가 수업을 터치하는 동안 페이지를 스크롤하면 활성 상태가 적용됩니다.


0

브라우저가 화면을 조작하려고 시도 :hover :focus :active할 때 모바일 장치 의 고정 또는 멈춤 문제 중 일부 가 누락 될 수 있습니다 <meta name="viewport" content="width=device-width">.


0

나를위한 해결책은 touchend가 노드를 복제하고 교체하는 것이 었습니다 ...이 작업은 싫어하지만 offsetHeight로 요소를 다시 칠하려고해도 작동하지 않았습니다.

    let cloneNode = originNode.cloneNode( true );
    originNode.parentNode.replaceChild( cloneNode, originNode );

결국 이것은 나를 위해 작동하지 않았습니다 ... 내 경우에는 확장 된 전체 ES6과 여러 이벤트 리스너를 복제해야 할 것입니다.
금지

0

HTML 클래스를 교체하여 수행 할 수 있습니다. 특히 큰 이미지 링크 등을 사용하면 전체 요소를 제거하는 것보다 글리치가 발생하기 쉽습니다.

또한 호버링 을 원하는지 결정할 수 있습니다 터치 (touchmove)로 스크롤 할 때 상태를 트리거 또는 타임 아웃을 추가하여 지연시킬 있습니다.

우리 코드의 중요한 변화 <a class='hover'></a>는 새로운 행동을 구현하는 요소 와 같은 추가 HTML 클래스를 사용하는 것 입니다.

HTML

<a class='my-link hover' href='#'>
    Test
</a>

CSS

.my-link:active, // :active can be turned off to disable hover state on 'touchmove'
.my-link.hover:hover {

    border: 2px dotted grey;
}

JS (jQuery 포함)

$('.hover').bind('touchstart', function () {

   var $el;
   $el = $(this);
   $el.removeClass('hover'); 

   $el.hover(null, function () {
      $el.addClass('hover');
   });
});

https://codepen.io/mattrcouk/pen/VweajZv

-

그래도 마우스와 터치가 모두 올바르게 테스트되는 장치는 없습니다.

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