Кратко
СкопированоSkip link (далее скип-линк) — специальный элемент на странице в виде гиперссылки, который помогает быстро перейти к контенту при использовании клавиатуры, пропустив блок с навигацией.
Обычно скип-линк используют для пропуска меню навигации вверху страницы, но область применения ничем не ограничена. Например, можно сделать переход из начала секции с комментариями к полю ввода нового комментария. Главное — не переборщить. Большое число ссылок может запутать пользователя.
Пример
СкопированоДля примера давайте откроем страницу задачи по добавлению доки про скип-линк. У GitHub вверху расположено меню, в котором есть строка поиска, ссылка на страницу пулреквестов и много чего ещё. Если мы будем переходить по разным страницам, то придётся кучу раз нажать Tab, чтобы добраться до контента.
К счастью, GitHub добавляет на страницы скип-линк. Если нажать Tab, когда страница открылась и мы находимся в самом верху, то в верхнем левом углу появится блок с надписью «Skip to content». Если теперь нажмём Enter, то перейдём сразу к контенту. В нашем случае это будет интерфейс репозитория.
Как реализовать
СкопированоСамая простая реализация — якорная ссылка, которая видна только при фокусе. Тогда пользователи клавиатуры в первую очередь сфокусируются на ней, когда нажмут Tab. При этом скринридеры прочитают её, а пользователи мыши даже не будут знать о её существовании. Такая ссылка им не нужна.
Допустим, у нас есть сайт с простой навигацией:
Если будем использовать клавиатуру для навигации, то придётся 5 раз нажать Tab, чтобы добраться до основного контента. И так придётся делать на каждой новой странице.
Давайте добавим скип-линк, чтобы упростить навигацию. Для этого в самое начало <body>
перед блоком навигации добавим ссылку, которая видна только при фокусе.
<body> <a class="skip-link" href="#main"> Перейти к контенту </a> <!-- Навигация --> <main id="main"> <!-- Остальной контент страницы --> </main></body>
<body> <a class="skip-link" href="#main"> Перейти к контенту </a> <!-- Навигация --> <main id="main"> <!-- Остальной контент страницы --> </main> </body>
Заметьте, что мы скрываем ссылку при помощи transform
. Просто сделать display
нельзя, тогда скринридеры её проигнорируют.
.skip-link { display: block; position: absolute; top: 0; left: 50%; padding: 10px 15px; color: #18191c; background: #10F3AF; transform: translateY(-100%);}
.skip-link { display: block; position: absolute; top: 0; left: 50%; padding: 10px 15px; color: #18191c; background: #10F3AF; transform: translateY(-100%); }
Когда ссылка в фокусе, покажем её, вернув значение по умолчанию transform
:
.skip-link:focus { transform: translateY(20%);}
.skip-link:focus { transform: translateY(20%); }
Теперь на странице сразу же появится скип-линк, когда нажмём Tab. С её помощью можем сразу перейти к контенту, не тратя время на навигацию. Если всё-таки интересует какой-то пункт в меню, можем нажать Tab ещё раз. Тогда скип-линк скроется, а фокус окажется на первом интерактивном элементе на странице.
На практике
Скопированосоветует Скопировано
🛠 С этой и другими реализациями скип-линк есть проблемы во всех мобильных браузерах в iOS до 13 версии, Android до 10 версии, а ещё в некоторых версиях Chrome и в Safari 14.
В каких-то браузерах при свайпе, нажатии на Tab или на клавишу со стрелкой фокус перемещается не на контент, к которому ведёт ссылка, а на следующий элемент после ссылки. Где-то скип-линк вообще не получает фокус.
Если поддерживаете старые браузеры и операционные системы, хорошо учесть эти баги.
Для решения проблемы добавьте к <main>
или к другому блоку, куда ведёт скип-линк, tabindex
. Атрибут tabindex
с отрицательным значением удаляет элемент из последовательной навигации.
<body> <a class="skip-link" href="#main"> Перейти к контенту </a> <!-- Навигация --> <main id="main" tabindex="-1"> <!-- Остальной контент страницы --> </main></body>
<body> <a class="skip-link" href="#main"> Перейти к контенту </a> <!-- Навигация --> <main id="main" tabindex="-1"> <!-- Остальной контент страницы --> </main> </body>
Из-за этого возникнут побочные эффекты. При переходе к основному блоку теперь выделяется вся область с отрицательным tabindex
, а при клике по странице фокус вернётся в её начало. Это исправит JavaScript. После события клика у скип-линк нужно установить фокус на теге, к которому ведёт ссылка, и добавить к нему tabindex
. При потере фокуса этот атрибут нужно удалить.
Один из вариантов решения проблемы для десктопных браузеров.
(_ => { const skip_lnk = document.querySelector('.skip_lnk'); if (!skip_lnk) return false; skip_lnk.addEventListener('click', e => { e.preventDefault(); const to_obj = document.getElementById(skip_lnk.href.split('#')[1]); if (to_obj) { to_obj.setAttribute('tabindex', '-1'); to_obj.addEventListener('blur', _ => { to_obj.removeAttribute('tabindex'); }, {once: true}); to_obj.focus(); } });})();
(_ => { const skip_lnk = document.querySelector('.skip_lnk'); if (!skip_lnk) return false; skip_lnk.addEventListener('click', e => { e.preventDefault(); const to_obj = document.getElementById(skip_lnk.href.split('#')[1]); if (to_obj) { to_obj.setAttribute('tabindex', '-1'); to_obj.addEventListener('blur', _ => { to_obj.removeAttribute('tabindex'); }, {once: true}); to_obj.focus(); } }); })();
Вариант решения проблемы с багом у TalkBack на Android.
(_ => { const skip_lnk = document.querySelector('.skip_lnk'); if (!skip_lnk) return false; skip_lnk.addEventListener('click', e => { e.preventDefault(); const to_obj = document.getElementById(skip_lnk.href.split('#')[1]); if (to_obj) to_obj.focus(); });})();
(_ => { const skip_lnk = document.querySelector('.skip_lnk'); if (!skip_lnk) return false; skip_lnk.addEventListener('click', e => { e.preventDefault(); const to_obj = document.getElementById(skip_lnk.href.split('#')[1]); if (to_obj) to_obj.focus(); }); })();
🛠 Когда у вас несколько скип-линк, можно обернуть их в <nav>
и назвать эту группу с помощью aria
. Тогда пользователи скринридеров могут использовать эту область как ориентир и быстро перемещаться к ней с помощью клавиш или через меню с ориентирами.
<header> <nav aria-label="Ссылки для пропуска меню"> <a href="#search" class="skip-link">Перейти к поиску</a> <a href="#main" class="skip-link">Перейти к содержимому</a> </nav> <nav aria-label="Главная"> <!-- Основная навигация --> </nav> <form id="search"> <!-- Поиск по сайту --> </form></header><main id="main"> <!-- Остальной контент страницы --></main>
<header> <nav aria-label="Ссылки для пропуска меню"> <a href="#search" class="skip-link">Перейти к поиску</a> <a href="#main" class="skip-link">Перейти к содержимому</a> </nav> <nav aria-label="Главная"> <!-- Основная навигация --> </nav> <form id="search"> <!-- Поиск по сайту --> </form> </header> <main id="main"> <!-- Остальной контент страницы --> </main>
На собеседовании
СкопированоЭто вопрос без ответа. Вы можете помочь! Почитайте о том, как контрибьютить в Доку.