: lớp giả hoạt động không hoạt động trong safari di động


109

Trong Webkit trên iPhone / iPad / iPod, việc chỉ định kiểu cho một: lớp giả hoạt động cho một <a>thẻ không kích hoạt khi bạn nhấn vào phần tử. Làm cách nào để kích hoạt cái này? Mã ví dụ:

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

Câu trả lời:


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

Chỉ áp dụng một lần, trái ngược với mọi phần tử nút dường như sửa chữa tất cả các nút trên trang. Ngoài ra, bạn có thể sử dụng thư viện JS nhỏ này có tên là ' Fastclick '. Nó tăng tốc độ các sự kiện nhấp chuột trên thiết bị cảm ứng và cũng xử lý vấn đề này.


19
Chỉ cần thêm ontouchstartmà không có dấu là đủ =""? (HTML5)
feklee

2
Đối với bất kỳ độc giả nào trong tương lai, tôi đã đăng một bản demo tại đây: http://jsbin.com/EjiWILe/3/ . Kiểm tra chức năng trên thiết bị iOS của bạn.
mhulse 19/1213

6
Bạn có thể giải thích lý do tại sao bạn đã áp dụng một trình nghe trống cho cơ thể? Nó làm việc như thế nào?
Maurizio Battaghini

2
Tôi đã sử dụng: focus và điều này cũng hoạt động cho điều đó. Cảm ơn vì Magic.
TecBrat

Tôi nhận được đóng băng trang trên iOS 9.1 và 9.3 sử dụng phương pháp này ... những phiên bản đã có một lỗi js, nhưng vẫn có 0,5% người dùng trên các hệ điều hành
Ruskin

55

Như các câu trả lời khác đã nêu, iOS Safari không kích hoạt lớp :activegiả trừ khi một sự kiện cảm ứng được gắn vào phần tử, nhưng cho đến nay hành vi này là "phép thuật". Tôi đã xem qua điều này trên Thư viện nhà phát triển Safari giải thích nó (tôi nhấn mạnh):

Bạn cũng có thể sử dụng thuộc tính -webkit-tap-highlight-colorCSS kết hợp với việc đặt sự kiện cảm ứng để định cấu hình các nút hoạt động tương tự như màn hình. Trên iOS, các sự kiện chuột được gửi nhanh đến mức không bao giờ nhận được trạng thái hoạt động hoặc ngừng hoạt động. Do đó, :activetrạng thái giả chỉ được kích hoạt khi có sự kiện chạm được đặt trên phần tử HTML — ví dụ: khi ontouchstart được đặt trên phần tử như sau:

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

Giờ đây khi nhấn và giữ nút trên iOS, nút sẽ chuyển sang màu được chỉ định mà không xuất hiện màu xám trong suốt xung quanh.

Nói cách khác, việc thiết lập một ontouchstartsự kiện (ngay cả khi nó trống) là thông báo rõ ràng cho trình duyệt phản ứng với các sự kiện chạm.

Theo ý kiến ​​của tôi, đây là hành vi thiếu sót, và có lẽ đã có từ thời điểm web "di động" về cơ bản không tồn tại (hãy xem những ảnh chụp màn hình đó trên trang được liên kết để hiểu ý tôi), và mọi thứ đều được định hướng bằng chuột. Điều thú vị cần lưu ý là các trình duyệt di động khác, mới hơn, chẳng hạn như trên Android, hiển thị trạng thái giả `: active 'khi chạm tốt mà không có bất kỳ hack nào như những gì cần thiết cho iOS.

(Lưu ý: Nếu bạn muốn sử dụng các kiểu tùy chỉnh của riêng mình trên iOS, bạn cũng có thể tắt hộp mờ màu xám mặc định mà iOS sử dụng thay cho :activetrạng thái giả bằng cách sử dụng thuộc tính -webkit-tap-highlight-colorCSS, như được giải thích trong cùng một trang được liên kết ở trên .)


Sau một số thử nghiệm, giải pháp dự kiến ​​đặt ontouchstartsự kiện trên <body>phần tử mà tất cả các sự kiện chạm vào bong bóng không hoạt động đầy đủ. Nếu phần tử hiển thị trong chế độ xem khi tải trang, thì phần tử đó hoạt động tốt, nhưng việc cuộn xuống và nhấn vào một phần tử nằm ngoài chế độ xem không kích hoạt :activetrạng thái giả như nó nên làm. Vì vậy, thay vì

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

đính kèm sự kiện vào tất cả các phần tử thay vì dựa vào sự kiện nổi lên phần thân (sử dụng jQuery):

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

Tuy nhiên, tôi không biết về tác động hiệu suất của điều này, vì vậy hãy cẩn thận.


CHỈNH SỬA: Có một lỗ hổng nghiêm trọng với giải pháp này: ngay cả khi chạm vào một phần tử trong khi cuộn trang sẽ kích hoạt :activetrạng thái giả. Độ nhạy quá mạnh. Android giải quyết vấn đề này bằng cách tạo ra một độ trễ rất nhỏ trước khi trạng thái được hiển thị, trạng thái này sẽ bị hủy nếu trang được cuộn. Về vấn đề này, tôi khuyên bạn chỉ nên sử dụng điều này trên các phần tử được chọn. Trong trường hợp của tôi, tôi đang phát triển một ứng dụng web để sử dụng trong lĩnh vực này về cơ bản là danh sách các nút để điều hướng các trang và gửi hành động. Vì toàn bộ trang có khá nhiều nút trong một số trường hợp, điều này sẽ không hiệu quả với tôi. Tuy nhiên, bạn có thể đặt :hovertrạng thái giả để điền vào thay thế. Sau khi vô hiệu hóa hộp màu xám mặc định, điều này hoạt động hoàn hảo.


6
Giải thích tuyệt vời về lý do tại sao và không chỉ là như thế nào ! Cảm ơn!
coderfin

6
Được ủng hộ vì mang lại cho các nhà phát triển sự hiểu biết, không chỉ là một công thức "ma thuật". Điều này vô cùng nhiều thông tin hơn những cái khác; cảm ơn bạn đã viết điều này cho chúng tôi.
user508633

Được ủng hộ cho lời giải thích chi tiết + cảnh báo. Đây phải là câu trả lời chính xác.
Master of Ducks

39

Thêm trình xử lý sự kiện cho ontouchstart trong thẻ <a> của bạn. Điều này làm cho CSS hoạt động một cách kỳ diệu.

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

3
Xin lỗi, đây là câu trả lời cũ, nhưng tại sao câu trả lời này vẫn hoạt động? Tôi không bận tâm về lý do "kỳ diệu", nhưng nếu bạn có thể giải thích tại sao nó hoạt động, tôi rất muốn đọc thêm chi tiết.
mhulse

1
@mhulse Tôi cũng muốn biết tại sao.
Jesse Rusak

Ha! Chúng ta cùng thuyền. Tôi sẽ cố gắng thực hiện một số nghiên cứu và đăng lại đây một liên kết đến các tài liệu chính thức (bán) về vấn đề này. Tôi thích kỹ thuật này hoạt động, tôi chỉ tự hỏi tại sao?
mhulse

7

Điều này phù hợp với tôi:

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

Lưu ý: nếu bạn thực hiện thủ thuật này, bạn cũng nên xóa màu nhấn-đánh dấu mặc định Mobile Safari áp dụng bằng cách sử dụng quy tắc CSS sau.

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

5

Kể từ ngày 8 tháng 12 năm 2016, câu trả lời được chấp nhận ( <body ontouchstart="">...</body>) không hoạt động đối với tôi trên Safari 10 (iPhone 5s): Bản hack đó chỉ hoạt động đối với những phần tử hiển thị khi tải trang.

Tuy nhiên, thêm:

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

đến headlàm việc theo cách tôi muốn, với nhược điểm mà bây giờ tất cả các sự kiện liên lạc trong di chuyển cũng kích hoạt các :activepseudo-nhà nước về các yếu tố xúc động. (Nếu đây là vấn đề với bạn, bạn có thể xem xét giải pháp thay thế của FighterJet :hover .)


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

Điều này phù hợp với tôi, hãy thêm vào CSS của bạn trên phần tử mà bạn muốn đánh dấu


3

Bạn đang sử dụng tất cả các lớp giả hay chỉ một lớp? Nếu bạn đang sử dụng ít nhất hai, hãy đảm bảo rằng chúng theo đúng thứ tự nếu không tất cả đều bị hỏng:

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

..trong đơn đặt hàng đó. Ngoài ra, nếu bạn chỉ đang sử dụng: active, hãy thêm: link, ngay cả khi bạn không tạo kiểu cho nó.


mẹo hay về thứ tự quan trọng khi tạo kiểu lớp giả.
brianarpie

1

Tôi đã xuất bản một công cụ có thể giải quyết vấn đề này cho bạn.

Bề ngoài, vấn đề trông có vẻ đơn giản, nhưng trên thực tế, hành vi chạm và nhấp cần được tùy chỉnh khá rộng rãi, bao gồm các chức năng thời gian chờ và những thứ như "điều gì xảy ra khi bạn cuộn danh sách liên kết" hoặc "điều gì xảy ra khi bạn nhấn vào liên kết và sau đó di chuyển chuột / ngón tay ra khỏi khu vực hoạt động "

Điều này sẽ giải quyết tất cả cùng một lúc: https://www.npmjs.com/package/active-touch

Bạn sẽ cần phải gán các kiểu: active cho lớp .active hoặc chọn tên lớp của riêng bạn. Theo mặc định, tập lệnh sẽ hoạt động với tất cả các phần tử liên kết, nhưng bạn có thể ghi đè nó bằng mảng bộ chọn của riêng mình.

Phản hồi trung thực, hữu ích và đóng góp được đánh giá cao!


2
Thư viện đó thêm 9 trình nghe sự kiện (không thụ động) vào mỗi phần tử liên kết nhưng không gọi removeEventListener - đây sẽ là một lỗ hổng lớn đối với các ứng dụng trang đơn, tôi nghĩ
Drenai

1
Cảm ơn Ryan. Tôi đã không hỗ trợ hoặc sử dụng mã này trong hơn một năm; Tôi sẽ gỡ nó xuống. Sau một số suy nghĩ và thử nghiệm, tôi đã thay đổi thiết kế của ứng dụng thay vì cố gắng ép buộc các tương tác không được trình duyệt tính đến hoặc nghĩ đến.
dmitrizzle

1

Đối với những người không muốn sử dụng ontouchstart, bạn có thể sử dụng mã này

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

1

Tôi đã thử câu trả lời này và các biến thể của nó, nhưng không có câu trả lời nào có vẻ hoạt động đáng tin cậy (và tôi không thích dựa vào 'ma thuật' cho những thứ như thế này). Vì vậy, thay vào đó, tôi đã làm như sau, hoạt động hoàn hảo trên tất cả các nền tảng, không chỉ Apple:

  1. Khai báo css đổi tên được sử dụng :activeđể .active.
  2. Tạo danh sách tất cả các phần tử bị ảnh hưởng và thêm pointerdown/mousedown/touchstarttrình xử lý sự kiện để áp dụng trình xử lý .activelớp và pointerup/mouseup/touchendsự kiện để loại bỏ nó. Sử dụng 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');
    });

Điều này hơi tẻ nhạt, nhưng bây giờ tôi đã có một giải pháp ít bị hỏng hơn giữa các phiên bản hệ điều hành của Apple. (Và ai cần một cái gì đó như thế này phá vỡ?)


Tôi nghĩ rằng nó cung cấp một câu trả lời cho câu hỏi. Dường như không có cách nào đáng tin cậy để làm cho: lớp giả hoạt động hoạt động trên Safari di động. Nhưng điều này có thể được mô phỏng một cách đáng tin cậy bằng cách sử dụng giải pháp tôi đã đưa ra. Tôi đã thực hiện điều này trong ứng dụng của mình và nó hoạt động hoàn hảo trên tất cả các nền tảng. Và tôi đã thêm mã bằng cách làm rõ.
daffinm

0

Một giải pháp là dựa vào :targetthay vì :active:

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

Kiểu sẽ được kích hoạt khi mỏ neo được nhắm mục tiêu bởi url hiện tại, url này mạnh mẽ ngay cả trên thiết bị di động. Hạn chế là bạn cần một liên kết khác để xóa neo trong url. Toàn bộ ví dụ:

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


-3

Không liên quan 100% đến câu hỏi này, nhưng bạn có thể sử dụng hack css anh chị em để đạt được điều này

HTML

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

SCSS

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

Nếu bạn muốn sử dụng chú giải công cụ html / css thuần túy

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
Theo Câu hỏi thường gặp, chữ ký và tự quảng cáo không được phép.
LittleBobbyTables - Au Revoir,
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.