Общий обзор того, как создавать адаптивные к цвету, отзывчивые и доступные компоненты <button> .
В этом посте я хочу поделиться своими мыслями о том, как создать адаптивный по цвету, отзывчивый и доступный элемент <button> . Попробуйте демо-версию и посмотрите исходный код.
Если вам удобнее видео, вот версия этого поста на YouTube:
Обзор
Элемент <button> создан для взаимодействия с пользователем. Событие click срабатывает от клавиатуры, мыши, сенсорного экрана, голоса и других факторов, с интеллектуальными правилами определения времени срабатывания . Он также поставляется с некоторыми стилями по умолчанию в каждом браузере, поэтому вы можете использовать их напрямую без каких-либо настроек. Используйте color-scheme , чтобы включить светлые и темные кнопки, предоставляемые браузером.
Существуют также различные типы кнопок , каждый из которых показан во встроенном примере Codepen. <button> без указания типа адаптируется к расположению внутри <form> , меняя тип на «Отправить».
<!-- buttons -->
<button></button>
<button type="submit"></button>
<button type="button"></button>
<button type="reset"></button>
<!-- button state -->
<button disabled></button>
<!-- input buttons -->
<input type="button" />
<input type="file">
В рамках конкурса GUI Challenge этого месяца каждая кнопка получит стили, которые помогут визуально различить её назначение. Кнопки сброса будут иметь предупреждающие цвета, поскольку они являются деструктивными, а кнопки отправки получат синий акцентный текст, чтобы выглядеть немного более заметными, чем обычные кнопки.

Кнопки также имеют псевдоклассы , которые можно использовать для стилизации с помощью CSS. Эти классы предоставляют возможности для настройки внешнего вида кнопки: :hover для наведения курсора мыши на кнопку, :active для нажатия мыши или клавиши клавиатуры, а также :focus или :focus-visible для помощи в стилизации с использованием вспомогательных технологий.
button:hover {}
button:active {}
button:focus {}
button:focus-visible {}

Разметка
В дополнение к типам кнопок, предусмотренным спецификацией HTML, я добавил кнопку со значком и кнопку с пользовательским классом btn-custom .
<button>Default</button>
<input type="button" value="<input>"/>
<button>
<svg viewBox="0 0 24 24" width="24" height="24" aria-hidden="true">
<path d="..." />
</svg>
Icon
</button>
<button type="submit">Submit</button>
<button type="button">Type Button</button>
<button type="reset">Reset</button>
<button disabled>Disabled</button>
<button class="btn-custom">Custom</button>
<input type="file">
Затем, для тестирования, каждая кнопка размещается внутри формы. Таким образом, я могу убедиться, что стили корректно обновляются для кнопки по умолчанию, которая работает как кнопка отправки. Я также меняю стратегию использования иконок, с встроенного SVG на маскированный SVG, чтобы обеспечить одинаковую эффективность обоих вариантов.
<form>
<button>Default</button>
<input type="button" value="<input>"/>
<button>Icon <span data-icon="cloud"></span></button>
<button type="submit">Submit</button>
<button type="button">Type Button</button>
<button type="reset">Reset</button>
<button disabled>Disabled</button>
<button class="btn-custom btn-large" type="button">Large Custom</button>
<input type="file">
</form>
Матрица комбинаций на данном этапе просто поражает воображение. С учётом типов кнопок, псевдоклассов и нахождения внутри или вне формы, существует более 20 комбинаций кнопок. Хорошо, что CSS помогает нам чётко описать каждую из них!
Доступность
Кнопки, естественно, доступны, но есть несколько распространенных улучшений.
Наведите курсор и сфокусируйтесь одновременно.
Мне нравится объединять :hover и :focus вместе с помощью функционального псевдоселектора :is() . Это помогает гарантировать, что мои интерфейсы всегда учитывают стили клавиатуры и вспомогательных технологий.
button:is(:hover, :focus) {
…
}
Интерактивное кольцо фокусировки
Мне нравится анимировать кольцо фокусировки для пользователей клавиатуры и вспомогательных технологий. Я делаю это, анимируя отступление контура от кнопки на 5 пикселей, но только когда кнопка неактивна. Это создает эффект, при котором кольцо фокусировки уменьшается до размера кнопки при нажатии.
:where(button, input):where(:not(:active)):focus-visible {
outline-offset: 5px;
}
Обеспечение проходного цветового контраста
Существует как минимум четыре различных цветовых сочетания между светлыми и темными цветами, для которых необходимо учитывать цветовой контраст: кнопка, кнопка отправки, кнопка сброса и отключенная кнопка. VisBug используется здесь для проверки и отображения всех их оценок одновременно:
Скрытие значков от людей, которые их не видят.
При создании кнопки с иконкой, иконка должна визуально дополнять текст кнопки. Это также означает, что иконка не будет полезна людям с нарушениями зрения. К счастью, браузер предоставляет способ скрыть элементы от программ чтения с экрана, поэтому людям с нарушениями зрения не придется возиться с декоративными изображениями на кнопках:
<button>
<svg … aria-hidden="true">...</svg>
Icon Button
</button>

Стили
В следующем разделе я сначала создам пользовательскую систему свойств для управления адаптивными стилями кнопки. С помощью этих пользовательских свойств я смогу начать выбирать элементы и настраивать их внешний вид.
Адаптивная стратегия пользовательских свойств
Стратегия использования пользовательских свойств в этом задании по созданию графического интерфейса очень похожа на ту, что применяется при построении цветовой схемы . Для адаптивной системы светлых и темных цветов для каждой темы определяется и соответствующим образом называется пользовательское свойство. Затем одно пользовательское свойство используется для хранения текущего значения темы и присваивается свойству CSS. Позже это единственное пользовательское свойство может быть обновлено до другого значения, после чего обновляется стиль кнопки.
button {
--_bg-light: white;
--_bg-dark: black;
--_bg: var(--_bg-light);
background-color: var(--_bg);
}
@media (prefers-color-scheme: dark) {
button {
--_bg: var(--_bg-dark);
}
}
Мне нравится, что светлая и темная темы декларативны и понятны. Косвенная адресация и абстракция перенесены в пользовательское свойство --_bg , которое теперь является единственным "реактивным" свойством; --_bg-light и --_bg-dark — статические. Также понятно, что светлая тема является темой по умолчанию, а темная применяется только при определенных условиях.
Подготовка к обеспечению единообразия дизайна
общий селектор
Следующий селектор используется для выбора всех типов кнопок и поначалу может показаться немного сложным. Используется конструкция :where() , поэтому настройка кнопки не требует специфичности. Кнопки часто адаптируются для альтернативных сценариев, и селектор :where() упрощает эту задачу. Внутри :where() выбирается каждый тип кнопки, включая ` ::file-selector-button , который нельзя использовать внутри :is() или :where() .
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"],
input[type="file"]
),
:where(input[type="file"])::file-selector-button {
…
}
Все пользовательские свойства будут находиться в пределах этого селектора. Пора рассмотреть все пользовательские свойства! В этой кнопке используется довольно много пользовательских свойств. Я опишу каждую группу по мере продвижения, а затем в конце раздела расскажу о темном и уменьшенном контекстах анимации.
цвет акцента кнопки
Кнопки отправки и значки — отличное место для добавления ярких цветовых акцентов:
--_accent-light: hsl(210 100% 40%);
--_accent-dark: hsl(210 50% 70%);
--_accent: var(--_accent-light);
Цвет текста кнопки
Цвета текста на кнопках не белые и не черные, а затемненные или осветленные версии параметра --_accent заданного с помощью hsl() и с сохранением оттенка 210 :
--_text-light: hsl(210 10% 30%);
--_text-dark: hsl(210 5% 95%);
--_text: var(--_text-light);
цвет фона кнопки
Фон кнопок использует тот же шаблон hsl() , за исключением кнопок светлой темы — для них установлен белый цвет, чтобы их поверхность казалась близкой к пользователю или на фоне других поверхностей:
--_bg-light: hsl(0 0% 100%);
--_bg-dark: hsl(210 9% 31%);
--_bg: var(--_bg-light);
Фон кнопки хорошо
Этот цвет фона используется для того, чтобы одна поверхность отображалась позади других поверхностей, например, в качестве фона поля ввода файла:
--_input-well-light: hsl(210 16% 87%);
--_input-well-dark: hsl(204 10% 10%);
--_input-well: var(--_input-well-light);
Отступы кнопок
Интервал вокруг текста на кнопке задается с помощью единицы измерения ch , которая является относительной длиной по отношению к размеру шрифта. Это становится критически важным, когда для больших кнопок можно просто пропорционально увеличить font-size и масштаб кнопки:
--_padding-inline: 1.75ch;
--_padding-block: .75ch;
Рамка из пуговиц
Радиус скругления углов кнопки сохраняется в пользовательском свойстве, чтобы поле ввода файла соответствовало другим кнопкам. Цвета границ соответствуют установленной адаптивной цветовой системе:
--_border-radius: .5ch;
--_border-light: hsl(210 14% 89%);
--_border-dark: var(--_bg-dark);
--_border: var(--_border-light);
эффект подсветки при наведении курсора на кнопку
Эти свойства определяют размер для перехода при взаимодействии, а цвет подсветки следует адаптивной цветовой системе. Мы рассмотрим, как они взаимодействуют, позже в этой статье, но в конечном итоге они используются для эффекта box-shadow :
--_highlight-size: 0;
--_highlight-light: hsl(210 10% 71% / 25%);
--_highlight-dark: hsl(210 10% 5% / 25%);
--_highlight: var(--_highlight-light);
тень текста кнопки
Каждая кнопка имеет едва заметную тень. Это помогает тексту располагаться поверх кнопки, улучшая читаемость и добавляя приятный элемент презентабельности.
--_ink-shadow-light: 0 1px 0 var(--_border-light);
--_ink-shadow-dark: 0 1px 0 hsl(210 11% 15%);
--_ink-shadow: var(--_ink-shadow-light);
Значок кнопки
Благодаря использованию единицы измерения относительной длины ch , значки имеют размер двух символов, что позволяет им масштабироваться пропорционально тексту кнопки. Цвет значка определяется параметром --_accent-color , который является адаптивным и соответствует теме оформления.
--_icon-size: 2ch;
--_icon-color: var(--_accent);
Тень кнопки
Для того чтобы тени правильно адаптировались к свету и тени, они должны менять как цвет, так и прозрачность. Тени в светлой тематике лучше всего смотрятся, когда они едва заметны и имеют оттенок, близкий к цвету поверхности, на которую они накладываются. Тени в темной тематике должны быть темнее и насыщеннее, чтобы они могли накладываться на более темные цвета поверхности.
--_shadow-color-light: 220 3% 15%;
--_shadow-color-dark: 220 40% 2%;
--_shadow-color: var(--_shadow-color-light);
--_shadow-strength-light: 1%;
--_shadow-strength-dark: 25%;
--_shadow-strength: var(--_shadow-strength-light);
Благодаря адаптивным цветам и интенсивности я могу создавать тени двух уровней глубины:
--_shadow-1: 0 1px 2px -1px hsl(var(--_shadow-color)/calc(var(--_shadow-strength) + 9%));
--_shadow-2:
0 3px 5px -2px hsl(var(--_shadow-color)/calc(var(--_shadow-strength) + 3%)),
0 7px 14px -5px hsl(var(--_shadow-color)/calc(var(--_shadow-strength) + 5%));
Кроме того, чтобы придать кнопкам слегка трёхмерный вид, используется тень толщиной 1px , создающая иллюзию объёма:
--_shadow-depth-light: 0 1px var(--_border-light);
--_shadow-depth-dark: 0 1px var(--_bg-dark);
--_shadow-depth: var(--_shadow-depth-light);
Переходы между кнопками
Следуя принципу адаптивных цветов, я создаю два статических свойства для хранения параметров системы дизайна:
--_transition-motion-reduce: ;
--_transition-motion-ok:
box-shadow 145ms ease,
outline-offset 145ms ease
;
--_transition: var(--_transition-motion-reduce);
Все свойства вместе в селекторе
:where( button, input[type="button"], input[type="submit"], input[type="reset"], input[type="file"] ), :where(input[type="file"])::file-selector-button { --_accent-light: hsl(210 100% 40%); --_accent-dark: hsl(210 50% 70%); --_accent: var(--_accent-light);--_text-light: hsl(210 10% 30%); --_text-dark: hsl(210 5% 95%); --_text: var(--_text-light);
--_bg-light: hsl(0 0% 100%); --_bg-dark: hsl(210 9% 31%); --_bg: var(--_bg-light);
--_input-well-light: hsl(210 16% 87%); --_input-well-dark: hsl(204 10% 10%); --_input-well: var(--_input-well-light);
--_padding-inline: 1.75ch; --_padding-block: .75ch;
--_border-radius: .5ch; --_border-light: hsl(210 14% 89%); --_border-dark: var(--_bg-dark); --_border: var(--_border-light);
--_highlight-size: 0; --_highlight-light: hsl(210 10% 71% / 25%); --_highlight-dark: hsl(210 10% 5% / 25%); --_highlight: var(--_highlight-light);
--_ink-shadow-light: 0 1px 0 hsl(210 14% 89%); --_ink-shadow-dark: 0 1px 0 hsl(210 11% 15%); --_ink-shadow: var(--_ink-shadow-light);
--_icon-size: 2ch; --_icon-color-light: var(--_accent-light); --_icon-color-dark: var(--_accent-dark); --_icon-color: var(--accent, var(--_icon-color-light));
--_shadow-color-light: 220 3% 15%; --_shadow-color-dark: 220 40% 2%; --_shadow-color: var(--_shadow-color-light); --_shadow-strength-light: 1%; --_shadow-strength-dark: 25%; --_shadow-strength: var(--_shadow-strength-light); --_shadow-1: 0 1px 2px -1px hsl(var(--_shadow-color)/calc(var(--_shadow-strength) + 9%)); --_shadow-2: 0 3px 5px -2px hsl(var(--_shadow-color)/calc(var(--_shadow-strength) + 3%)), 0 7px 14px -5px hsl(var(--_shadow-color)/calc(var(--_shadow-strength) + 5%)) ;
--_shadow-depth-light: hsl(210 14% 89%); --_shadow-depth-dark: var(--_bg-dark); --_shadow-depth: var(--_shadow-depth-light);
--_transition-motion-reduce: ; --_transition-motion-ok: box-shadow 145ms ease, outline-offset 145ms ease ; --_transition: var(--_transition-motion-reduce); }

Темные тематические адаптации
Значение статических свойств -light и -dark становится понятным, когда заданы свойства темной темы:
@media (prefers-color-scheme: dark) {
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"],
input[type="file"]
),
:where(input[type="file"])::file-selector-button {
--_bg: var(--_bg-dark);
--_text: var(--_text-dark);
--_border: var(--_border-dark);
--_accent: var(--_accent-dark);
--_highlight: var(--_highlight-dark);
--_input-well: var(--_input-well-dark);
--_ink-shadow: var(--_ink-shadow-dark);
--_shadow-depth: var(--_shadow-depth-dark);
--_shadow-color: var(--_shadow-color-dark);
--_shadow-strength: var(--_shadow-strength-dark);
}
}
Этот дизайн не только хорошо читается, но и позволяет пользователям этих настраиваемых кнопок с уверенностью использовать сами элементы, зная, что они будут соответствующим образом адаптироваться к предпочтениям пользователя.
Сниженная адаптация к движению
Если движение не вызывает проблем у данного пользователя, присвойте параметру --_transition значение переменной var(--_transition-motion-ok) :
@media (prefers-reduced-motion: no-preference) {
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"],
input[type="file"]
),
:where(input[type="file"])::file-selector-button {
--_transition: var(--_transition-motion-ok);
}
}
Несколько общих стилей
Для кнопок и полей ввода необходимо установить тип шрифта « inherit , чтобы они соответствовали шрифтам остальной части страницы; в противном случае их стиль будет определяться браузером. Это также относится к letter-spacing . Установка line-height равным 1.5 задает размер рамки, чтобы текст имел некоторое пространство сверху и снизу:
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"],
input[type="file"]
),
:where(input[type="file"])::file-selector-button {
/* …CSS variables */
font: inherit;
letter-spacing: inherit;
line-height: 1.5;
border-radius: var(--_border-radius);
}

Кнопки стиля
Регулировка селектора
Элемент input input[type="file"] не является кнопкой в поле ввода, ею является псевдоэлемент ::file-selector-button , поэтому я удалил input[type="file"] из списка:
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"],
input[type="file"]
),
:where(input[type="file"])::file-selector-button {
}
Настройка курсора и сенсорного экрана
Сначала я стилизую курсор под стиль pointer , что помогает кнопке показать пользователям мыши, что она интерактивна. Затем я добавляю touch-action: manipulation чтобы щелчки не требовали ожидания и наблюдения за возможным двойным щелчком, что делает нажатие кнопок более быстрым:
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"]
),
:where(input[type="file"])::file-selector-button {
cursor: pointer;
touch-action: manipulation;
}
Цвета и рамки
Далее я настраиваю размер шрифта, фон, цвет текста и границы, используя некоторые из адаптивных пользовательских свойств, заданных ранее:
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"]
),
:where(input[type="file"])::file-selector-button {
…
font-size: var(--_size, 1rem);
font-weight: 700;
background: var(--_bg);
color: var(--_text);
border: 2px solid var(--_border);
}

Тени
Кнопки созданы с использованием отличных приемов. text-shadow адаптируется к свету и темноте, создавая приятный, едва заметный эффект того, что текст кнопки хорошо располагается поверх фона. Для box-shadow назначены три тени. Первая, --_shadow-2 , — это обычная тень блока. Вторая тень — это визуальный эффект, создающий впечатление, что кнопка немного скошена. Последняя тень предназначена для подсветки при наведении курсора, изначально ее размер равен 0, но позже ей будет присвоен размер, и она будет плавно переходить от кнопки.
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"]
),
:where(input[type="file"])::file-selector-button {
…
box-shadow:
var(--_shadow-2),
var(--_shadow-depth),
0 0 0 var(--_highlight-size) var(--_highlight)
;
text-shadow: var(--_ink-shadow);
}

Макет
Я задал кнопке flexbox -макет, а именно inline-flex -макет, который будет соответствовать её содержимому. Затем я центрировал текст и выравнивал дочерние элементы по центру по вертикали и горизонтали. Это поможет иконкам и другим элементам кнопки правильно выравниваться.
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"]
),
:where(input[type="file"])::file-selector-button {
…
display: inline-flex;
justify-content: center;
align-items: center;
text-align: center;
}

Расстояние
Для отступов между кнопками я использовал gap , чтобы соседние элементы не соприкасались, и логические свойства padding, поэтому отступы между кнопками работают для всех текстовых макетов.
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"]
),
:where(input[type="file"])::file-selector-button {
…
gap: 1ch;
padding-block: var(--_padding-block);
padding-inline: var(--_padding-inline);
}

Сенсорный интерфейс и управление мышью
Следующий раздел предназначен в основном для пользователей сенсорных мобильных устройств. Первое свойство, user-select , предназначено для всех пользователей; оно предотвращает выделение текста на кнопке. Это особенно заметно на сенсорных устройствах, когда кнопка нажата и удерживается, а операционная система выделяет текст на кнопке.
Как правило, я обнаружил, что это не соответствует пользовательскому опыту использования кнопок во встроенных приложениях, поэтому я отключаю эту функцию, устанавливая параметр user-select в значение none. Цвета подсветки при касании ( -webkit-tap-highlight-color ) и контекстные меню операционной системы ( -webkit-touch-callout ) — это другие функции кнопок, ориентированные на веб-технологии, которые не соответствуют общим ожиданиям пользователей, поэтому я удаляю и их.
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"]
),
:where(input[type="file"])::file-selector-button {
…
user-select: none;
-webkit-tap-highlight-color: transparent;
-webkit-touch-callout: none;
}
Переходы
Адаптивная переменная --_transition присваивается свойству перехода :
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"]
),
:where(input[type="file"])::file-selector-button {
…
transition: var(--_transition);
}
При наведении курсора, когда пользователь не нажимает на кнопку, отрегулируйте размер тени, чтобы создать эффект фокусировки, будто кнопка «растет» изнутри:
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"]
):where(:not(:active):hover) {
--_highlight-size: .5rem;
}
После фокусировки увеличьте смещение контура фокусировки относительно кнопки, чтобы создать эффект, будто фокус вырастает изнутри кнопки:
:where(button, input):where(:not(:active)):focus-visible {
outline-offset: 5px;
}
Иконки
Для работы с иконками в селектор добавлен селектор :where() для прямых дочерних элементов SVG или элементов с пользовательским атрибутом data-icon . Размер иконки задается с помощью пользовательского свойства, используя логические свойства inline и block. Задается цвет обводки, а также drop-shadow соответствующая text-shadow . flex-shrink установлен на 0 , чтобы иконка никогда не сжималась. Наконец, я выбираю иконки с линиями и назначаю им стили с помощью fill: none и round концов линий и соединений линий:
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"]
) > :where(svg, [data-icon]) {
block-size: var(--_icon-size);
inline-size: var(--_icon-size);
stroke: var(--_icon-color);
filter: drop-shadow(var(--_ink-shadow));
flex-shrink: 0;
fill: none;
stroke-linecap: round;
stroke-linejoin: round;
}

Настройка кнопок отправки
Мне хотелось, чтобы кнопки отправки выглядели немного рекламными, и я добился этого, сделав цвет текста кнопок акцентным цветом:
:where(
[type="submit"],
form button:not([type],[disabled])
) {
--_text: var(--_accent);
}

Настройка кнопок сброса
Я хотел, чтобы кнопки сброса имели встроенные предупреждающие знаки, которые бы оповещали пользователей об их потенциально деструктивном поведении. Я также решил оформить кнопку в светлой теме с большим количеством красных акцентов, чем в темной. Настройка осуществляется путем изменения соответствующего светлого или темного базового цвета, и кнопка обновит свой стиль:
:where([type="reset"]) {
--_border-light: hsl(0 100% 83%);
--_highlight-light: hsl(0 100% 89% / 20%);
--_text-light: hsl(0 80% 50%);
--_text-dark: hsl(0 100% 89%);
}
Мне также показалось, что было бы неплохо, если бы цвет контура выделяющего элемента совпадал с акцентным красным цветом. Цвет текста меняется с темно-красного на светло-красный. Я задаю цвет контура в соответствии с этим, используя ключевое слово currentColor :
:where([type="reset"]):focus-visible {
outline-color: currentColor;
}

Настройка отключенных кнопок
Слишком часто при попытке сделать неактивную кнопку менее заметной, чтобы она выглядела менее активной, у отключенных кнопок наблюдается плохой цветовой контраст. Я протестировал каждый набор цветов и убедился, что они соответствуют требованиям, изменяя значение яркости HSL до тех пор, пока результат в DevTools или VisBug не стал приемлемым.
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"]
)[disabled] {
--_bg: none;
--_text-light: hsl(210 7% 40%);
--_text-dark: hsl(210 11% 71%);
cursor: not-allowed;
box-shadow: var(--_shadow-1);
}

Настройка кнопок ввода файла
Кнопка ввода файла представляет собой контейнер для элемента `<span>` и кнопки. CSS позволяет немного изменить стиль контейнера ввода, а также вложенной кнопки, но не элемента `<span>`. Контейнеру задан параметр max-inline-size , чтобы он не увеличивался больше необходимого размера, а inline-size: 100% позволяет ему уменьшаться и соответствовать контейнерам меньшего размера. Цвет фона установлен на адаптивный цвет, который темнее других поверхностей, поэтому он выглядит так, будто находится за кнопкой выбора файла.
:where(input[type="file"]) {
inline-size: 100%;
max-inline-size: max-content;
background-color: var(--_input-well);
}
Кнопке выбора файла и кнопкам ввода типа задан специальный параметр appearance: none , чтобы удалить любые стили, предоставленные браузером, которые не были переопределены стилями других кнопок.
:where(input[type="button"]),
:where(input[type="file"])::file-selector-button {
appearance: none;
}
Наконец, к inline-end кнопки добавляется отступ, чтобы отодвинуть текст, отображаемый в виде тега <span>, от кнопки, создавая тем самым некоторое пространство.
:where(input[type="file"])::file-selector-button {
margin-inline-end: var(--_padding-inline);
}

Особые исключения для темной темы
Я сделал фон основных кнопок действий более темным для повышения контрастности текста, что придало им немного более рекламный вид.
@media (prefers-color-scheme: dark) {
:where(
[type="submit"],
[type="reset"],
[disabled],
form button:not([type="button"])
) {
--_bg: var(--_input-well);
}
}

Создание вариантов
Ради интереса и практичности я решил показать, как создать несколько вариантов. Один вариант очень яркий, похожий на то, как часто выглядят основные кнопки. Другой вариант — большой. Последний вариант имеет иконку, заполненную градиентом.
Яркая кнопка
Чтобы добиться такого стиля кнопки, я напрямую заменил базовые свойства на синие. Хотя это было быстро и легко, это убирает адаптивные свойства и выглядит одинаково как в светлой, так и в темной теме.
.btn-custom {
--_bg: linear-gradient(hsl(228 94% 67%), hsl(228 81% 59%));
--_border: hsl(228 89% 63%);
--_text: hsl(228 89% 100%);
--_ink-shadow: 0 1px 0 hsl(228 57% 50%);
--_highlight: hsl(228 94% 67% / 20%);
}

Большая кнопка
Такой стиль кнопки достигается путем изменения пользовательского свойства --_size . Отступы и другие элементы пространства задаются относительно этого размера и масштабируются пропорционально новому размеру.
.btn-large {
--_size: 1.5rem;
}

Кнопка-иконка
Этот эффект иконки никак не связан со стилями нашей кнопки, но он демонстрирует, как его можно достичь всего несколькими свойствами CSS, и насколько хорошо кнопка обрабатывает иконки, которые не являются встроенными SVG-изображениями.
[data-icon="cloud"] {
--icon-cloud: url("https://api.iconify.design/mdi:apple-icloud.svg") center / contain no-repeat;
-webkit-mask: var(--icon-cloud);
mask: var(--icon-cloud);
background: linear-gradient(to bottom, var(--_accent-dark), var(--_accent-light));
}
![]()
Заключение
Теперь, когда вы знаете, как я это сделал, как бы вы поступили иначе?! 🙂
Давайте разнообразим наши подходы и изучим все способы создания веб-контента.
Создайте демо-запись, пришлите мне ссылки в Твиттере , и я добавлю её в раздел ремиксов сообщества ниже!
Ремиксы от сообщества
Пока здесь ничего интересного нет.
Ресурсы
- Исходный код на GitHub