วิธีการป้องกันเอฟเฟกต์โฮเวอร์แบบเหนียวสำหรับปุ่มบนอุปกรณ์ระบบสัมผัส


144

ฉันได้สร้างม้าหมุนที่มีปุ่มก่อนหน้าและปุ่มถัดไปที่สามารถมองเห็นได้เสมอ ปุ่มเหล่านี้มีสถานะโฮเวอร์พวกเขาเปลี่ยนเป็นสีน้ำเงิน บนอุปกรณ์ระบบสัมผัสเช่น 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

การแก้ปัญหาทั้งหมดที่ฉันพบดูเหมือนไม่สมบูรณ์ มีวิธีแก้ไขปัญหาที่สมบูรณ์แบบหรือไม่

คำตอบ:


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 จุดที่ดีฉันเปลี่ยนตัวอย่างเพื่อตั้งค่าตัวจัดการ onclick ในเหตุการณ์ ontouchend
Sjoerd Visscher

4
โปรดพิจารณาการเพิ่มรหัสตัวอย่างขั้นต่ำให้กับคำตอบของคุณ ขอบคุณ! stackoverflow.com/help/how-to-answer
2540625

1
@SjoerdVisscher ฉันได้วางแล้ว StackOverflow ชอบรหัสที่จะอยู่ในคำตอบเนื่องจากลิงก์สามารถหายไปได้ (และในกรณีนี้มันต้องไม่ใช่แค่คลิกผ่าน แต่แล้วดูแหล่งที่มาและการทำงานออกซึ่งบิตมีเทคนิคในคำถาม.)
คาร์เรนคุก

2
@KevinBorders ใช่ในบางอุปกรณ์การหน่วงเวลาระหว่างการลบและการแทรกซ้ำขององค์ประกอบอาจเป็นสิ่งที่น่าสังเกตมาก น่าเสียดายที่ฉันพบบนอุปกรณ์ Android 4.4 ของฉันที่ทำสิ่งนี้โดยไม่มี setTimeout ไม่ทำงาน
Rodney

1
แนวคิดนี้น่าสนใจ แต่ฉันพบว่ามันค่อนข้างกระตุกและไม่รองรับการใช้งานกับอุปกรณ์ระบบสัมผัสทั้งหมด ฉันต้องการโซลูชันที่รุกรานน้อยกว่าโดยใช้การตรวจจับการสนับสนุนแบบสัมผัสและ css บริสุทธิ์เช่นstackoverflow.com/a/39787268/885464
Lorenzo Polidori

83

เมื่อใช้งานCSS Media Queries ระดับ 4คุณจะสามารถทำสิ่งนี้ได้:

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

หรือเป็นภาษาอังกฤษ: "หากเบราว์เซอร์รองรับการโฮเวอร์ที่เหมาะสม / จริง / จริง / ไม่มีการจำลอง (เช่นมีอุปกรณ์ป้อนข้อมูลหลักที่เหมือนเมาส์) ให้ใช้สไตล์นี้เมื่อbuttonมีการโฮเวอร์"

เนื่องจากส่วนหนึ่งของ Media Queries ระดับ 4 นี้มีการใช้งานเฉพาะใน Chrome ที่มีเลือดไหลออกมาฉันจึงเขียนโพลีฟิลล์เพื่อจัดการกับสิ่งนี้ ใช้มันคุณสามารถแปลง CSS อนาคตข้างต้นเป็น:

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

(การเปลี่ยนแปลงใน.no-touchเทคนิค) จากนั้นใช้ JavaScript ฝั่งไคลเอ็นต์จาก polyfill เดียวกันที่ตรวจพบการสนับสนุนสำหรับการโฮเวอร์คุณสามารถสลับการมีอยู่ของ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แทนและคุณจะเห็นว่ามันไม่ได้รับการสนับสนุนใน Firefox และ IE11 :( ดังนั้นคุณจึงต้องใช้ polyfill
CherryDT

ดูเหมือนว่า polyfill ไม่ได้รับการสนับสนุนอีกต่อไป (repo ถูกเก็บถาวร) และต้องการ jQuery ...
amoebe

ตอนนี้ได้รับการสนับสนุนอย่างกว้างขวางในเบราว์เซอร์มือถือและใช้งานได้อย่างมีเสน่ห์ ฉันคิดว่ามันควรจะเป็นคำตอบที่ได้รับการยอมรับ
เทรเวอร์เบิร์นแฮม

นี่เป็นวิธีที่ง่ายที่สุดในการดำเนินการและคำตอบที่ดีที่สุด ทำงานได้ใน Firefox บน Android Mobile และ PC ไม่แน่ใจเกี่ยวกับอุปกรณ์ระบบสัมผัสและเมาส์คู่
HalfMens

28

นี่เป็นปัญหาทั่วไปที่ไม่มีวิธีแก้ปัญหาที่สมบูรณ์แบบ พฤติกรรมการวางเมาส์เหนือเมาส์มีประโยชน์และเป็นอันตรายกับการสัมผัส การรวมปัญหาเป็นอุปกรณ์ที่รองรับการสัมผัสและเมาส์ (พร้อมกันไม่น้อยกว่า) เช่น Chromebook Pixel และ Surface

วิธีแก้ปัญหาที่สะอาดที่สุดที่ฉันพบคือเปิดใช้งานการโฮเวอร์เฉพาะเมื่ออุปกรณ์ไม่สนับสนุนการป้อนข้อมูลด้วยสัมผัสเท่านั้น

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

9

คุณสามารถแทนที่เอฟเฟ็กต์โฮเวอร์สำหรับอุปกรณ์ที่ไม่รองรับโฮเวอร์ ชอบ:

.my-thing {
    color: #BADA55;
}

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

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

ทดสอบและตรวจสอบแล้วใน iOS 12

ไปที่https://stackoverflow.com/a/50285058/178959เพื่อชี้เรื่องนี้


นี่เป็นวิธีที่ทันสมัยกว่าไม่ต้องใช้ javascript หรือ DOM ในการจัดการมีการสนับสนุนเบราว์เซอร์เต็มรูปแบบ (ยกเว้น IE) และควรเป็นคำตอบที่ยอมรับได้
funkju

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

คุณสามารถปรับปรุงคำตอบนี้โดยใช้การเปิด () แทนการคลิก () การลบองค์ประกอบออกจาก DOM และติดตั้งอีกครั้งฉันสูญเสียกิจกรรมการคลิกของฉัน เมื่อฉันเขียนฟังก์ชั่นใหม่ของฉันด้วยการเปิดผูกพันกับองค์ประกอบจากนั้นลบและเพิ่มการทำงาน ตัวอย่างเช่น: `$ ('body'). on ('คลิก', '# elementwithhover', function () {// / clone, insertafter, remove}); ฉันจะลงคะแนนนี้หากคุณทำการเปลี่ยนแปลงที่
Will Lanni

การโคลนที่แท้จริงเก็บรักษาคลิกเหตุการณ์ในตัวเอเลเมนท์ใหม่ซึ่งแทนที่องค์ประกอบด้วยโฮเวอร์ที่ติดอยู่ องค์ประกอบดั้งเดิมจะถูกลบออกจากโดมหลังจากโคลน
Verard Sloggett

พี่ชายที่น่ากลัว, 10x
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

3

ฉันกำลังจะโพสต์ทางออกของตัวเอง แต่ตรวจสอบว่ามีคนโพสต์แล้วฉันพบว่า @Rodney เกือบจะทำมัน อย่างไรก็ตามเขาพลาดสิ่งสำคัญครั้งสุดท้ายที่ทำให้มันไม่แน่นอนอย่างน้อยก็ในกรณีของฉัน ฉันหมายความว่าฉันก็เอาเหมือนกัน.fakeHoverนอกจากนี้ระดับ / ลบผ่านทางmouseenterและmouseleaveการตรวจสอบเหตุการณ์ แต่เพียงอย่างเดียวต่อ seทำหน้าที่เกือบจะเหมือนกับ :hover"ของแท้" ฉันหมายถึง: เมื่อคุณแตะที่องค์ประกอบในตารางของคุณมันจะไม่ตรวจพบว่าคุณมี "leaved" มัน - ดังนั้นการรักษาสถานะ "fakehover"

สิ่งที่ฉันได้เป็นเพียงเพื่อฟังบนclickมากเกินไปดังนั้นเมื่อผม "แตะปุ่ม" mouseleaveฉันด้วยตนเองยิง

ศรีนี่คือรหัสสุดท้ายของฉัน:

.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

นี่คือสิ่งที่ฉันเกิดขึ้นหลังจากศึกษาคำตอบที่เหลือ มันควรจะสามารถรองรับผู้ใช้แบบสัมผัสเท่านั้นเมาส์เท่านั้นหรือไฮบริด

สร้างคลาส hover แยกต่างหากสำหรับเอฟเฟกต์โฮเวอร์ โดยค่าเริ่มต้นเพิ่มคลาส hover นี้ลงในปุ่มของเรา

เราไม่ต้องการตรวจจับการมีอยู่ของการรองรับการสัมผัสและปิดใช้งานเอฟเฟ็กต์โฮเวอร์ทั้งหมดตั้งแต่เริ่มต้น ดังที่ผู้อื่นกล่าวถึงอุปกรณ์ไฮบริดกำลังได้รับความนิยม ผู้คนอาจมีระบบสัมผัส แต่ต้องการใช้เมาส์และในทางกลับกัน ดังนั้นให้ลบคลาส hover เมื่อผู้ใช้กดปุ่มจริง

ปัญหาต่อไปคือถ้าผู้ใช้ต้องการกลับไปใช้เมาส์หลังจากกดปุ่ม? เพื่อแก้ปัญหานั้นเราต้องหาช่วงเวลาที่เหมาะสมเพื่อเพิ่มคลาสโฮเวอร์ที่เราลบออกไป

อย่างไรก็ตามเราไม่สามารถเพิ่มกลับคืนได้ทันทีหลังจากลบเนื่องจากสถานะโฮเวอร์ยังทำงานอยู่ เราอาจไม่ต้องการทำลายและสร้างปุ่มทั้งหมดอีกครั้งเช่นกัน

ดังนั้นฉันคิดว่าจะใช้อัลกอริทึมที่รอไม่ว่าง (โดยใช้ 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>

แก้ไข: วิธีอื่นที่ฉันพยายามคือโทรe.preventDefault()ภายใน ontouchstart หรือ ontouchend ดูเหมือนว่าจะหยุดเอฟเฟ็กต์โฮเวอร์เมื่อปุ่มถูกแตะ แต่มันก็หยุดการเคลื่อนไหวของปุ่มคลิกและป้องกันไม่ให้มีการเรียกใช้ฟังก์ชั่น onclick เมื่อปุ่มถูกแตะดังนั้นคุณต้องเรียกใช้งานเหล่านั้นด้วยตนเองใน ไม่ใช่วิธีที่สะอาดมาก


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

คุณต้องโทร hoverTouchUnstick () หนึ่งครั้งจากตัวจัดการเหตุการณ์ ontouchstart ทั่วโลก และวิธีนี้จะทำงานได้อย่างสมบูรณ์
Jusid

1

เพิ่มรหัส JS นี้ในหน้าของคุณ:

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

ตอนนี้ใน CSS ของคุณก่อนที่ทุกโฮเวอร์จะเพิ่มคลาสโฮเวอร์ดังนี้

.hover .foo:hover {}

หากอุปกรณ์สัมผัสระดับร่างกายจะว่างเปล่ามิฉะนั้นระดับอุปกรณ์จะเลื่อนอยู่และมีการใช้กฎ!


ไม่ได้ผลสำหรับฉัน แต่สิ่งนี้ทำได้:document.body.className = 'ontouchstart' in window ? '' : 'hover';
drskullster

1

ฉันสามารถเพิ่มคลาส no-hover ontouchend สำหรับแต่ละปุ่มและทำให้ CSS ของฉันเป็นเช่นนี้: ปุ่ม: ไม่ (.no-hover): โฮเวอร์ {background-color: blue; } แต่นั่นอาจไม่ดีสำหรับประสิทธิภาพและไม่ได้จัดการ> อุปกรณ์เช่น Chromebook Pixel (ซึ่งมีทั้งหน้าจอสัมผัสและเมาส์)> อย่างถูกต้อง

นี่คือจุดเริ่มต้นที่เหมาะสม ขั้นตอนถัดไป: ใช้ / ลบคลาส nohover กับกิจกรรมต่อไปนี้ (สาธิตด้วย jQuery)

buttonelement
 .on("touchend touchcancel",function(){$(this).addClass("nohover")})
 .on("touchstart mouseover",function({$(this).removeClass("nohover")});   

ประกาศ: ถ้าคุณต้องการใช้คลาสอื่น ๆ กับปุ่มกด, ไม่: (.nohover) ใน CSS จะไม่ทำงานอีกต่อไปตามที่คาดไว้ คุณต้องเพิ่มคำจำกัดความที่แยกต่างหากแทนค่าเริ่มต้นและ! แท็กสำคัญเพื่อแทนที่สไตล์โฮเวอร์: .nohover {สีพื้นหลัง: สีขาว! สำคัญ}

สิ่งนี้ควรจัดการอุปกรณ์เช่น Chromebook Pixel (ซึ่งมีทั้งหน้าจอสัมผัสและเมาส์) อย่างถูกต้อง! และฉันไม่คิดว่านี่เป็นนักฆ่าประสิทธิภาพที่สำคัญ ...


1

วิธีแก้ปัญหาที่ได้ผลสำหรับฉัน:

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

เพิ่มรหัสนี้ในสไตล์ชีทของคุณ

ฉันต้องการกำจัดพื้นหลังสีเทาที่ปรากฏบน iOS Safari เมื่อมีการคลิกลิงก์ แต่ดูเหมือนว่าจะทำอะไรได้มากกว่า ตอนนี้คลิกปุ่ม (พร้อม:hoverpseudoclass!) เปิดทันที! ฉันทดสอบบน 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>

อย่างไรก็ตามสิ่งนี้ลบออกเพียง: โฮเวอร์ pseudoclass จากองค์ประกอบหลังจากเหตุการณ์การสัมผัสอื่น ๆ ถูกเปิดใช้งานเช่นการปัดหรือการสัมผัสอื่น


1
สำหรับข้อมูลโค้ดของคุณสี่เหลี่ยมยังคงเป็นสีชมพูหลังจากที่ฉันแตะมัน ฉันเดาว่าคุณไม่ได้แก้ปัญหาที่ถามในคำถามนี้จริงหรือ
เควินลี

วิธีนี้ไม่ทำงาน ครั้งแรกที่คุณใช้วิธีการที่ไม่ถูกต้องจะก่อให้เกิดเหตุการณ์ที่คุณควรใช้.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
cspolton

1

ฉันเจอปัญหาที่คล้ายกันแอพพลิเคชั่นของฉันใช้งานได้กับทุกขนาดหน้าจอมีเอฟเฟกต์โฮเวอร์จำนวนมากในอุปกรณ์ที่ใช้ขนาดหน้าจอเดสก์ท็อป / เมาส์และต่อมาฉันก็รู้ว่าอุปกรณ์ที่ใช้ระบบสัมผัส - เลื่อนและมันเป็นอุปสรรค์สำหรับแอปที่จะทำงานอย่างถูกต้องสำหรับผู้ใช้อุปกรณ์ที่ใช้ระบบสัมผัส

เราใช้ประโยชน์จากSCSSในแอปของเรา และฉันกำหนดmixinเพื่อดูแลอุปกรณ์ที่ใช้ระบบสัมผัส

@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-effect แบบเหนียวแล้วฉันวางไว้ข้างใน@ รวมถึงการสนับสนุนโฮเวอร์ ()เพื่อให้แน่ใจว่าการโฮเวอร์ใช้ได้กับอุปกรณ์เหล่านั้นที่สนับสนุนการโฮเวอร์เท่านั้น

@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

นี่คือรหัส JavaScript ง่ายๆที่ไม่ต้องการให้นักพัฒนาแก้ไข CSS หรือเขียนกฎ CSS ใหม่ ฉันเขียนสิ่งนี้สำหรับปุ่ม Bootstrap ด้วยclass="btn"แต่มันจะทำงานกับปุ่มใด ๆ ที่มีชื่อคลาสเฉพาะ

ขั้นตอนคือ:

  1. ตรวจสอบว่าเป็นอุปกรณ์สัมผัส
  2. หากเป็นเช่นนั้นให้ทำซ้ำกฎ CSS ทั้งหมด document.styleSheets
  3. ลบกฎที่มีทั้ง.btnและ:hover

การกำจัด.btn :hoverกฎ CSS ทั้งหมดช่วยให้มั่นใจได้ว่าจะไม่มีเอฟเฟ็กต์โฮเวอร์แบบมองเห็นบนปุ่ม

ขั้นตอนที่ 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: ลบกฎ CSS ที่ประกอบด้วย `btn` และ`: hover`

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

รหัสเสร็จสมบูรณ์อยู่บนGitHubและNPM

การสาธิตการแสดงสดที่terrymorse.com


สิ่งนี้ไม่ได้ลบผลการโฮเวอร์สำหรับอุปกรณ์หน้าจอสัมผัสด้วยเมาส์ / แทร็กแพดหรือไม่
Jensei

@Jensei อาจเป็นไปได้ กฎโฮเวอร์จะถูกลบหากอุปกรณ์ตรงกัน@media (hover:none)หรือเมื่อผู้ใช้สัมผัสหน้าจอเป็นครั้งแรก คุณสามารถทดลองใช้งานได้ในหน้าสาธิตสดเพื่อให้แน่ใจ
terrymorse

0

คุณสามารถตั้งค่าสีพื้นหลังใน:activeสถานะและให้:focus พื้นหลัง defaut

หากคุณตั้งค่าสีพื้นหลังผ่านonfocus/ontouchสไตล์สีจะยังคงอยู่เมื่อ:focusสถานะหายไป
คุณต้องรีเซ็ตonblurเป็นเพื่อเรียกคืน defaut bg เมื่อโฟกัสหายไป


แต่ฉันต้องการคงประสิทธิภาพการโฮเวอร์ไว้สำหรับผู้ใช้เมาส์
Chris

: โฮเวอร์และ: แอคทีฟสามารถรับ CSS เดียวกันได้อยู่: มุ่งเน้นที่คุณมีปัญหา ที่จริงแล้วถ้าคุณตั้งค่าสีพื้นหลังผ่านออนโฟกัสสไตล์สีจะยังคงอยู่เมื่อโฟกัสได้หายไป คุณต้องรีเซ็ต onlur เช่นกันเพื่อกู้คืน defaut bg
G-Cyrillus

0

สิ่งนี้ใช้งานได้สำหรับฉัน: ใส่สไตล์โฉบในคลาสใหม่

.fakehover {background: red}

จากนั้นเพิ่ม / ลบคลาสตามที่ต้องการ

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

ทำซ้ำสำหรับ touchstart และ touchend events หรือเหตุการณ์ใดก็ตามที่คุณต้องการได้ผลลัพธ์ตามที่ต้องการยกตัวอย่างเช่นฉันต้องการให้เอฟเฟกต์โฮเวอร์ถูกสลับบนหน้าจอสัมผัส


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

คุณสามารถลองด้วยวิธีนี้

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

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="">ตั้งค่าแท็กร่างกายของคุณจะเป็นเช่นนี้ ฉันไม่ได้เป็นแฟนของ "แฮ็ค" นี้ แต่ช่วยให้ Safari บน iOS ตอบสนองต่อการสัมผัสได้ทันที ไม่แน่ใจว่าทำงานได้ดี แต่ทำงานอย่างไร

  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) หรือแม้กระทั่งเพิ่มหมดเวลาที่จะหยุดยั้งพวกเขา

การเปลี่ยนแปลงที่สำคัญเท่านั้นในรหัสของเราจะใช้คลาส HTML เพิ่มเติมเช่น<a class='hover'></a>ในองค์ประกอบที่ใช้พฤติกรรมใหม่

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

-

ฉันไม่มีอุปกรณ์ใดที่มีทั้งเมาส์และแตะเพื่อทดสอบอย่างถูกต้อง


0

จากปี 2020 คุณสามารถเพิ่มสไตล์การโฮเวอร์ภายในเคียวรีสื่อบันทึก

@media (hover: hover) and (pointer: fine) {
    /* css hover class/style */
}

เคียวรีสื่อบันทึกนี้ระบุว่าสไตล์จะทำงานกับเบราว์เซอร์ที่ไม่เลียนแบบ: โฮเวอร์ดังนั้นมันจะไม่ทำงานบนเบราว์เซอร์แบบสัมผัส

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.