: คลาสหลอกที่ใช้งานไม่ได้ทำงานในซาฟารีมือถือ


109

ใน Webkit บน iPhone / iPad / iPod การระบุสไตล์สำหรับ: คลาสหลอกที่ใช้งานอยู่สำหรับ<a>แท็กจะไม่ทริกเกอร์เมื่อคุณแตะที่องค์ประกอบ ฉันจะทำให้สิ่งนี้ทริกเกอร์ได้อย่างไร รหัสตัวอย่าง:

<style> 
a:active { 
    background-color: red;
}
</style>
<!-- snip -->
<a href="#">Click me</a>

คำตอบ:


238
<body ontouchstart="">
    ...
</body>

ใช้เพียงครั้งเดียวซึ่งตรงข้ามกับทุกองค์ประกอบของปุ่มดูเหมือนจะแก้ไขปุ่มทั้งหมดในหน้า หรือคุณสามารถใช้ไลบรารี JS ขนาดเล็กที่เรียกว่า ' Fastclick ' เร่งเหตุการณ์การคลิกบนอุปกรณ์สัมผัสและดูแลปัญหานี้ด้วย


19
ไม่เพียงพอที่จะเพิ่มontouchstartโดยไม่ต้อง=""? (HTML5)
feklee

2
สำหรับผู้อ่านใด ๆ ในอนาคตผมได้โพสต์สาธิตที่นี่: http://jsbin.com/EjiWILe/3/ ตรวจสอบการทำงานบนอุปกรณ์ iOS ของคุณ
mhulse

6
คุณอธิบายได้ไหมว่าทำไมคุณถึงใช้ตัวฟังที่ว่างเปล่ากับร่างกาย? มันทำงานอย่างไร?
Maurizio Battaghini

2
ฉันใช้: โฟกัสและมันก็ใช้ได้เช่นกัน ขอบคุณสำหรับเวทมนตร์
TecBrat

ฉันได้รับหน้าค้างบน iOS 9.1 และ 9.3 โดยใช้วิธีนี้ ... เวอร์ชันเหล่านั้นมีข้อผิดพลาด js แต่ยังมีผู้ใช้ 0.5% ในระบบปฏิบัติการเหล่านั้น
Ruskin

55

ตามที่คำตอบอื่น ๆ ระบุไว้ iOS Safari จะไม่เรียก:activeใช้คลาสหลอกเว้นแต่ว่าจะมีการเชื่อมต่อเหตุการณ์การสัมผัสเข้ากับองค์ประกอบ แต่จนถึงขณะนี้พฤติกรรมนี้ "วิเศษ" ฉันเจอคำประกาศเล็กน้อยนี้ในไลบรารีนักพัฒนา Safariที่อธิบายไว้ (เน้นของฉัน):

คุณยังสามารถใช้-webkit-tap-highlight-colorคุณสมบัติ CSS ร่วมกับการตั้งค่าเหตุการณ์การสัมผัสเพื่อกำหนดค่าปุ่มต่างๆให้ทำงานคล้ายกับเดสก์ท็อป ใน iOS เหตุการณ์ของเมาส์จะถูกส่งไปอย่างรวดเร็วจนไม่ได้รับสถานะการหยุดทำงานหรือสถานะแอ็คทีฟ ดังนั้น:activeสถานะหลอกจะถูกทริกเกอร์ก็ต่อเมื่อมีการตั้งค่าเหตุการณ์การสัมผัสบนองค์ประกอบ HTML ตัวอย่างเช่นเมื่อตั้งค่า ontouchstart บนองค์ประกอบดังนี้:

<button class="action" ontouchstart=""
        style="-webkit-tap-highlight-color: rgba(0,0,0,0);">
    Testing Touch on iOS
</button>

ตอนนี้เมื่อแตะปุ่มค้างไว้บน iOS ปุ่มจะเปลี่ยนเป็นสีที่ระบุโดยไม่มีสีเทาโปร่งใสโดยรอบปรากฏขึ้น

กล่าวอีกนัยหนึ่งคือการตั้งค่าontouchstartเหตุการณ์ (แม้ว่าจะว่างเปล่า) เป็นการบอกให้เบราว์เซอร์ตอบสนองต่อเหตุการณ์การสัมผัสอย่างชัดเจน

ในความคิดของฉันนี่เป็นพฤติกรรมที่มีข้อบกพร่องและอาจย้อนกลับไปในช่วงเวลาที่เว็บ "มือถือ" ไม่มีอยู่จริง (ดูภาพหน้าจอเหล่านั้นในหน้าที่เชื่อมโยงเพื่อดูว่าฉันหมายถึงอะไร) และทุกอย่างเน้นที่เมาส์ เป็นที่น่าสนใจที่จะทราบว่าเบราว์เซอร์มือถืออื่น ๆ ที่ใหม่กว่าเช่นบน Android แสดงสถานะหลอก `` ใช้งาน 'เมื่อสัมผัสได้ดีโดยไม่ต้องแฮ็กใด ๆ เช่นสิ่งที่จำเป็นสำหรับ iOS

(หมายเหตุด้านข้าง: หากคุณต้องการใช้สไตล์ที่กำหนดเองบน iOS คุณสามารถปิดใช้งานกล่องโปร่งแสงสีเทาเริ่มต้นที่ iOS ใช้แทนสถานะ:activeหลอกโดยใช้-webkit-tap-highlight-colorคุณสมบัติ CSS ตามที่อธิบายไว้ในหน้าที่เชื่อมโยงเดียวกันด้านบน .)


หลังจากการทดลองบางครั้งวิธีแก้ปัญหาที่คาดไว้ในการตั้งค่าontouchstartเหตุการณ์ใน<body>องค์ประกอบที่เหตุการณ์สัมผัสทั้งหมดแล้วฟองจะทำงานได้ไม่เต็มที่ หากองค์ประกอบสามารถมองเห็นได้ในวิวพอร์ตเมื่อหน้าโหลดแสดงว่าทำงานได้ดี แต่การเลื่อนลงและแตะองค์ประกอบที่อยู่นอกวิวพอร์ตจะไม่ทำให้เกิดสถานะ:activeหลอกอย่างที่ควรจะเป็น ดังนั้นแทนที่จะเป็น

<!DOCTYPE html>
<html><body ontouchstart></body></html>

แนบเหตุการณ์กับองค์ประกอบทั้งหมดแทนที่จะอาศัยเหตุการณ์ที่เกิดขึ้นกับร่างกาย (โดยใช้ jQuery):

$('body *').on('touchstart', function (){});

อย่างไรก็ตามฉันไม่ทราบถึงผลกระทบด้านประสิทธิภาพของสิ่งนี้ดังนั้นโปรดระวัง


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


6
คำอธิบายที่ยอดเยี่ยมเกี่ยวกับสาเหตุและวิธีการ ! ขอบคุณ!
coderfin

6
ได้รับการโหวตเพื่อให้ผู้พัฒนาเข้าใจไม่ใช่แค่สูตร "เวทมนตร์" นี่เป็นข้อมูลที่ให้ข้อมูลมากกว่าข้อมูลอื่น ๆ อย่างไม่มีที่สิ้นสุด ขอบคุณที่เขียนสิ่งนี้ให้เรา
user508633

เพิ่มคะแนนสำหรับคำอธิบายโดยละเอียด + คำเตือน นี่น่าจะเป็นคำตอบที่ถูกต้อง
Master of Ducks

39

เพิ่มตัวจัดการเหตุการณ์สำหรับ ontouchstart ในแท็ก <a> ของคุณ สิ่งนี้ทำให้ CSS ทำงานได้อย่างน่าอัศจรรย์

<a ontouchstart="">Click me</a>

3
ขออภัยนี่เป็นคำตอบเก่า แต่ทำไมถึงใช้ได้ ฉันไม่คิดว่าจะเป็นเหตุผล "มหัศจรรย์" แต่ถ้าคุณสามารถอธิบายได้ว่าทำไมมันถึงได้ผลฉันอยากอ่านรายละเอียดเพิ่มเติม
mhulse

1
@mhulse ฉันอยากรู้ว่าทำไม
Jesse Rusak

ฮา! เราอยู่ในเรือลำเดียวกัน ฉันจะพยายามหาข้อมูลและโพสต์ลิงก์กลับไปที่ (กึ่ง) เอกสารทางการเกี่ยวกับเรื่องนี้ ฉันชอบที่เทคนิคนี้ใช้ได้ผลฉันแค่สงสัยว่าทำไม?
mhulse

7

สิ่งนี้ใช้ได้กับฉัน:

document.addEventListener("touchstart", function() {},false);

หมายเหตุ: หากคุณทำเคล็ดลับนี้คุณควรลบค่าเริ่มต้นของการแตะ - ไฮไลต์สี Mobile Safari โดยใช้กฎ CSS ต่อไปนี้

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

5

เมื่อวันที่ 8 ธันวาคม 2016 คำตอบที่ยอมรับ ( <body ontouchstart="">...</body>) ใช้ไม่ได้กับฉันใน Safari 10 (iPhone 5s): แฮ็คนั้นใช้ได้กับองค์ประกอบที่มองเห็นได้ในการโหลดหน้าเว็บเท่านั้น

อย่างไรก็ตามการเพิ่ม:

<script type='application/javascript'>
  document.addEventListener("touchstart", function() {}, false);
</script>

เพื่อให้headทำงานได้ตามที่ฉันต้องการโดยมีข้อเสียคือตอนนี้เหตุการณ์การสัมผัสทั้งหมดในระหว่างการเลื่อนยังทำให้เกิดสถานะ:activeหลอกบนองค์ประกอบที่สัมผัส (หากนี่เป็นปัญหาสำหรับคุณคุณอาจพิจารณาวิธีแก้ปัญหาของ FighterJet :hover )


4
//hover for ios
-webkit-tap-highlight-color: #ccc;

สิ่งนี้ใช้ได้ผลสำหรับฉันเพิ่มใน CSS ของคุณในองค์ประกอบที่คุณต้องการเน้น


3

คุณใช้คลาสหลอกทั้งหมดหรือแค่คลาสเดียว? หากคุณใช้อย่างน้อยสองอย่างตรวจสอบให้แน่ใจว่าอยู่ในลำดับที่ถูกต้องไม่เช่นนั้นทั้งหมดจะแตก:

a:link
a:visited
a:hover
a:active

..เพื่อให้. นอกจากนี้หากคุณเพิ่งใช้: active ให้เพิ่มลิงก์: แม้ว่าคุณจะไม่ได้จัดแต่งทรงผมก็ตาม


เคล็ดลับดีๆเกี่ยวกับการสั่งซื้อมีความสำคัญเมื่อจัดแต่งทรงผมชั้นเรียนหลอก
brianarpie

1

ฉันได้เผยแพร่เครื่องมือที่ควรแก้ปัญหานี้ให้คุณแล้ว

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

สิ่งนี้ควรแก้ปัญหาทั้งหมดในครั้งเดียว: https://www.npmjs.com/package/active-touch

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

ข้อเสนอแนะที่เป็นประโยชน์และเป็นประโยชน์ชื่นชมมาก!


2
ไลบรารีนั้นเพิ่มผู้ฟังเหตุการณ์ 9 (ไม่ใช่แบบพาสซีฟ) ให้กับทุกองค์ประกอบลิงก์ แต่ไม่เรียก removeEventListener - นี่จะเป็นข้อบกพร่องใหญ่สำหรับแอปพลิเคชันหน้าเดียวที่ฉันคิด
Drenai

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

1

สำหรับผู้ที่ไม่ต้องการใช้ ontouchstart คุณสามารถใช้รหัสนี้ได้

<script>
 document.addEventListener("touchstart", function(){}, true);
</script>

1

ฉันลองใช้คำตอบนี้และรูปแบบต่างๆ แต่ดูเหมือนจะไม่มีอะไรทำงานได้อย่างน่าเชื่อถือ (และฉันไม่ชอบที่จะใช้ 'เวทมนตร์' สำหรับสิ่งต่างๆเช่นนี้) ดังนั้นฉันจึงทำสิ่งต่อไปนี้แทนซึ่งทำงานได้อย่างสมบูรณ์บนทุกแพลตฟอร์มไม่ใช่แค่ Apple:

  1. ประกาศ CSS เปลี่ยนชื่อที่ใช้ในการ:active.active
  2. สร้างรายการองค์ประกอบที่ได้รับผลกระทบทั้งหมดและเพิ่มpointerdown/mousedown/touchstartตัวจัดการเหตุการณ์เพื่อใช้.activeคลาสและpointerup/mouseup/touchendตัวจัดการเหตุการณ์เพื่อลบออก ใช้ jQuery:

    let controlActivationEvents = window.PointerEvent ? "pointerdown" : "touchstart mousedown";
    let controlDeactivationEvents = window.PointerEvent ? "pointerup pointerleave" : "touchend mouseup mouseleave";
    
    let clickableThings = '<comma separated list of selectors>';
    $(clickableThings).on(controlActivationEvents,function (e) {
        $(this).addClass('active');
    }).on(controlDeactivationEvents, function (e) {
        $(this).removeClass('active');
    });

มันค่อนข้างน่าเบื่อ แต่ตอนนี้ฉันมีวิธีแก้ปัญหาที่เสี่ยงต่อการแตกระหว่าง Apple OS เวอร์ชันน้อยกว่า (และใครต้องการอะไรแบบนี้?)


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

0

วิธีแก้ปัญหาคือการพึ่งพา:targetแทน:active:

<style> 
a:target { 
    background-color: red;
}
</style>
<!-- snip -->
<a id="click-me" href="#click-me">Click me</a>

สไตล์จะถูกเรียกใช้เมื่อจุดยึดถูกกำหนดเป้าหมายโดย URL ปัจจุบันซึ่งมีประสิทธิภาพแม้ในอุปกรณ์เคลื่อนที่ ข้อเสียคือคุณต้องมีลิงค์อื่นเพื่อล้างจุดยึดใน url ตัวอย่างที่สมบูรณ์:

a:target { 
    background-color: red;
}
<a id="click-me" href="#click-me">Click me</a>
<a id="clear" href="#">Clear</a>


-3

ไม่มีความเกี่ยวข้องกับคำถามนี้ 100% แต่คุณสามารถใช้ css sibling hack เพื่อบรรลุเป้าหมายนี้ได้เช่นกัน

HTML

<input tabindex="0" type="checkbox" id="145"/>
<label for="145"> info</label>
<span> sea</span>

วทส

input {
    &:checked + label {
      background-color: red;
    }
  }

หากคุณต้องการใช้คำแนะนำเครื่องมือ html / css บริสุทธิ์

span {
  display: none;
}
input {
    &:checked ~ span {
      display: block;
    }
  }

-6
<!DOCTYPE html>

<html lang="en">

<head>
<meta charset="utf-8">

<title></title>

<style>
        a{color: red;}
        a:hover{color: blue;}
</style>
</head>

<body>

        <div class="main" role="main">
                <a href="#">Hover</a>
        </div>

</body>
</html>

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