: активний псевдоклас не працює в мобільному сафарі


109

В Webkit на iPhone / iPad / iPod із зазначенням стилів для: активного псевдокласу для an <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
Чи можете ви пояснити, чому ви застосували порожній слухач до тіла? Як це працює?
Мауріціо Баттагіні

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, відображають псевдо-стан `` active 'на дотик просто чудово, без будь-яких злому, як те, що потрібно для iOS.

(Побічна примітка. Якщо ви хочете використовувати власні власні стилі на iOS, ви також можете відключити сірий напівпрозорий вікно за замовчуванням, яке iOS використовує замість :activeпсевдодержави, використовуючи -webkit-tap-highlight-colorвластивість CSS, як пояснено на тій самій пов’язаній сторінці вище .)


Після деякого експерименту очікуване рішення встановити ontouchstartподію на <body>елемент, до якого всі торкаються події, а потім бульбашки, працює не повністю. Якщо елемент видно у вікні перегляду під час завантаження сторінки, він працює добре, але прокручування вниз та натискання елемента, який був поза вікном перегляду, не означає запускає :activeпсевдо-стан як слід. Отже, замість

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

прикріпіть подію до всіх елементів, а не покладайтеся на те, що подія піднімається до тіла (використовуючи jQuery):

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

Однак я не знаю наслідків цього для продуктивності, тому будьте обережні.


EDIT: У цьому рішенні є одна серйозна вада: навіть торкання елемента під час прокрутки сторінки активує :activeпсевдо-стан. Чутливість занадто сильна. Android вирішує це, вводячи дуже невелику затримку до появи стану, яке скасовується, якщо сторінка прокручується. Зважаючи на це, я пропоную використовувати це лише для вибраних елементів. У моєму випадку я розробляю веб-додаток для використання у цій галузі, яка в основному є переліком кнопок для навігації по сторінках та подання дій. Оскільки у всій сторінці в деяких випадках є кнопки, це не працює для мене. Однак ви можете встановити :hoverпсевдодержаву, щоб замість цього заповнити. Після відключення сірого поля за замовчуванням це працює чудово.


6
Чудове пояснення того, чому і не тільки як ! Дякую!
кодерфін

6
Захищений для того, щоб дати розбіжникам зрозуміти, а не просто "чарівний" рецепт. Це нескінченно більш інформативно, ніж інші; дякую, що ви написали це для нас.
user508633

Запропоновано для детального пояснення + застереження. Це має бути правильна відповідь.
Майстер качок

39

Додайте обробник події для ontouchstart у свій тег <a>. Це змушує CSS магічно працювати.

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

3
Вибачте, це стара відповідь, але чому це працює? Я не заперечую "магічно" як причину, але якщо ви можете пояснити, чому це працює, я хотів би прочитати більше деталей.
mhulse

1
@mhulse Я також хотів би знати, чому.
Джессі Русак

Га! Ми в одному човні. Я спробую провести кілька досліджень і опублікувати тут посилання на (напів-) офіційні документи з цього питання. Мені подобається, що ця техніка працює, мені просто цікаво, чому?
mhulse

7

Це працює для мене:

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

Примітка: якщо ви зробите цей трюк, також варто видалити стандартний колір, що торкається та підкреслить, мобільний 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псевдо-стану на порушених елементів. (Якщо це проблема для вас, ви можете розглянути можливість :hover вирішення проблеми FighterJet .)


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 або вибрати власне ім’я класу. За замовчуванням сценарій буде працювати з усіма елементами посилання, але ви можете перезаписати його власним масивом селекторів.

Чесний, корисний відгук та внесок дуже цінується!


2
Ця бібліотека додає 9 (не пасивних) слухачів подій до кожного елемента посилання, але не викликає deleteEventListener - це буде великим недоліком для додатків для однієї сторінки, я думаю
Drenai

1
Дякую Райан Я не підтримую або використовую цей код більше року; Я його зніму. Після декількох роздумів та експериментів я змінив дизайн програми, замість того, щоб намагатися змусити взаємодії, які не враховувались і не продумані браузерами.
Дмитріс

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. (А кому потрібно щось на кшталт цього зламу?)


Я думаю, що це дає відповідь на питання. Здається, немає надійного способу змусити активний псевдоклас працювати на мобільному Safari. Але це можна надійно наслідувати за допомогою наданого нами рішення. Я це зробив у своєму додатку, і він прекрасно працює на всіх платформах. І я додав код для уточнення.
нарцис

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 і для цього

HTML

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

SCSS

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
Відповідно до FAQ, підписи та самореклама забороняються.
LittleBobbyTables - Au Revoir
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.