Как сделать блокировку ссылок

Как сделать блокировку ссылок

От автора: недавно на работе была поднята тема того, как делается блокировка ссылок. В прошлом году каким-то образом к стилям наших шрифтов был добавлен якорь disabled, пока я этого не видел. Есть проблема: в HTML нет реального способа заблокировать тег a (с валидным атрибутом href). А зачем вообще это делать? Ссылки лежат в основе веба.

В какой-то момент я понял, что моим коллегам это не понравится, поэтому я начал думать, как реализовать блокировку ссылок. Понимая, что это потребует много времени, я хотел доказать, что затея не стоит тех усилий и кода, который придется поддерживать. Но я боялся, что если покажу, что это все-таки сделать можно, они проигнорируют все мои предупреждения и просто используют мой пример как доказательство того, что все в порядке. Меня это не потрясло, но я подумал, что вам может пригодиться мое исследование.

Во-первых:

Просто не делайте этого

Заблокированная ссылка уже не ссылка, это текст. Вам нужно пересмотреть дизайн, если в нем есть заблокированные ссылки.

В BootStrap есть примеры применения класса .disabled к якорям, я их ненавижу. По крайней мере, они сказали, что этот класс всего лишь добавляет стиль disabled. Формулировка вводит в заблуждение. Чтобы реально отключить ссылку, недостаточно просто придать ей вид отключенной ссылки.

Современные тенденции и подходы в веб-разработке

Узнайте алгоритм быстрого профессионального роста с нуля в сайтостроении

Узнать подробнее

Надежный способ: удалите href

Если вы приняли решение игнорировать мои предупреждения и все еще хотите заблокировать ссылку, то лучший способ, который я знаю – удалите href атрибут.

Из спецификации Hyperlink: «Атрибут href в тегах a и area необязателен; когда атрибут отсутствует, эти элементы не создают гиперссылки.»

У MDN определение попроще: «Для создания плейсхолдер ссылки этот атрибут можно пропустить (в HTML5). Плейсхолдер ссылка похожа на обычную ссылку, но она никуда не ведет.»

Стандартный JS код вставки и удаления атрибута href:

/* 
 * Use your preferred method of targeting a link
 *
 * document.getElementById('MyLink');
 * document.querySelector('.link-class');
 * document.querySelector('[href="https://unfetteredthoughts.net"]');
 */
// "Disable" link by removing the href property
link.href = '';
// Enable link by setting the href property
link.href = 'https://unfetteredthoughts.net';

Стилизовать через CSS тоже довольно просто:

a {
  /* Disabled link styles */
}
a:link, a:visited { /* or a[href] */
  /* Enabled link styles */
}

Этого мало, хочу что-то сложнее, чтобы казаться умнее!

Если хотите усложнить, то вот на что стоит смотреть. Надеюсь, вы поймете, что то, что я хочу вам показать, не стоит затраченных усилий.

Во-первых, ссылку необходимо стилизовать так, чтобы она выглядела отключенной.

.isDisabled {
  color: currentColor;
  cursor: not-allowed;
  opacity: 0.5;
  text-decoration: none;
}
<a class="isDisabled" href="https://unfetteredthoughts.net">Disabled Link</a>

Как сделать блокировку ссылок

Установка color в значение currentColor должна сбросить цвет шрифта к обычному, не ссылочному. Я также задал курсор not-allowed – при наведении на элемент показывается иконка, что взаимодействие невозможно. Мы упустили пользователей, у которых нет мыши, которые не могут навести курсор на элемент, которые в основном касаются экрана и клавиатуры. Далее необходимо прозрачность задать на половину. Согласно WCAG, отключенные элементы не обязаны соблюдать правила цветового контраста. Думаю, это очень рискованно, так как сейчас это просто текст, а снижение прозрачности на половину сильно затрудняет чтение пользователям с плохим зрением – еще одна причина, почему я ненавижу блокировку ссылок. И наконец, удаляем подчеркивание текста, так как подчеркивание явный признак ссылки. Теперь ссылка выглядит как заблокированная!

Современные тенденции и подходы в веб-разработке

Узнайте алгоритм быстрого профессионального роста с нуля в сайтостроении

Узнать подробнее

Но не совсем! Пользователь все еще может кликнуть, нажать пальцем на нее. Я уже слышу, как вы кричите pointer-events.

.isDisabled {
  ...
  pointer-events: none;
}

ОК, закончили! Ссылка отключена! Отключена только для пользователей с мышью и пользователей сенсорных устройств. А если браузер не поддерживает pointer-events? Согласно caniuse поддержка отсутствует в Opera Mini и IE<11. IE11 и Edge не поддерживают pointer-events, если display не задан в block или inline-block. Установка pointer-events в none переписывает наш курсор not-allowed, и пользователи с мышью опять будут думать, что ссылка рабочая. Все уже начинает разваливаться. Теперь необходимо поменять разметку и CSS…

.isDisabled {
  cursor: not-allowed;
  opacity: 0.5;
}
.isDisabled > a {
  color: currentColor;
  display: inline-block;  /* For IE11/ MS Edge bug */
  pointer-events: none;
  text-decoration: none;
}
<span class="isDisabled"><a href="https://unfetteredthoughts.net">Disabled Link</a></span>

Оборачивание ссылки в тег span и присвоение ему класса isDisabled дает нам половину стилей disabled. Забавно, но теперь класс disabled стал общим, и его можно использовать на других элементах (кнопках и элементах формы). Теперь реальная ссылка имеет pointer-events и text-decoration заданные в none.

А что с пользователями клавиатуры? Пользователи с клавиатурой будут активировать ссылку по ENTER. pointer-events только для курсоров, keyboard-events нет. Также нужно предотвратить активацию для старых браузеров без поддержки pointer-events. Теперь нужно подключить JS.

Подключаем JS

// After using preferred method to target link
link.addEventListener('click', function (event) {
  if (this.parentElement.classList.contains('isDisabled')) {
 event.preventDefault();
  }
});

Теперь наша ссылка выглядит отключенной и не реагирует на активацию по клику, нажатию и ENTER. Но и это не все! Пользователи скрин ридеров не знают, что эта ссылка отключена. Необходимо дать описание, что ссылка отключена. Атрибут disabled невалиден на ссылках, но мы можем указать aria-disabled=»true».

<span class="isDisabled"><a href="https://unfetteredthoughts.net" aria-disabled="true">Disabled Link</a></span>

Сейчас я стилизую ссылку по атрибуту aria-disabled. Люблю использовать ARIA атрибуты как хуки для CSS, так как присутствие неправильно стилизованных элементов является индикатором отсутствия важной доступности.

.isDisabled {
  cursor: not-allowed;
  opacity: 0.5;
}
a[aria-disabled="true"] {
  color: currentColor;
  display: inline-block;  /* For IE11/ MS Edge bug */
  pointer-events: none;
  text-decoration: none;
}

Теперь наша ссылка выглядит отключенной, ведет себя как отключенная и описана как отключенная.

К сожалению, даже если ссылка описана отключенной, некоторые скрин ридеры (JAWS) будут говорить, что она кликабельна. Они делают это для всех элементов, у которых есть обработчик события клика. Они делают это из-за тенденции разработчиков превращать неинтерактивные элементы типа div и span в псевдоинтерактивные с простым обработчиком. Здесь мы ничего сделать не можем. Мы не смогли обмануть вспомогательную технологию удалением всех признаков ссылки. Что еще ироничнее, потому что мы пытались обмануть ее раньше.

А что если переместить обработчик в body?

document.body.addEventListener('click', function (event) {
  // filter out clicks on any other elements
  if (event.target.nodeName == 'A' && event.target.getAttribute('aria-disabled') == 'true') {
 event.preventDefault();
  }
});

Получилось? Не совсем. В какой-то момент нам понадобится активировать эти ссылки. Поэтому необходимо написать код, который будет переключать состояние/поведение.

function disableLink(link) {
// 1. Add isDisabled class to parent span
  link.parentElement.classList.add('isDisabled');
// 2. Store href so we can add it later
  link.setAttribute('data-href', link.href);
// 3. Remove href
  link.href = '';
// 4. Set aria-disabled to 'true'
  link.setAttribute('aria-disabled', 'true');
}
function enableLink(link) {
// 1. Remove 'isDisabled' class from parent span
  link.parentElement.classList.remove('isDisabled');
// 2. Set href
  link.href = link.getAttribute('data-href');
// 3. Remove 'aria-disabled', better than setting to false
  link.removeAttribute('aria-disabled');
}

Теперь все. Теперь наша ссылка отключена визуально, функционально и семантически для всех пользователей. Это потребовало всего лишь 10 строк CSS, 15 строк JS (в том числе 1 обработчик в body) и 1 HTML тега.

Серьезно, ребят, не делайте этого.

Автор: Gerard Cohen

Источник: https://css-tricks.com/

Редакция: Команда webformyself.

Современные тенденции и подходы в веб-разработке

Узнайте алгоритм быстрого профессионального роста с нуля в сайтостроении

Узнать подробнее
Самые свежие новости IT и веб-разработки на нашем Telegram-канале

Практика HTML5 и CSS3 с нуля до результата!

Получите бесплатный пошаговый видеокурс по основам адаптивной верстки с полного нуля на HTML5 и CSS3

Получить

Метки:

Похожие статьи:

Комментарии Вконтакте:

Комментарии Facebook:

Комментарии (2)

  1. Div.Overlow

    Серьезно, ребят, не делайте этого.
    Автор: Gerard Cohen
    - Спасибо автору, как вовремья статья, по щучему велению прямо

  2. Div.Overlow

    Спасибо за публикацию статьи и автору, очень к стати и вовремья как раз нужно

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Я не робот.

Spam Protection by WP-SpamFree