Перевод подготовлен в рамках онлайн-курса "HTML/CSS". Приглашаем всех желающих на открытый урок «CSS Reset — ненужный артефакт или спасательный круг». На этом вебинаре рассмотрим, зачем нам CSS Reset, что такое рендеринг и как браузер рендерит страницу.   Toggles (или их еще называют "тумблеры"/"переключатели") широко используются в современных интерфейсах. Они, как правило, относительно просты, и их можно рассматривать как простые флажки (checkbox). Тем не менее, их часто делают недоступными тем или иным способом. В этой статье я покажу небольшую имплементацию доступного toggle на HTML + CSS, которую вы можете применить в своих проектах и доработать по своему усмотрению. Разметка Стилизация Контейнер The toggle и дескриптор handle Стили для фокуса Проверенное состояние Отключенное состояние Поддержка право-лево Иконки Вариант кнопки Завершение Дисклеймер: Прежде чем использовать toggle, подумайте, насколько это наилучший вариант пользовательского интерфейса для данной ситуации. Toggles могут быть визуально непонятными, и в некоторых случаях кнопка может быть более подходящим решением для данной ситуации. Как всегда, давайте начнем с HTML. В данном случае мы начнем с самых основ, а именно с правильно обозначенного флажка. Это input с <label>, с правильными атрибутами и видимой меткой. Если toggle вызывает немедленное действие (например, переключение темы) и поэтому зависит от JavaScript, то вместо него следует использовать <button>. Обратитесь к варианту кнопки для получения дополнительной информации о разметке - стили, по сути, одинаковы. Спасибо Adrian Roselli за то, что он обратил наше внимание на это! Стоит отметить, что это не единственный способ разметки такого компонента интерфейса. Например, вместо него можно использовать 2 radio inputs. Sara Soueidan более подробно рассказывает о проектировании и создании toggle. Теперь нам понадобится немного больше. Чтобы не передавать статус флажка, полагаясь только на цвет (Критерий успеха WCAG 1.4.1 "Использование цвета"), мы собираемся использовать пару иконок. Мы будем использовать небольшой контейнер между вводом данных и текстовой меткой, который будет содержать 2 иконки: галочку и крестик (взяты из иконок Material UI). Затем мы создадим toggle handle с псевдоэлементом, который будет охватывать одну из иконок за раз. Следует отметить несколько моментов, связанных с нашей разметкой: Мы используем aria-hidden="true"  для наших SVG, потому что они не должны обнаруживаться вспомогательными технологиями, так как являются сугубо декоративными. Мы также используем focusable="false" для наших SVG, чтобы избежать проблем с Internet Explorer, где SVG по умолчанию фокусируются. Мы используем hidden для контейнера .Toggle__display , чтобы скрыть его, когда CSS недоступен, поскольку он должен вернуться к базовому флажку. Его значение отображения будет переопределено в CSS. Прежде чем мы углубимся в стилизацию, я хотел бы уточнить терминологию, чтобы было легче следить за развитием событий: Контейнер - это обертка <label>, которая содержит как toggle, так и текстовую метку (.Toggle). Toggle - это визуальный тумблер, зеленый или красный в зависимости от статуса, с 2 иконками (.Toggle__display). Handle - это круглый диск, охватывающий одну из иконок и перемещающийся влево и вправо при взаимодействии с toggle  (.Toggle__display::before). Input - Вход - это HTML <input>, который визуально скрыт, но остается доступным и фокусируемым (.Toggle__input). Давайте начнем с базовых стилей для нашего контейнера. Затем - наш toggle. Чтобы облегчить настройку его стилей, мы используем некоторые пользовательские свойства CSS для перемещения вокруг handle и его диаметра. Переход здесь осуществляется таким образом, что handle плавно скользит из одной стороны в другую. Это может немного отвлекать или настораживать некоторых людей, поэтому рекомендуется отключить этот переход, когда включена функция reduced-motion (уменьшение движения). Это можно сделать с помощью следующего фрагмента: Мы вставили наш контейнер toggle после самого ввода, чтобы использовать комбинатор смежных сиблингов ( + )для стилизации toggle в зависимости от состояния ввода (проверен, сфокусирован, отключен...). Сначала давайте разберемся со стилями для фокуса. До тех пор, пока они заметны, они могут быть настолько индивидуальными, насколько мы захотим. Для того чтобы быть достаточно нейтральным, я решил отобразить родной контур фокуса вокруг toggle, когда вход сфокусирован. Я заметил одну интересную вещь: при нажатии на родной флажок или его метку контур фокуса не появляется. Это происходит только при фокусировке флажка с помощью клавиатуры. Мы можем имитировать это поведение, удалив стили, которые мы только что применили, когда селектор :focus-visible не подходит. Затем нам нужно разобраться с проверенным состоянием. В этом случае мы хотим сделать две вещи: обновить цвет фона toggle с красного на зеленый и сдвинуть handle вправо, чтобы он закрыл крестик и показал галочку (100% собственной ширины). Adrian Roselli справедливо заметил, что эта схема не учитывает возможное "смешанное" (или "неопределенное" состояние). Это справедливо для простоты, поскольку большинство флажков/тумблеров не нуждаются в таком состоянии, но его следует учитывать, когда это необходимо. Наконец, мы можем добавить несколько пользовательских стилей, чтобы сделать отключенный toggle более явным. Изначально я забыл о поддержке право-лево, и Adrian Roselli был достаточно любезен, чтобы указать мне на это, поэтому я обновил код. В идеале мы должны использовать псевдо-класс :dir() , но, к сожалению, на данный момент браузеры поддерживают его довольно плохо, поэтому нам приходится полагаться на селектор атрибута [dir]. Нам нужно настроить все, что в настоящее время направлено так, чтобы было исходное и проверенное положение handle. Наконец, мы применим некоторые стили к нашим иконкам, как рекомендует Florens Verschelde в своем фантастическом руководстве по SVG-иконкам: Как упоминалось ранее, использование флажка не обязательно является наиболее подходящей разметкой. Если toggle имеет немедленный эффект (и поэтому полагается на JavaScript), и если он не может иметь неопределенное состояние, то вместо него следует использовать элемент <button> с атрибутом aria-pressed. Adrian Roselli в своем материале о toggles предлагает дерево решений для выбора между флажком и кнопкой. К счастью, наш код легко адаптировать, чтобы он работал так же, как и кнопка. Во-первых, мы изменим HTML таким образом, что <label> станет <button>, а <input> будет удален. Затем нам нужно убедиться, что <button>  не похожа на саму кнопку. Для этого мы сбросим стили кнопки по умолчанию, включая контур фокуса, поскольку он применяется при toggle (переключении). Затем нам нужно дополнить все наши селекторы, связанные с вводом, вариацией для выбора варианта кнопки. Вот и все! Таким образом, мы можем использовать либо разметку флажка, либо разметку кнопки, в зависимости от того, что больше подходит для данной ситуации, и иметь одинаковые стили в обоих случаях. Очень удобно! Как видите, ничего особо сложного в этом нет, но все же есть над чем подумать. Вот чего мы добились: Мы используем реальный элемент формы флажка, который мы стилизуем под toggle. Он передает свой статус с помощью иконографии и цвета. Он не оставляет артефактов, когда CSS недоступен. Он имеет собственные стили по фокусу и может быть настроен. У него есть отключенное состояние. При необходимости он имеет поддержку право-лево. Он должен быть относительно легко адаптирован к темному режиму при наличии некоторых глобальных пользовательских свойств. Здорово! Не стесняйтесь играть с кодом на CodePen, и я надеюсь, что это поможет вам сделать ваши toggles доступными.  А также, я рекомендую прочитать эти статьи, чтобы продвинуться дальше: Designing and building toggle switches от Sara Soueidan Toggle buttons от Heydon Pickering ARIA switch controls от Scott O'Hara Under-engineered toggles от Adrian Roselli Примечание Dion упоминает, что toggle может выглядеть наоборот, и это мнение поддерживает Rawrmonstar, а Mikael Kundert упоминает, что использование флажков обычно проще.  Узнать подробнее о курсе "HTML/CSS" Смотреть открытый урок «CSS Reset — ненужный артефакт или спасательный круг» Редактор