- PVSM.RU - https://www.pvsm.ru -
В рамках “Дизайна госсистем” мы создали для вас (разработчиков всех видов) чек-лист доступности сайта для людей с ограниченными возможностями, который нужно прибить над рабочим столом каждого дизайнера и фронтендера. Он подходит к любым проектам (совсем не только государственным) в нем нет ничего лишнего. В нем только исключительно важная, критичная и полезная информация.
Так что печатайте, читайте и делитесь со своими коллегами.
Это крайне необходимые текст и знания.
Требования по доступности сайта определяются стандартом WCAG уровня AA. Стандарт довольно подробно описывает все требования, содержит ссылки на разъяснения, используемые техники и часто встречающиеся ошибки. Это позволяет полностью опираться на него при анализе доступности веб-страниц и их адаптации. Кроме того, в общем доступе имеется большой инструментарий для полуавтоматического выявления ошибок: валидаторы и дополнения для браузеров.
В этом документе представлены практические рекомендации по применению стандарта, описан инструментарий и процесс проверки сайта на доступность, даны ссылки на ключевые материалы и руководства по доступности сайтов, а также на примеры реализации наиболее распространённых виджетов.
Стандарт WCAG 2.0 уровня AA описывает критерии доступности для разных категорий пользователей. На практике для соблюдения хорошего уровня соответствия критериям тестировщику будет полезно представить себя на месте следующих категорий пользователей (или привлечь их к тестированию):
Слепые (полностью незрячие — пользователи экранных чтецов). Требуется широкий набор мер, включая:
Всем участникам разработки (дизайнерам, разработчикам, проект-менеджерам, тестировщикам и редакторам) можно также ознакомиться с кратким чек-листом [1], в котором описаны основные обязанности каждого специалиста по обеспечению доступности.
См. также:
Цвет не может быть единственным способом предоставления какой-либо информации или разметки.
Необходимо соблюдать контрастность согласно WCAG 2.0.
Измерять контрастность в HTML можно WAVE Evaluation Tool [4]
Не следует опираться на сенсорные характеристики.
Детально данное требование разобрано ниже в описании критерия 1.3.3.
Должно быть предусмотрено визуальное отображение состояний фокуса на полях и элементах управления.
См. также Accessibility Guidelines. The Checlist for Designers [5].
Проверка сайта валидаторами на общую валидность HTML: https://validator.w3.org/ [6]
Проверка сайта специализированными валидаторами:
http://wave.webaim.org/ [8] и расширение для Chrome WAVE Evaluation Tool [4]. Находят большое количество ошибок, предоставляют подсказки по исправлению и ссылку на стандарт, предоставляют информацию в удобном виде, подсвечивают синтаксис и aria-атрибуты.
Главное удобство в том, что расширение может анализировать не исходный код, а текущее состояние страницы.
Нужно помнить, что наличие сообщений об ошибках валидатора само по себе не является формальным критерием несоответствия WCAG. Кроме того, некоторые сообщения носят рекомендательный характер или помечены как потенциальные. Решения по ним должны приниматься исходя из контекста.
Верно и обратное: не любая проблема находится валидатором: необходимо ручное тестирование в т.ч. с применением экранных чтецов (см. ниже).
Проверка в экранных чтецах.
Наиболее простой в настройке является комбинация Windows + Firefox/IE + NVDA. Также широко распространен JAWS (программа платная и дорогая, но поставляется в триал-версии с 40-минутным режимом). Пользователям других ОС тестовое окружение можно настроить в виртуальных машинах от Microsoft (https://developer.microsoft.com/en-us/microsoft-edge/tools/vms/ [12] — бывший modern.ie), работает приемлемо, по крайней мере, с ВМ Windows 7.
Программы экранного доступа довольно специфичны для тех, кто с ними сталкивается впервые, однако к пользованию ими можно относительно быстро привыкнуть. Освоить программу на уровне краткой инструкции (см. ниже) рекомендуется всем фронт-энд разработчикам и тестировщикам. Это не займёт много времени.
Соблюдение семантики разметки. В частности, можно выделить следующее (перечислено далеко не всё):
Разметка семантических областей с помощью role=main, role=navigation, role=contentinfo, role=complementary, role=banner и др.
Ссылка должна быть первым фокусируемым элементом на странице. Это ссылка, предназначенная для незрячих пользователей. После загрузки страницы фокус должен попадать на ссылку по первому нажатию TAB, затем по нажатию на ENTER страница должна якориться на элементе с основным содержимым.
Эталонная реализация на http://webaim.org/ [20]. После загрузки нужно нажать на TAB — ссылка становится видимой в левом верхнем углу, затем ENTER.
Строгая иерархия заголовков начиная с заголовка уровня 1.
Управляемость с клавиатуры:
Предоставление дополнительной текстовой информации:
Предоставление меток (label) для элементов ввода: с помощью <label for="...">, aria-label, aria-labelledby. Не должно быть элементов управления и ввода без текста или текстовой метки.
Подробнее о том, как вычисляется текстовая альтернатива, см. https://www.w3.org/TR/wai-aria/roles#textalternativecomputation [22]
Обратите внимание, что не имеет смысла добавлять aria-label к не имеющим семантики элементам (например, <span>).
Для прочих элементов (списки, группировки полей <fieldset> и др., landmarks) атрибут aria-label также будет интерпретироваться по-разному, и при его использовании нужно понимать его предназначение для каждого элемента.
<abbr title="и так далее">
и т.д.
</abbr>
.sr_only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
border: 0;
}
<span class="sr_only">
текст для экранных чтецов
</span>
Значимая информация, представленная в виде диаграмм, графиков, интерактивных Flash (в большинстве случаев), SVG, Canvas и других, должна быть представлена также и в текстовом виде: отдельными параграфами, таблицами, возможно, на отдельной странице или в скрытом от зрячих пользователей с помощью class="sr_only" блоке.
Примечание: в большинстве случаев имеется техническая возможность адаптировать перечисленные элементы для пользования незрячими, но в виду трудозатратности, необходимости проработки по сути отдельного интерфейса для незрячих, проблем с тестированием и т.д. обычно легче и, главное, удобнее для пользователя иметь текстовое представление данных.
Рекомендуется по возможности использовать встроенные компоненты браузера, если они удовлетворяют требуемому функционалу: комбинированные списки (<select>), флаги (checkbox), радиокнопки, кнопки, поля ввода.
Следует также избегать переусложнения управления с клавиатуры, не изобретать новые паттерны взаимодействия при наличии решающих те же задачи стандартных решений [23], стараясь компоновать интерфейс из известных и доступных для инвалидов компонентов и подходов. См. раздел "Примеры реализации доступных интерфейсов" и описание критерия 4.1.2 ниже.
Допускается создание элементов, скрытых для зрячих пользователей, но доступных для незрячих. Делается это с помощью техники вынесения элемента далеко за левый край экрана (класс sr_only, описанный выше).
Допустима реализация отдельного альтернативного интерфейса для экранных чтецов (со скрытием основного варианта интерфейса) в случае, если обычный виджет сделать доступным затруднительно. При этом нужно не забывать об управляемости элемента с клавиатуры зрячими пользователями.
Пользоваться этим приёмом нужно с осторожностью: если есть выбор, то следует предпочесть адаптировать общий интерфейс под использование незрячими пользователями.
Реализация отдельного интерфейса смысл, если это значительно упрощает интерфейс для незрячих, например, ввод даты вручную вместо календаря (но календарь тоже можно сделать доступным), использование списка вместо карты для выбора стран/городов.
Важно не переусердствовать: практика показывает, что слепые пользователи не испытывают затруднения при пользовании некоторыми интерфейсами, которые на первый взгляд кажутся неудобными для незрячих.
Проверка сайта валидаторами на общую валидность HTML: https://validator.w3.org/ [6].
Максимальное соответствие спецификации используемой версии HTML не является обязательным, но рекомендуется (см. технику [G192][g192]). Однако имеется ряд ошибок, важных для доступности сайта и обязательных к исправлению. Они перечислены в описании критерия 4.1.2 в разделе "Детальная проверка на соответствие WCAG AA".
Проверка сайта специализированными валидаторами. См. раздел "Средства проверки".
Проверка управляемости с клавиатуры без экранных чтецов.
Не должно быть кликабельных, но недоступных с клавиатуры элементов (если им нет специальной доступной альтернативы). Такие элементы следует реализовывать с помощью тегов <a href=..></a>, <button> или с помощью сочетания атрибутов role=button, role=link и tabindex.
Фокус должен быть видимым, корректно перемещаться, не "застревать" при попадании ни на один элемент и не теряться при любом действии пользователя в любом состоянии страницы.
Просмотр сайта с применёнными стилями, приближающими его к тому, каким его видят незрячие. Стили можно найти по адресу https://github.com/Harut/wai-aria.css [24]. Это позволит найти большую часть ошибок «на глаз», не сверяясь с каждым пунктом чек-листа. Этот пункт является необязательным, не заменяет, а предваряет просмотр страницы в экранных чтецах. Обращать внимание, в первую очередь, рекомендуется на несоответствия в полной визуальной версии и версии с применёнными стилями.
Проверка в экранных чтецах. На этом этапе большинство критических ошибок должно быть обнаружено и исправлено при предыдущих проверках.
Необходимо проверить восприятие экранными чтецами таблиц, нестандартных элементов, удобство пользования функционалом страницы, правильность и полноту озвучиваемых атрибутов (в основном, role и aria-*.
WAI-ARIA 1.0 Authoring Practices: https://www.w3.org/TR/wai-aria-practices/ [26]. Документация для разработчиков, содержит описание неочевидных моментов и подходов по созданию доступного интерфейса.
Содержит также набор шаблонов для проектирования [23] самых распространённых виджетов (эту информацию в более сжатом табличном виде можно также найти в рекомендациях от WebAIM [27]).
В данном разделе приведена выжимка из WCAG в форме чек-листа на соответствие уровню AA, сгруппированный по соответствующим критериям WCAG. Список составлен на основе http://webaim.org/standards/wcag/checklist [32]. Официальный набор рекомендаций, техник и список часто встречающихся ошибок можно найти по ссылке: https://www.w3.org/WAI/WCAG20/quickref/ [33].
Всем участникам разработки и тестирования сайта рекомендуется внимательно изучить и освоить данный список, чтобы допускать как можно меньше ошибок на этапе разработки или исправлять их на ранних этапах. Это позволит обходиться наименьшими трудозатратами при разработке и тестировании, а также сосредоточиться при тестировании на деталях, которые важны, но могут быть упущены в общем количестве ошибок.
1.1. Текстовая версия: предоставьте текстовую версию любого нетекстового контента
1.1.1. Нетекстовый контент (Level A)
1.2. Медиаконтент: предоставьте альтернативную версию медиаконтента, ограниченного по времени
Вкратце, следует предоставлять расшифровку текста записи, текстовое описание её содержимого или субтитры. Если видео содержит визуальную информацию, которая не представлена звуком, следует также предоставить для него аудио-описание.
В случае, если такое содержимое появится на сайте, следует обратиться к стандарту WCAG или, например, рекомендациям Webaim [32].
1.3. Адаптируемость: создавайте контент, который можно представить в различных видах без потери данных или структуры
1.3.1. Информация и связность (Level A)
1.3.2. Значимая последовательность чтения (Level A)
1.3.3. Сенсорные характеристики (Level A)
Если это не является неотъемлемой и неминуемой частью функционала:
1.4. Избирательность: упростите просмотр и прослушивание контента, отделив важные части от второстепенных
1.4.1. Использование цвета (Level A)
1.4.2. Управление звуком (Level A)
1.4.3. Контраст (Level AA)
1.4.4. Изменение размеров текста (Level AA)
1.4.5. Текст на изображениях (Level AA)
2.1. Доступность управления с клавиатуры
2.1.1. Клавиатура (Level A)
Весь функционал должен быть доступен для управления с клавиатуры, за исключением случаев, когда это в принципе невозможно (например, рисование от руки).
Необходимо убедиться в работоспособности как в сочетании с экранными чтецами, так и без.
Все элементы, с которыми можно взаимодействовать, должны принимать фокус. В случае, если реализовано нажатие на элемент, оно должно быть доступно наравне как посредством мыши, так и посредством клавиатуры.
По умолчанию, фокусировку и взаимодействие с клавиатурой поддерживают элементы формы, кнопки <button> и ссылки <a href>.
Собственные реализации элементов управления или ввода должны предоставлять те же возможности для взаимодействия посредством клавиатуры, что и встроенные в браузер элементы и/или примеры реализации похожих виджетов на специализированных сайтах по доступности (например, Open Ajax Accessibility [28]).
Нужно помнить, что реализации виджетов на этих сайтах может быть не идеальной, и во многих случаях может потребоваться их доработка или исправление. Необходимо проверять сложные решения в экранных чтецах.
Использование обработчиков mousedown и mouseup в качестве обработчиков нажатия на элемент будет приводить к недоступности его с клавиатуры. Также не обеспечивает доступность событие click на не фокусируемых по-умолчанию элементах, т.е. всех, кроме элементов формы, кнопок <button> и ссылок <a href>.
Рекомендуется избегать таких случаев, но если это невозможно, то для таких элементов необходимо дополнительно прописывать обработку событий клавиатуры.
Открывающиеся при наведении мыши подсказки или меню также должны быть доступны с клавиатуры. Можно, например, показывать (а для подсказок ещё и озвучивать) текст элемента при фокусе.
Спецификация ARIA предусматривает атрибут aria-haspopup для реализации подобных виджетов (например [36]), но с его поддержкой и работой с клавиатуры без экранных чтецов есть вопросы [37].
2.1.2. Отсутствие ловушек для фокуса (Level A)
2.2. Достаточное время: предоставьте пользователям достаточно времени для ознакомления и работы с контентом
2.2.1. Настройка времени (Level A)
Исключения, предусмотренные стандартом:
2.2.2. Пауза, остановка, скрытие. (Level A)
Стандарт предусматривает исключения из правил, если отсутствует техническая возможность или если анимация или обновление имеют ключевое значение для функционала страницы, и без них меняется смысл или поведение страницы. Примеры исключений с объяснением можно найти в пояснениях к критерию [38].
Критерий довольно строгий, и полное следование ему иногда может потребовать много времени на разработку и ухудшить пользование страницей для обычных пользователей. Нужно искать компромисс между строгими формальными требованиями стандарта и реальностью в каждом случае, но при этом нужно продумывать взаимодействие для каждой из перечисленных категорий пользователей (см. Введение).
2.3. Не используйте заведомо опасные для здоровья элементы дизайна
2.3.1. Ограничение в три или менее вспышки в секунду (Level A)
2.4. Навигация: предоставьте пользователям помощь и поддержку в навигации, поиске контента и в определении их текущего положения на сайте
2.4.1. Пропуск повторяющихся на всех страницах блоков (Level A)
2.4.2. Заголовок страницы (Level A)
2.4.3. Порядок перемещения фокуса (Level A)
2.4.4. Предназначение ссылки (в контексте) (Level A)
2.4.5. Различные способы поиска (Level AA)
2.4.6. Заголовки и метки (Level AA)
2.4.7. Видимый фокус (Level AA)
3.1. Удобочитаемость: сделайте весь текстовый контент удобочитаемым и понятным
3.1.1. Язык страницы (Level A)
3.1.2. Язык частей страницы (Level AA)
3.2. Предсказуемость отображения и функционала
3.2.1. Предсказуемость при фокусе (Level A)
Попадание фокуса на какой-либо элемент не должно вызывать значимых изменений на странице (смены контекста):
3.2.2. Предсказуемость при вводе (Level A)
Ввод информации или взаимодействие с каким-либо полем или элементом управления не должен вызывать значимых изменений на странице (смены контекста), если пользователь не был проинформирован об этом заранее.
Примеры смены контекста можно найти выше в п. 3.2.1.
Наиболее распространенный случай — переход на другую страницу или открытие нового окна по событию onchange на элементах <select>, радиокнопках или чекбоксах. Следует по возможности избегать такого поведения, переходить на страницу только по нажатию на кнопку или на ENTER [G80][g80].
При тестировании следует учесть, что событие onchange в разных браузерах срабатывает по-разному.
3.2.3. Единообразная навигация (Level AA)
3.2.4. Единообразие названий (Level AA)
3.3. Помощь при вводе: помогайте пользователям избегать ошибок при вводе информации и исправлять их
3.3.1. Выявление ошибок (Level A)
Ошибки формы дожны быть представлены в интуитивном и доступном виде.
В большинстве случаев рекомендуется следующий подход: у элемента с ошибкой должен быть id, по которому на него поле ссылается с помощью атрибута aria-describedby.
Атрибут aria-describedby меняется динамически: в обычном состоянии он указывает на подсказку или описание поля, а в случае ошибки ввода — на текст ошибки (вместо или вместе с подсказкой — aria-describedby может содержать несколько идентификаторов).
Желательно предоставить общее сообщение об ошибке в начале страницы. Плюсом будет также возможность перехода из сообщения по ссылке к первому полю с ошибкой.
Во всех деталях данная техника описана в статье от WebAIM [41].
3.3.2. Текстовые метки и инструкции для полей ввода (Level A)
Имеются информативные и правильно связанные метки (<label>, aria-label, aria-labelledby), подсказки и инструкции (aria-describedby), примеры заполнения полей, заголовки группировок полей (<legend>).
Следует обратить внимание на поля состоящие из нескольких элементов (например, радиокнопки, выбор даты — от и до, телефон — отдельно код и номер и т.д.): необходимо синтактически связать общую текстовую метку с каждым полем. Например, <fieldset> и <legend>, либо aria-labelledby="field-label-id subfield-label-id", либо aria-label="Дата от".
3.3.3. Подсказки при ошибках (Level AA)
3.3.4. Предотвращение ошибок (для юридических, финансовых и пользовательских данных) (Level AA)
Для ввода данных, которые имеют юридическую или финансовую значимость, для других контролируемых пользователем данных (определение дано в стандарте), выполняется хотя бы одно из требований:
4.1. Максимальная совместимость с существующими и будущими приложениями, включая ассистивные технологии
4.1.1. Синтаксис (Level A)
Отсутствуют существенные ошибки валидации HTML/XHTML (http://validator.w3.org/ [42])
Максимальное соответствие спецификации используемой версии HTML не является обязательным, но рекомендуется (см. технику [G192][g192]).
Важные для доступности сайта моменты:
4.1.2. Заданы имена, роли, значения, состояния и взаимосвязи между элементами (Level A)
Если элементы имеют роли, значения, названия, или между ними есть отношения, они должны быть выражены по возможности с помощью role, aria-* и других атрибутов.
Ниже неполный список случаев, когда уместна дополнительная семантическая разметка:
Разметка ссылки, раскрывающей или скрывающей какой-либо блок на странице с помощью aria-expanded (w3c wiki [46]).
Внимание! Пример на Open Ajax Accessibility содержит ошибку и противоречит примеру на w3c wiki и спецификации WAI-ARIA [47], не следует на него ссылаться или использовать. Атрибут aria-expanded должен быть не у раскрывающегося элемента, а у связанной кнопки или ссылки.
Автор:
Источник [51]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/html/208372
Ссылки в тексте:
[1] кратким чек-листом: http://accessibility.voxmedia.com/
[2] Раздел "Введение" стандарта WCAG 2.0: https://www.w3.org/Translations/WCAG20-ru/#intro
[3] Методики выполнения WCAG 2.0: https://www.w3.org/TR/WCAG20-TECHS/
[4] WAVE Evaluation Tool: https://chrome.google.com/webstore/detail/wave-evaluation-tool/jbbplnpkjmmeebjpijfedlgcdilocofh
[5] Accessibility Guidelines. The Checlist for Designers: http://accessibility.voxmedia.com/#designers
[6] https://validator.w3.org/: https://validator.w3.org/
[7] http://achecker.ca/checker/: http://achecker.ca/checker/
[8] http://wave.webaim.org/: http://wave.webaim.org/
[9] http://khan.github.io/tota11y/: http://khan.github.io/tota11y/
[10] AInspector Sidebar for Firefox: https://addons.mozilla.org/ru/firefox/addon/ainspector-sidebar/
[11] Accessibility Developer Tools Chrome: https://chrome.google.com/webstore/detail/accessibility-developer-t/fpkknkljclfencbdbgkenhalefipecmb
[12] https://developer.microsoft.com/en-us/microsoft-edge/tools/vms/: https://developer.microsoft.com/en-us/microsoft-edge/tools/vms/
[13] Описание принципов работы программ экранного доступа: http://webaim.org/techniques/screenreader/
[14] NVDA: бесплатная программа экранного доступа для тотально незрячих и слабовидящих: http://www.nvaccess.org/
[15] Краткая инструкция по пользованию NVDA для зрячих разработчиков: http://webaim.org/articles/nvda/
[16] Шпаргалка по командам NVDA: http://webaim.org/resources/shortcuts/nvda
[17] Развернутый список команд NVDA: https://dequeuniversity.com/screenreaders/nvda-keyboard-shortcuts
[18] Программа экранного доступа JAWS: http://www.freedomscientific.com/Products/Blindness/JAWS
[19] Шпаргалка по командам JAWS: http://webaim.org/resources/shortcuts/jaws
[20] http://webaim.org/: http://webaim.org/
[21] декоративных элементов: https://www.w3.org/WAI/tutorials/images/decorative/
[22] https://www.w3.org/TR/wai-aria/roles#textalternativecomputation: https://www.w3.org/TR/wai-aria/roles#textalternativecomputation
[23] стандартных решений: https://www.w3.org/TR/wai-aria-practices/#aria_ex
[24] https://github.com/Harut/wai-aria.css: https://github.com/Harut/wai-aria.css
[25] https://www.w3.org/TR/WCAG20-TECHS/aria.html: https://www.w3.org/TR/WCAG20-TECHS/aria.html
[26] https://www.w3.org/TR/wai-aria-practices/: https://www.w3.org/TR/wai-aria-practices/
[27] в рекомендациях от WebAIM: http://webaim.org/techniques/keyboard/#testing
[28] http://oaa-accessibility.org/: http://oaa-accessibility.org/
[29] https://developer.mozilla.org/en-US/docs/Web/Accessibility: https://developer.mozilla.org/en-US/docs/Web/Accessibility
[30] https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/widgets/overview: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/widgets/overview
[31] http://heydonworks.com/practical_aria_examples/: http://heydonworks.com/practical_aria_examples/
[32] http://webaim.org/standards/wcag/checklist: http://webaim.org/standards/wcag/checklist
[33] https://www.w3.org/WAI/WCAG20/quickref/: https://www.w3.org/WAI/WCAG20/quickref/
[34] Рекомендуется избегать использования атрибута accesskey без необходимости: http://webaim.org/techniques/keyboard/accesskey
[35] проблемы с порядком переключения фокуса: http://webaim.org/techniques/keyboard/tabindex
[36] например: http://heydonworks.com/practical_aria_examples/#submenus
[37] есть вопросы: http://www.maxability.co.in/2014/11/aria-haspopup-property/
[38] в пояснениях к критерию: https://www.w3.org/TR/UNDERSTANDING-WCAG20/time-limits-pause.html#time-limits-pause-examples-head
[39] https://www.w3.org/Translations/WCAG20-ru/#general-thresholddef: https://www.w3.org/Translations/WCAG20-ru/#general-thresholddef
[40] см. стандарт WCAG 2.0: https://www.w3.org/TR/UNDERSTANDING-WCAG20/consistent-behavior-receive-focus.html#context-changedef
[41] в статье от WebAIM: http://webaim.org/techniques/formvalidation/#error
[42] http://validator.w3.org/: http://validator.w3.org/
[43] managed state: https://www.w3.org/TR/wai-aria/terms#def_managedstate
[44] Providing Keyboard Focus: https://www.w3.org/TR/2013/WD-wai-aria-practices-20130307/#kbd_focus
[45] WAI ARIA Authoring practices 3.3: https://www.w3.org/TR/2013/WD-wai-aria-practices-20130307/#modal_dialog
[46] w3c wiki: https://www.w3.org/WAI/GL/wiki/Using_aria-expanded_to_indicate_the_state_of_a_collapsible_element
[47] спецификации WAI-ARIA: https://www.w3.org/TR/wai-aria/states_and_properties#aria-expanded
[48] WAI ARIA Authoring practices 4.4: https://www.w3.org/TR/2013/WD-wai-aria-practices-20130307/#relations_haspopup
[49] @Harut: https://github.com/Harut
[50] GitHub: https://github.com/govdesign/accessibility-guidelines
[51] Источник: https://habrahabr.ru/post/314910/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best
Нажмите здесь для печати.