- PVSM.RU - https://www.pvsm.ru -

Создаём максимально недоступный сайт с идеальной оценкой Lighthouse

Встроенный инструмент тестирования Google Lighthouse оценивает доступность (accessibility) сайтов по шкале от 0 до 100. Похвально стремиться к максимальной читаемости контента, но оценка 100 не означает, что сайт идеально доступен. Для доказательства я провёл небольшой эксперимент.

Всегда приятно видеть, как люди хвастаются в твиттере своими оценками Lighthouse: это значит, что они заботятся о качестве.

Создаём максимально недоступный сайт с идеальной оценкой Lighthouse - 1

Lighthouse награждает лучшие сайты зелёным кружочком с цифрой 100, которую вы с гордостью показываете клиентам и друзьям.

Оценка качества кода важна, но ещё важнее правильно её интерпретировать. Если автоматический инструмент говорит, что сайт доступен на 100%, это не обязательно так. Это только значит, что мы заложили основу для тестирования вручную. Для тестов Lighthouse использует библиотеку axe-core [1] со своим набором правил [2]. Она выявляет некоторые плохие практики, но не все. Другие практики не плохи сами по себе, но могут быть вредными, если ими злоупотреблять.

Одним автоматическим тестированием вы не обеспечите хорошее качество. Для доказательства я создан максимально недоступный сайт с идеальной оценкой Lighthouse.

Предыстория

Зак Летерман недавно написал [3] в твиттере:

Бесплатная идея для статьи:

Как построить самый медленный веб-сайт с идеальной оценкой Lighthouse

И ответ Вадима Макеева [4] вдохновил меня на работу.

Было бы интересно почитать! Подкидываю идейку:
<img src=picture.png alt=picture.png>

Я подумал, что это замечательная мысль: не только запутать максимальное количество посетителей сайта, но и получить сверху идеальную оценку Lighthouse.

Отсекаем как можно больше людей

Возьмём за основу эту простую, хорошо доступную страницу.

Создаём максимально недоступный сайт с идеальной оценкой Lighthouse - 2

CodePen: Доступность 100%, шаг 0 [5]

Обязательный CSS

Начнём с простого. Я хочу убедиться, что мой идеальный веб-сайт не работает без CSS. Для этого добавляю атрибут hidden в элемент body. Это HTML-эквивалент display: none; в CSS (если хотите почитать о скрытии контента с сохранением доступности, см. «Инклюзивное скрытие» [6] Скотта О'Хары).

HTML

<body hidden>
  ...
</body>

Создаём максимально недоступный сайт с идеальной оценкой Lighthouse - 3
Идеально чистая страница

hidden визуально скрывает содержимое и удаляет его из дерева доступности (accessibility tree). Одного этого достаточно, чтобы устранить абсолютно всех посетителей и пройти тесты Lighthouse, но мы не ищем лёгких путей. Я хочу создать сайт, который совершенно недоступен и технически всё ещё отображает контент. Итак, добавим CSS и вернём контент обратно.

HTML

<head>
  <link rel="stylesheet" href="style.css">
</head>
<body class="loaded" hidden>
  ...
</body>

CSS

.loaded {
  display: block;
}

Мы вернулись к тому, что было раньше, но теперь должен загружаться CSS.

CodePen: доступность 100%, шаг 1 [7]

Обязательный JS

Добавим ещё одну зависимость. Класс для отображения контента я теперь добавляю не в HTML, а через JS.

HTML

<head>
  <link rel="stylesheet" href="style.css">
  <script src="script.js"></script>
</head>

<body hidden>
  ...
</body>

JS

  document.querySelector('body').classList.add('loaded');

Здорово! Сайт по-прежнему не изменился, но чтобы отображать хоть какой-то контент, обязательно должны загружаться и правильно работать файлы CSS и JS.

CodePen: доступность 100%, шаг 2 [8]

Кажется, пришло время для первого испытания Lighthouse. Скрестим пальцы!

Создаём максимально недоступный сайт с идеальной оценкой Lighthouse - 4

Идеальный результат на сайте c CSS и JS. Это здорово, но мы можем сделать лучше.

К чёрту пользователей со скрин-ридерами

Есть много способов, чтобы помешать работе программ для чтения с экрана. Самый простой и эффективный — использовать атрибут aria-hidden="true". Этот мощный атрибут, его следует применять с осторожностью, потому что он удаляет элементы из дерева доступности. Обычно его применяют для помощи людям со скрин-ридерами, удаляя избыточный или посторонний контент [9]. На нашем сайте прописываем этот атрибут для элемента body.

HTML

<body hidden aria-hidden="true">
  ...
</body>

Теперь люди со скрин-ридерами испытают один из тех «редких» моментов [10], когда им встречается недоступный сайт.

CodePen: доступность 100%, шаг 3 [11]

Отсекаем пользователей с клавиатурами

Пользователи с клавиатурами могут перемещаться по странице, нажимая клавишу Tab для перехода от одного интерактивного элемента к другому. Браузер показывает контур вокруг элементов в фокусе.

Создаём максимально недоступный сайт с идеальной оценкой Lighthouse - 5

Давай избавимся от этого.

CSS

*:focus {
  outline: none !important;
}

Всего тремя строчками CSS мы отсекаем от сайта целую группу людей. Технически, они ещё могут взаимодействовать со страницей: по нажатию Tab по-прежнему происходит переход между интерактивными элементами, просто индикатор фокуса больше не показывается. Поскольку в нашем эксперименте требуется полностью ограничить возможности людей, давайте отключим клавиатуру вообще.

JS

document.addEventListener('keydown', function(e) {
  e.preventDefault();
})

Наше приложение теперь удаляет функциональность по умолчанию всех клавиш.

CodePen: доступность 100%, шаг 4 [12]

Время для следующего теста.

Создаём максимально недоступный сайт с идеальной оценкой Lighthouse - 6

Всё ещё идеально.

Ладно, пришло время для грязных трюков.

Эксплоит для режима высокой контрастности

В Windows люди со слабым зрением могут улучшить контраст, включив так называемый режим высокой контрастности [13].

Создаём максимально недоступный сайт с идеальной оценкой Lighthouse - 7

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

Мы можем таргетировать свойство media специально на этих пользователей.

CSS

@media screen and (-ms-high-contrast: active) {
  /* High contrast styling rules */
  * {
    color: #000000;
  }
}

Эти правила применяются только в том случае, если включён режим высокой контрастности в Windows. К сожалению, мы не знаем, какие цвета использует тема: светлые или тёмные. Установка цвета #000000 для всех элементов может сработать, а может и нет, в зависимости от предпочтений пользователя. Такая вероятность 50% меня не устраивает, но нам повезло: контрастные цвета Windows сопоставляются с ключевыми словами системного цвета CSS [14]. Можно использовать эти ключевые слова и убедиться, что наш текст всегда соответствует цвету любого фона в режиме высокой контрастности. Фоновый цвет в ОС сопоставляется с цветом windows в CSS. Итак, укажем этот цвет для всего текста на странице.

CSS

@media screen and (-ms-high-contrast: active) {
  * {
    color: window !important;
  }
}

Создаём максимально недоступный сайт с идеальной оценкой Lighthouse - 8

О боже. Это так подло. Теперь мне посыпятся предложения на работу от Facebook и Uber.

CodePen: доступность 100%, шаг 5 [15]

К чёрту пользователей с мышками

Здесь совсем легко: просто удаляем с экрана курсор.

CSS

*,
*:hover {
  cursor: none;
}

Для пользователя с мышкой свойство cursor: none; делает то же самое, что для пользователя с клавиатурой делает свойство outline: none;. Без курсора сначала трудно ориентироваться, но элементы по-прежнему кликабельны. Давайте улучшим качество нашего приложения, ещё раз обрезав пользователям доступный интерфейс.

CSS

body {
  pointer-events: none;
}

Ну вот, другое дело. После указания pointer-events: none; пользователи больше не могут нажать ни на какой элемент. Это свойство хорошо поддерживается, но чтобы функция работала на как можно большем количестве браузеров, желательно применить принцип прогрессивной деградации.

JS

function removeA11y() {
  if ("pointerEvents" in document.body.style) {
    console.log('pointer-events supported')
    return;
  }

  document.addEventListener('click', function(e) {
    e.preventDefault();
  })
}

removeA11y();

Этот запасной скрипт запускается и удаляет события click из всех элементов, если браузер не поддерживает свойство pointer-events.

CodePen: доступность 100%, шаг 6 [16]

Создаём максимально недоступный сайт с идеальной оценкой Lighthouse - 9

Здорово! Сайт по-прежнему совершенно доступен!

К чёрту читаемость

Мы больше не можем использовать мышь или клавиатуру, но всё ещё видим текст на странице. Непорядок.

CSS

body {
  opacity: 0.03;
}

Контент остался на странице, но почти не заметен. Потрясающе!

CodePen: доступность 100%, шаг 7 [17]

Эксплоит режима чтения в Safari

Тестируя сайт в разных браузерах, я заметил, что он по-прежнему доступен в Safari в режиме чтения.

Создаём максимально недоступный сайт с идеальной оценкой Lighthouse - 10

Как выяснилось, можно отключить этот режим, если указать минимальный размер шрифта в body.

CSS

body {
  opacity: 0.03;
  font-size: 1px;
}

CodePen: доступность 100%, шаг 8 [18]

Долой просмотр исходника

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

Если опытный пользователь попадёт на такой сайт, в нём может проснуться внутренний хакер [19] и он попытается хакнуть его. Я имею в виду, просмотреть исходный код страницы.

Вишенка на торте недоступности нашего сайта — конвертация текста в HTML-мнемоники [20]. Эти мнемоники [21] (entity) обычно используются для отображения зарезервированных, невидимых символов и тех, которые трудно ввести с помощью стандартной клавиатуры. Мы используем их для обфускации.

Создаём максимально недоступный сайт с идеальной оценкой Lighthouse - 11

CodePen: доступность 100%, шаг 9 [22]

И последнее испытание.

Создаём максимально недоступный сайт с идеальной оценкой Lighthouse - 12

Выводы

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

Это статья о нас. Оценки указывают на качество наших приложений и сайтов, но мы не должны слепо доверять этим цифрам. Мы должны понимать, что автоматическое тестирование — только первый шаг.

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

«Данная проверка определяет возможности для улучшения доступности вашего веб-приложения [23]. Автоматическая проверка способна обнаружить только часть проблем, поэтому рекомендуется также провести ручное тестирование».

Мы тестируем и оптимизируем сайты не ради приятного чувства, которое даёт высокая оценка. Мы делаем это для людей: чтобы сайт был доступен как можно большему числу пользователей. В дизайне и программировании мы же не полагаемся полностью на автоматизацию. Вот и в тестировании не следует этого делать.

Спасибо Эрику [24] за корректуру и отзывы.

Ссылки и ресурсы

Автор: m1rko

Источник [28]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/html/320047

Ссылки в тексте:

[1] axe-core: https://github.com/dequelabs/axe-core

[2] своим набором правил: https://github.com/GoogleChrome/lighthouse/blob/ad0a747a712b815677b6ea3bcc59ee7a0883426d/lighthouse-core/gather/gatherers/accessibility.js#L26-L50

[3] написал: https://twitter.com/zachleat/status/1122184546609446919

[4] ответ Вадима Макеева: https://twitter.com/pepelsbey_/status/1122203926584074240

[5] CodePen: Доступность 100%, шаг 0: https://codepen.io/matuzo/pen/vwVRJx

[6] «Инклюзивное скрытие»: https://www.scottohara.me/blog/2017/04/14/inclusively-hidden.html

[7] CodePen: доступность 100%, шаг 1: https://s.codepen.io/matuzo/pen/QRZmrJ

[8] CodePen: доступность 100%, шаг 2: https://s.codepen.io/matuzo/pen/GaYxLx

[9] удаляя избыточный или посторонний контент: https://www.w3.org/WAI/PF/aria/states_and_properties#aria-hidden

[10] «редких» моментов: https://webaim.org/projects/million/

[11] CodePen: доступность 100%, шаг 3: https://s.codepen.io/matuzo/pen/OYBZbd

[12] CodePen: доступность 100%, шаг 4: https://s.codepen.io/matuzo/pen/vwVrxo

[13] режим высокой контрастности: https://developer.paciellogroup.com/blog/2016/12/windows-high-contrast-mode-the-limited-utility-of-ms-high-contrast/

[14] ключевыми словами системного цвета CSS: https://www.w3.org/wiki/CSS/Properties/color/keywords#System_Colors

[15] CodePen: доступность 100%, шаг 5: https://s.codepen.io/matuzo/pen/Ezdpoa

[16] CodePen: доступность 100%, шаг 6: https://s.codepen.io/matuzo/pen/zQmJYB

[17] CodePen: доступность 100%, шаг 7: https://s.codepen.io/matuzo/pen/eaPLeB

[18] CodePen: доступность 100%, шаг 8: https://s.codepen.io/matuzo/pen/QRZVJj

[19] внутренний хакер: https://en.wikipedia.org/wiki/Hackers_(film)#Plot

[20] конвертация текста в HTML-мнемоники: https://v2.cryptii.com/text/htmlentities

[21] мнемоники: https://developer.mozilla.org/en-US/docs/Glossary/Entity

[22] CodePen: доступность 100%, шаг 9: https://s.codepen.io/matuzo/pen/joeeqy

[23] улучшения доступности вашего веб-приложения: https://developers.google.com/web/fundamentals/accessibility/

[24] Эрику: https://ericwbailey.design/

[25] Google Lighthouse: https://developers.google.com/web/tools/lighthouse/

[26] Web Fundamentals – Доступность: https://developers.google.com/web/fundamentals/accessibility/?utm_source=lighthouse&amp;utm_medium=devtools

[27] The A11y Project: https://a11yproject.com

[28] Источник: https://habr.com/ru/post/455016/?utm_source=habrahabr&utm_medium=rss&utm_campaign=455016