button 3 что за кнопка

CSS и XPath для QA: чтобы разобраться с локаторами, нужно всего лишь…

Привет! Меня зовут Иван, я руковожу горизонталью автоматизации тестирования в Skyeng. Часть моей работы — обучать ручных тестировщиков ремеслу автоматизации. И тема с поиском локаторов, по моему опыту, самая тяжкая для изучения. Здесь куча нюансов, которые надо учитывать, но стоит разобраться, и локаторы начинают бросаться в глаза сами. Хороший автоматизатор должен идеально уметь находить читабельные и краткие локаторы на странице. Об этом и пойдет речь ниже.

Наливаем чай-кофе и погнали!

Что такое локатор

Локатор — обычный текст, которой идентифицирует себя как элемент DOM’а страницы. Простым языком: с помощью локатора на странице можно найти элементы. В случае CSS — локатор включает в себя набор уникальных атрибутов элемента, а в случае XPath — это путь по DOM’у к элементу.

Если вы изучали CSS ранее, то в конструкции ниже p будет являться локатором элемента, также и атрибут color: red может являться его локатором. Атрибут элемента это всё, что идёт после тега. Например, в теге

атрибутами являются class и id.

Сразу оговорка по терминологии, локатор = селектор.

Локатор — это название селектора на русском. Иногда встречаю в интернете, что селектор относится только к CSS, но это не совсем так. XPath-локатор тоже может быть, просто означает он путь к элементу в DOM’е. Давайте похоливарим в комментах, чем же всё-таки локатор отличается от селектора 😉

DOM страницы — это HTML-код, написанный человеком или сгенерированный фреймворком, который преобразуется браузером в DOM. То есть набор объектов, где каждый объект — это HTML-тег.

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

родители и дети элементов

Полное строение элемента

Элемент состоит из имени, то есть самого HTML-тега. Например, div, span, input, button и другие. Внутри него перечислены атрибуты, которые отвечают за все возможные свойства элемента. Например, цвет, размер, действие, которое будет происходить по клику на элемент.

У элемента может быть родитель и ребёнок. Родитель может быть один, а детей может быть несколько. Если детей несколько, то они являются соседями и каждый из них образует свою ось. 1 ребёнок = 1 ось со своими особенностями и своими вложенными элементами. А — родитель, B D E F W X Y — дети A. У каждого элемента есть свои дети, свои дальнейшие ветки, это и называется оси.

Поиск локаторов в браузере

Для поиска элементов в DOM’е страницы нужны средства разработчиков в браузере. Рассмотрим их на примере Chrome. Они же называются DevTools (F12). Нас интересует вкладка Elements, именно там находятся все элементы. Чтобы найти локатор в поле Elements, нужно нажать Ctrl+F. Внизу появится небольшое поле поиска, с ним мы будем работать всё время.

Давайте попробуем найти элемент по названию HTML-тега. Искать просто: в строке поиска вводим название тега. Скорее всего этот локатор элемента будет не уникальным и по его значению найдутся много элементов. Для тестов важно, чтобы был только один элемент для взаимодействия. Если одному локатору будут соответствовать несколько элементов, то тест или будет взаимодействовать с первым из них, или просто упадёт с ошибкой. Элементы можно искать не только с помощью тегов (p, span, div и т.д.), но и с помощью атрибутов тега. Например, color=”red” и class=”button”. Подробнее об этом чуть ниже.

Мы пытаемся найти элемент по тегу button, нам вернулось 269 результатов.

Микро-задание: попробуй открыть DevTools на этой страничке (F12) и найти (Ctrl + F) количество элементов с тегом button.

P.S. поздравляю, ты уже написал свой первый локатор! Дальше — больше 🙂

Уникальные локаторы

Где будем практиковаться? https://eu.battle.net/login/ru/ — простая и понятная форма авторизации.

Рассмотрим поиск на примере формы авторизации и регистрации. В коде страницы есть 2 поля («Почта» и «Пароль») и кнопка «Авторизация». Сравним, по каким атрибутам можно найти локатор и определим уникальные атрибуты.

Подробно разберём, как можно найти локатор поля Почта:

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

Разберём, как можно найти локатор поля Пароль:

Больше примеров не добавлял — аналогично с предыдущим: другие значения атрибутов слишком длинные.

Разберём, как можно найти локатор поля Авторизация:

Начнём с разбора не уникальных локаторов. Если по локатору находятся 2 и более элементов на HTML-странице, такой локатор можно назвать неуникальным. Тест при обнаружении большого количества элементов по данному локатору упадёт или возьмёт первый. Ненадежно, точно не наш бро.

Уникальный, но non-suitable локатор. Если мы в DevTools введем вышеуказанные названия, то найдется элемент. И здесь мы опускаемся до следующего уровня написания локаторов — уровня понятности, читаемости и надёжности локатора.

title=»Электронная почта или телефон» — считается плохим паттерном писать локаторы с русским текстом. Тем более в примере текст в title еще и длинный, это визуально громоздко. На текст завязываться можно в крайнем случае, но нужно быть готовым к тому, что тексты часто меняются, любая правка может сломать автотесты.

title=»Пароль» — аналогично ^

type=»text» — представь, ты открываешь среду разработки и видишь локатор “тип=текст”. Совсем не ясно, к какому элементу относится локатор. Со смысловой точки зрения, это неудачный локатор, потому что он не передаёт смысл локатора.

type=»password» — этот атрибут говорит о том, что у поля тип «password» и все символы, которые мы вводим заменяются на звёздочки/точки. При добавлении еще одного поля с type=”password” (например, поле «Подтвердите пароль») локатор сразу станет неактуальным. Стараемся думать наперёд.

Уникальные локаторы. Они найдут только один элемент, они осмысленные, иногда читабельные и краткие. Как раз уникальные атрибуты — это class, id, name и подобные. Они точно наши бро!

Хороший локатор — краткий, читабельный и осмысленный. Например, у поля «Пароль» хорошо иметь в локаторе слово password.

Возникает вопрос, почему class=»btn-block btn btn-primary submit-button btn-block» был вынесен в категорию уникальных? Такие локаторы встречаются повсеместно, и именно их мы берём за основу и приводим к красивому виду.

Поиск элементов с помощью CSS

id и class — самые важные атрибуты, с помощью которых мы будем искать бóльшую часть элементов на странице. Есть очень много тонкостей по работе с ними, постараемся рассмотреть все из них.

Кнопка «Авторизация» имеет несколько классов в одном:

Каждый из этих классов определяет свой визуал кнопки. Например, btn-primary определяет цвет кнопки, submit-button увеличивает её размер (это лишь догадки, основное значение знают только Blizzard). Несколько классов внутри атрибута class разделяются пробелом.

Наличие более одного класса внутри атрибута говорит о том, что он комбинированный. Бывают и комбинированные атрибуты кроме классов. Но классы необязательно будут уникальны для одного элемента. В данном случае у кнопки «Авторизация» такие атрибуты:

class=»btn-block btn btn-primary submit-button btn-block»

Но если добавить туда кнопку «Регистрация», то может отличаться лишь один класс. Например, он будет выглядеть следующим образом:

class=»btn-block btn btn-primary registration-button btn-block»

Сразу заметно, что отличается всего лишь один класс — submit-button сменился на registration-button. Остальные свойства могут иметь и другие кнопки.

Читабельность локатора

Допустим, мы ищем элемент по полному классу. Это хороший и действенный способ. Почти всегда элемент будет уникальным, но очень нечитабельным и громоздким, как в случае с кнопкой «Авторизация».

class с помощью CSS можно записать следующим образом:

.locator (точка — сокращенная запись class’а)

или выделяем название и значение класса в квадратные скобочки: [class=”value”]

Полный класс элемента кнопки «Авторизация» состоит из 5 классов: btn-block btn btn-primary submit-button btn-block, а выглядеть полный локатор будет так:

[class=”btn-block btn btn-primary submit-button btn-block”]

Разделение происходит с помощью пробела внутри. Для класса его сокращенной формой является точка, поэтому можно записать локатор так:

Читайте также:  что делать если бывшая подруга хочет общаться

Да, стало короче, но всё равно есть смысловая перегрузка. Сокращаем дальше.

Отдельно здесь стоит добавить про поиск по подстроке. Запись [class=”локатор”] ищет только всю строку класса элемента. Если мы напишем [class=”btn-block”] или любой другой класс, то кнопка «Авторизация» не будет найдена. Но если мы запишем локатор полностью [class=”btn-block btn btn-primary submit-button btn-block”], то кнопка найдётся.

Из данной ситуации помогает найти выход символ звёздочки. Он ищет ПОДстроку в строке, то есть часть локатора может найти элемент.

Краткость локатора

Можно почитать на википедии, там приведён доступный пример для общего понимания поиска по подстроке. Также поиск по подстроке можно сравнить с методом includes из JS

Локатор кнопки«Авторизация» [class=”btn-block btn btn-primary submit-button btn-block”] можно записать следующим образом:

[class*=”primary submit”] (конец одного класса и начала другого, но только в том случае, если они написаны подряд, друг за другом)

можно даже сократить название подкласса: не длинное submit-button, а просто submit, например, [class*=”submit”]. Можно даже сократить слово submit — [class*=”sub”].

Важно понимать, это будет работать, если классы идут только последовательно. Если мы укажем [class*=”btn-block submit-button”], то локатор работать не будет, потому что между btn-block и submit-button идут несколько классов: btn и btn-primary. Но это можно обойти, разделив локатор на 2 разных. Например, 2 класса слитно — [class*=”btn-block”][class*=”submit-button”]. Это работает и часто пригождается, когда нужно уточнить, в каком именно элементе мы ищем определенный класс.

Также можно комбинировать краткую запись с помощью точки и тега элемента:

Краткую запись (через точку) предпочтительнее использовать, чем полную (в квадратных скобках).

Лаконичность локатора

Мы можем определить кнопку «Авторизация» по классу submit-button. Это не самый лаконичный локатор, но дословно означает действие отправки данных на сервер с формы авторизации. Но что делать, если у кнопки нет контекста? Например, классы кнопки Авторизации будут выглядеть так: [class=”btn-block btn btn-primary btn-block”]. Если нет контекста из слова submit (отправка), то можно очень быстро потеряться и сразу не ясно, к какому элементу относится этот локатор. В данном случае нам поможет название текущего элемента или его родителя.

Для наглядности рассмотрим весь блок с кнопкой «Авторизация».

Как вариант — к локатору можно добавить сам тег button. Например, button[class*=”btn”] (сократил класс для наглядности). В таком случае можно взять тег или класс родителя за основу, а именно div или [class=»control-group submit no-cancel»]. Если нужно указать родителя, то эта связь пишется через пробел. Через пробел можно обращаться на любой уровень вложенности, например, из form сразу прыгнуть к button. Полный путь будет выглядеть так: form div button.

С полученными знаниями можно расширить пул локаторов:

#password-form #submit (решётка — сокращённая форма id, точка — сокращённая форма class)

и еще много-много локаторов, которые можно найти комбинаторикой, главное, чтобы по итогу локатор выглядел кратко и лаконично, передавал суть элемента

С ID работает всё точно также, только краткая запись ID — это решётка, например, можно записать как form#password-form, по такому же принципу, как и с классом

Поиск по кастомным атрибутам

Кастомные атрибуты тоже заслуживают упоминания. У элемента могут быть не только классы и айдишники, но и еще бесконечно множество атрибутов. В исключительных случаях можно искать элементы по этим атрибутам, но только в случае их приличного вида. Например, в случае кнопки «Авторизация» указаны несколько необычных атрибутов, которые вряд ли можно использовать за основу для её поиска:

Локаторы можно и нужно комбинировать! Элементы, состоящие из нескольких классов, айди и других атрибутов, можно объединять в один локатор. Например, возьмем элемент формы, который находится выше кнопки «Авторизация»: form#password-form[method=”post”][class*=”username”]

Итоги поиска локаторов с помощью CSS

классы и id можно писать сокращенно с помощью точки и решетки

: #size = [id=”size”] = [id*=”ze”] = button#size = button[id=”size”]

всё, что не class, и не id в сокращённом виде пишем в [] (квадратных скобках), например, [name=”phone”], [data-qa-id=”regButton”]

Поиск элементов с помощью XPath

XPath в корне отличается от CSS как идеей, так и реализацией. XPath — это полноценный язык для поиска элементов в дереве, причём неважно каком, будь это XML или XHTML. Можно использовать XPath в веб-страницах, нативной мобильной вёрстке и других инструментах.

Я изучал XPath больше месяца с нуля. Проблема была в том, что я никак не понимал принцип его работы — мы ходим от элемента к элементу, но не ясно, как это происходит, как писать красивые пути, какие преимущества у такого подхода. Неделями изучал документацию, статьи на блогах (к сожалению, тогда еще не было человекопонятных статей на Хабре) и видео в ютубе. Мне очень помогло одно видео, где автор объяснял базовые принципы XPath, после чего меня осенило и в голове сложилась картинка. Поэтому хочу поделиться с вами этой информацией, чтобы сократить время на изучение тонны материала. Изучение XPath самостоятельно полезно, но я бы с огромным удовольствием потратил полтора месяца на вещи поважнее.

Предположим, у нас есть следующая структура документа:

div/div/button/span — это и есть путь к элементу с помощью XPath, только первый элемент ищут по всему дереву элементов, поэтому пишут // в начале строки. В данном случае это будет выглядеть так: //div/div/button/span. 2 слэша можно использовать не только в начале — они обозначают то, что мы ищем элемент где-то внутри. Например, //div//span — элемент будет найден, мы пропустили второй div и button.

Главная отличительная особенность XPath — возможность проходить не только от родителя к детям, но и от детей к родителям. Например, есть структура:

Мы можем перейти от кнопки doLogin в кнопку doReg вот так:

Чтобы перейти на уровень выше, как и терминале ОС, нужно написать 2 точки, как показано в примере. С помощью 2 точек мы поднимаемся с уровня span сначала до button, а с button до общего div.

Главный вопрос, который может возникнуть, а где это может пригодиться? Практически всюду, где есть одинаковые блоки, которые отличаются по какому-то одному признаку. Возьмем страницу RDR2 в Epic Games. На середине страницы сейчас перечислены 3 издания:

В DevTools отчётливо видно, что блоки идентичные. Отличия только в названии издания, описании и цене.

Есть задача: нажмите на кнопку «Купить сейчас» у издания Red Dead Online. Для этого надо завязаться на текст издания, подняться до первого общего элемента у названия издания и кнопки и опуститься до кнопки «Купить сейчас».

//*[contains(text(), “Red Dead Online”)]/ancestor::*[contains(@data-component, «OfferCard»)]//*[contains(@data-component, «Purchase»)]

Лайфхак: как найти первый общий элемент у двух элементов?

В XPath, как и в CSS, можно искать по элементам и по атрибутам в элементе. Например:

Можно найти кнопку регистрации:

//*[@href=”/doReg”] или //span[@href=”/doReg”]

//*[@name=”regButton”] или //button[@name=”regButton”]

Как мы можем заметить — звёздочка заменяет название элемента. Где стоит звёздочка, означает, что элемент может называться как угодно. Главное, чтобы внутри него был заданный атрибут. Если мы хотим указать конкретный элемент, то подставляем его вместо звёздочки. Например, путь //span[@href=”/doReg”] — сразу говорит нам, что в элементе span мы ищем @href=”/doReg”, но если нам не важен элемент, то тогда span заменяем на звёздочку //*[@href=”/doReg”].

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

Еще следует упомянуть переходы по смежным осям. В примере выше есть 2 разные оси — 2 button: элементы одинаковые, но отвечают за разные кнопки. Это можно сделать с помощью зарезервированных слов: following-sibling и preceding-sibling.

Например, нам нужно достать кнопку Войти, зная кнопку Регистрация: //*[@name=”regButton”]/following-sibling::*[@name=”loginButton”]. Если нужно найти кнопку Регистрации зная кнопку Войти, то делается это точно также, только ищем в осях, идущих до кнопки Регистрации: //*[@name=”loginButton”]/preceding-sibling::*[@name=”regButton”]. Переходы между осями или дереву (вверх-вниз) всегда происходит через 2 точки, если мы пишем полное название направления, например, following-sibling::, ancestor::

Читайте также:  что делает лаборант на элеваторе

Не всегда есть возможность искать элементы по полному названию класса, так как оно может являться достаточно большим и нечитабельным. В CSS мы это делали с помощью символа звёздочки. Здесь звёздочку заменяет слово contains и работает точно также, как и в CSS. Например, ищем кнопку Войти: //*[contains(@name, “Login”)]. Как мы видим, contains — это что-то вроде функции в XPath. 1 параметр — атрибут, в котором ищем часть текста, 2 — сам текст.

Последней функцией, которую мы рассмотрим, будет text(). Она позволяет искать элемент по тексту, который в нём находится. Например, есть HTML-разметка:

Чтобы найти текст по точному совпадению, нужно писать следующий путь: //*[text()=”Кнопка Войти”]. Но если мы захотим искать по 1 слову, то на помощь приходит комбинация со словом contains, а именно: //*[contains(text(), “Войти”)].

Коротко про «Гибкие локаторы»

Термин «гибкий локатор» применяется к поиску локаторов через CSS и с XPath. Называется он гибким, потому что независимо от текста внутри — локатор не изменится. Для примера снова возьмём страничку с игрой RDR2. На ней есть 3 издания. Сами локаторы не меняются, меняется только текст (название, описание, цена). Общий шаблон локатора будет выглядеть так: //*[contains(text(), “Название издания”)]/ancestor::*[contains(@data-component, «OfferCard»)]//*[contains(@data-component, «Purchase»)]. Текст уже можем в него передавать любой, какой захотим. Так вот именно этот локатор будет называться гибким — его тело остаётся неизменным, а меняются лишь параметры внутри него. В автоматизации мы очень часто пользуемся гибкими локаторами.

Выводы

Мы разобрали 2 основных способа поиска элементов на странице, с помощью CSS и XPath. Небольшое сравнение этих методов:

Плюсы CSS

Минусы CSS

— простой для освоения и полностью граничит с изучением базового CSS

— что-то вроде мифа — он работает быстрее, то есть быстрее ищет элемент на странице, но на фоне мощности современных процессоров эта разница во времени неощутима и составляет пару миллисекунд

— может переходить только от родителя к ребёнку, но не наоборот — вверх подниматься нельзя

— более ограниченный набор функций для поиска элементов, например, нельзя искать элемент по тексту, который в нём находится

— CSS заточен только под веб-страницы

Плюсы XPath

Минусы XPath

— полноценный язык для поиска элементов не только в вебе, но и в других средах и документах

— позволяет перемещаться по дереву вниз и вверх

— гибко работает с осями элементов

— есть очень много функций, которые помогают в поиске локаторов, например, поиску по тексту в элементе или аналог normalize-space, который убирает пробелы у строки по бокам

— работает дольше, чем поиск по CSS, хоть и незначительно

В тестах лучше использовать CSS, но это не всегда реально. Именно поэтому в таких случаях приходит на помощь XPath.

Источник

Стилизация старого доброго элемента button

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

Стили, применяемые к кнопкам по умолчанию

Может, разговор о «стандартных стилях» покажется кому-то обсуждением каких-то элементарных вещей, но, на самом деле, поговорить об этом довольно интересно. Вот стандартная таблица стилей для кнопок из пользовательского агента Google Chrome.

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

Простая кнопка, к которой применены стандартные стили

Свойство appearance этих кнопок установлено в none

Кнопка после сброса свойств

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

Стилизация обычных кнопок

Начнём с базового примера, поговорив о стилизации обычных кнопок, на которых выводится лишь текст. На следующем рисунке представлена «анатомия» обычной кнопки.

Цвет текста (Text Color), размер шрифта (Font Size), фон (Background), скругление углов (Roundness), внутренний отступ (Padding)

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

Обычное состояние кнопки (Normal), получение фокуса (Focus), наведение на кнопку указателя мыши (Hover), отключение кнопки (Disabled)

▍Стили, применяемые к кнопкам при наведении на них мыши и при получении ими фокуса

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

Этот материал указывает на то, что важен порядок добавления стилей, применяемых к кнопке при наведении на неё мыши ( hover ) и при получении ей фокуса ( focus ).

Хорошо, если сначала идёт стиль hover, а потом — стиль focus

Вот как выглядит правильный порядок описания стилей:

▍Минимальная ширина кнопки

Для того чтобы кнопка хорошо выглядела, она должна иметь определённую ширину. Важно заранее об этом подумать и принять во внимание длинные и короткие надписи, которые могут содержаться на кнопках. Благодаря свойству min-width можно установить минимальную ширину кнопки. Вот моя статья, где в подробностях обсуждается это и другие подобные свойства.

Стоит задавать свойство кнопок min-width

▍Внутренние отступы

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

Взглянем на следующий рисунок.

Рекомендовано назначать кнопкам внутренние отступы

▍Семейство шрифта, используемого для надписей, расположенных на кнопках

▍Стилизация отключённых кнопок

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

Вот HTML-код, описывающий отключённую кнопку:

Вот CSS-код стилизации такой кнопки:

Когда кнопка отключена, она не может получить фокус с клавиатуры и удаляется из дерева доступности элементов страницы.

▍Внешний вид указателя мыши при наведении его на кнопку

Стандартный указатель мыши, наведённый на кнопку, выглядит как стрелка. Мне нравится этот ответ на StackOverflow: «Кнопки — это традиционный элемент управления настольных программ. Это — среда, в которой указатель в виде руки никогда не использовался до наступления эры интернета. Когда на веб-страницах стали применять тот же самый элемент управления, разработчики просто пытались сделать так, чтобы кнопки выглядели так же, как в настольных приложениях».

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

Стандартный курсор-стрелка и улучшенный курсор в виде руки.

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

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

Кнопки со значком

Иногда нужно, чтобы на кнопке был бы некий значок. Это может понадобиться для того, чтобы выделить кнопку, или чтобы лучше проинформировать пользователя о роли кнопки. Важно, чтобы кнопки со значками были бы доступны пользователям с ограниченными возможностями.

Примеры кнопок со значками

Обратите внимание на то, что я воспользовался стилем vertical-align: middle для того чтобы выровнять значок и содержимое кнопки по вертикали.

Читайте также:  что делать если все симптомы коронавируса а тест отрицательный

Вот HTML-код кнопки, о которой идёт речь:

Может показаться, что теперь достаточно просто скрыть элемент span и дело будет сделано:

Хотя при таком подходе текст пропадает, а значок остаётся, это очень плохо в плане доступности контента. Кнопку уже «не видят» инструменты для чтения с экрана. Например, VoiceOver в macOS сообщает о том, что такая кнопка — это просто «Button», без каких-либо подробностей о ней. У этой проблемы есть несколько решений.

▍Использование SVG-значков

▍Настройка размеров кнопки со значком

Кнопка, у которой задано CSS-свойство min-width, и кнопка, у которой это свойство не задано

▍Визуальное скрытие текста

▍Установка размера шрифта в 0

▍Использование атрибута aria-label

Если вы хотите больше узнать о кнопках со значками — взгляните на этот материал.

Кнопки, содержащие несколько строк текста

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

Кнопка, содержащая две строки текста

Тут показана кнопка для формы подписки, содержащая основной и вспомогательный текст. Как сделать такую кнопку и при этом не забыть о её доступности для людей с ограниченными возможностями? Вот соответствующий HTML-код:

Средство для чтения с экрана «озвучит» эту кнопку как «Subscribe to our newsletter 240K+ subscribers». Когда пользователь это услышит, это его может запутать, так как ничто не будет разделять две строки текста, выводимые на кнопке. Взгляните на скриншот инструмента Chrome для исследования доступности элементов.

Исследование доступности элементов в Chrome

Для того чтобы не путать пользователей, я предпочёл бы скрыть вторую строку текста от средств для чтения с экрана. Сделать это можно, использовав атрибут aria-hidden в соответствующем элементе :

Если по какой-то причине изменить HTML-разметку нельзя, есть и другой способ добавления дополнительного текста на кнопку. Решение этой проблемы, которое показалось мне интересным, я нашёл на сайте Smashing Magazine. Оно заключается в том, чтобы размещать содержимое, пользуясь псевдоэлементами. При таком подходе средства для чтения с экрана не будут видеть ничего лишнего. Вот CSS-код этого решения:

Ссылки () или кнопки ( )?

Когда стоит пользоваться ссылками, а когда — кнопками? Для начала давайте поговорим о том, чем они отличаются друг от друга.

▍Ссылки

▍Кнопки

Использование ссылок и кнопок

▍Элемент не обязан выглядеть как кнопка

Мне нравится этот пример, в котором, с учётом требований доступности контента, реализована панель-«аккордеон». Вначале, если представить, что JavaScript недоступен, результат рендеринга разметки выглядит так, как показано ниже.

Материалы страницы в условиях недоступности JavaScript

Вот HTML-код фрагмента такой разметки:

В случае доступности JavaScript вышеприведённая разметка позволит описать элементы, которые могут сворачиваться и раскрываться. Достигается это путём создания кнопки и добавления её в элемент

Материалы страницы в условиях, когда JavaScript-функциональность доступна

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

▍Кнопка загрузки

Ссылка для загрузки документа, оформленная как кнопка

Вот код этой ссылки:

При таком подходе в нашем распоряжении оказывается ссылка, стилизованная как кнопка, которая делает своё дело, используя лишь семантические структуры HTML.

Кнопки с обводкой

Обычная кнопка при наведении на неё мыши становится кнопкой с обводкой

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

Градиентные кнопки

Когда я работал над статьёй о позиционировании элементов, мне понадобилась кнопка с градиентным заполнением.

Мне было нужно нечто, подобное следующему рисунку.

Градиентная кнопка и её вариант с обводкой

Тут представлены два варианта кнопки — градиентная кнопка и кнопка с обводкой. Для того чтобы добиться такого внешнего вида кнопки, мне нужно было, чтобы у базовой (градиентной) кнопки имелась бы прозрачная граница. Эта граница будет показана только для кнопки с обводкой.

Тут всё, вроде бы, выглядит разумно, но в ходе работы я столкнулся со странной проблемой. Я даже попытался решить её, попросив помощи у пользователей Twitter. Эта проблема представлена на следующем рисунке.

Обычная кнопка, кнопка с градиентом (граница, на самом деле, прозрачная; цветом она выведена лишь для наглядности), кнопка со странными краями

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

Я попробовал добавить к кнопке широкую границу для того чтобы понаблюдать за тем, что из этого получится. Обратите внимание на то, как повторяется градиент, и на то, что его размер соответствует свойству padding кнопки.

Кнопка с широкими границами и градиент

Вот, если хотите поэкспериментировать, пример на CodePen.

Что лучше — height или padding?

▍Фиксированная высота

Предположим, что у нас имеется кнопка, стилизованная следующим образом:

При таком подходе текст не выравнивается по центру. Выглядит всё это так, как показано ниже.

Кнопка, текст которой не выровнен по центру

Но у этого метода есть минусы:

▍Вертикальный внутренний отступ

Существуют шрифты, которые центруются очень хорошо. А есть такие, которые ведут себя иначе. Иногда для достижения цели одно из значений вертикального внутреннего отступа нужно немного изменить. Взгляните на следующую кнопку.

Попытка центровки текста кнопки

Вот CSS-код стилизации этой кнопки:

В этом случае содержимое кнопки выглядит слегка смещённым. Значение верхнего внутреннего отступа нужно немного уменьшить:

Оборачивание содержимого кнопки в тег

В ходе экспериментов я выяснил, что центровка текста кнопок Adobe немного сбита. Вот как это выглядит.

Центровка немного сбита

Я исследовал эти кнопки и заметил интересный паттерн. Содержимое обёрнуто в элемент с указанием фиксированной высоты для кнопки.

Изменение высоты кнопки и автоматическое центрирование её содержимого

Вот и всё. Хочу отметить, что при написании данного раздела мне помогла эта статья.

Кнопки внутри flexbox- или grid-контейнеров

Тут у вас может появиться вопрос о том, какое отношение кнопки имеют к flex- и grid-макетам. Позвольте мне прояснить этот вопрос.

Я работал над разделом одного проекта. Мне нужно было вертикально центрировать его содержимое. Поэтому я использовал flex-макет:

То, что у меня получилось, меня несколько удивило.

Результат использования flex-макета

По умолчанию каждый flex-элемент растягивается в пределах ширины родительского элемента. Именно это и произошло с кнопкой, представленной на предыдущем рисунке. Для того чтобы избежать этой неприятности, нужно настроить свойство align-self :

Вот как кнопка будет выглядеть после этого.

Кнопка выглядит гораздо лучше

Кнопка, растянутая по высоте

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

Решение проблемы растянутой кнопки

Использование единиц измерения em

Единицу измерения em можно использовать для правильной настройки размеров кнопок. Эта единица измерения в такой ситуации весьма полезна. Единица измерения em равна font-size элемента ( px или rem ). Взглянем на следующий пример:

Кнопки разных размеров

А вот фрагменты CSS-кода, в котором используется единица измерения em :

Для кнопок разного типа нужно создать классы, в которых задаётся разный размер шрифта:

→ Вот пример использования подобных кнопок на CodePen

→ Вот моя статья на эту тему. Рекомендую с ней ознакомиться

Анимация и переходы

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

Итоги

Мне было очень приятно работать над этим материалом. Его написание заняло у меня больше года. Я счастлив от того, что он, наконец, опубликован. Надеюсь, вы нашли здесь что-то такое, что вам пригодится.

Уважаемые читатели! Известны ли вам какие-нибудь полезные способы работы с кнопками, которые остались за рамками этой статьи?

Источник

Сказочный портал