构建按钮组件

基础性地概述了如何构建颜色自适应、响应式且无障碍的 <button> 组件。

在本文中,我想分享一下关于如何构建自适应颜色、自适应且易于访问的 <button> 元素的想法。 试用演示并查看源代码

在浅色和深色主题中,通过键盘和鼠标与按钮进行互动。

如果您更喜欢视频,可以观看此博文的 YouTube 版本:

概览

Browser Support

  • Chrome: 1.
  • Edge: 12.
  • Firefox: 1.
  • Safari: 1.

Source

<button> 元素专为用户互动而构建。其 click 事件由键盘、鼠标、触摸、语音等触发,并具有关于其时间的智能规则。它还在每个浏览器中提供了一些默认样式,因此您可以直接使用这些样式,而无需进行任何自定义。使用 color-scheme 还可以选择启用浏览器提供的浅色和深色按钮。

此外,还有不同类型的按钮,每个按钮都显示在前面的 Codepen 嵌入中。没有类型的 <button> 将适应 <form> 中的类型,并更改为提交类型。

<!-- buttons -->
<button></button>
<button type="su><bmit&qu>o<t;/button
button typ><e=">;<button"/button><
button> t<ype="reset&quo>t<;/button

!-- b><utton s>ta<te --
button disable>d</button

!-- input bu>t<tons --
input typ>e="button" /
input type="file"

在本月的 GUI 挑战中,每个按钮都将获得样式,以帮助直观区分其意图。重置按钮具有警告颜色,因为它们具有破坏性;提交按钮具有蓝色强调文本,因此它们看起来比常规按钮更醒目。

预览所有按钮类型的最终集合,包括表单内和表单外的按钮,并对图标按钮和自定义按钮进行了优化。
所有按钮类型的最终集合预览,包括表单内和表单外的按钮, 并为图标按钮和自定义按钮添加了精美元素

按钮还具有伪类,可供 CSS 用于设置样式。这些类提供 CSS 钩子,用于自定义按钮的外观::hover 用于鼠标悬停在按钮上时,:active 用于鼠标或键盘按下时,:focus 或 :focus-visible 用于辅助技术样式。

button:hover {}
button:active {}
button:focus {}
button:focus-visible {}
深色主题中所有按钮类型的最终集合的预览。
深色主题中所有按钮类型的最终集合预览

Markup

除了 HTML 规范提供的按钮类型外,我还添加了一个带图标的按钮和一个带自定义类 btn-custom 的按钮。

<button>Default</button>
<input type="button&quo<t; va>lu>e<=">;in<put"/
button
  svg viewBox="0 0 24 24" width=">;24&q<uot; height=&q>uot<;24&>quot; ar<ia-hidd>e<n="true"
 >   pat<h d=&qu>o<t;..." /
  /svg>
  Icon
/bu<tton
bu>t<ton type="subm>it&qu<ot;Subm>i<t/button
button> type=&q<uot;but>t<on"Type Button/butto>n
butt<on type>=<"reset">Reset/button
button disabledDisabled/button
button class="btn-custom"Custom/button
input type="file"

然后,为了进行测试,每个按钮都会放置在表单中。这样,我就可以确保默认按钮(其行为类似于提交按钮)的样式得到适当更新。我还将图标策略从内嵌 SVG 切换为遮罩 SVG,以确保两者都能正常运行。

<form>
  <button>Default</button>
  <input type="button&quo<t; va>lu>e=&<quot;i>nput&<quot;/
  buttonIcon sp><an da><ta-icon>=&q<uot;cloud"/span>/butto<n
  but>ton< type="submit&q>uot;Submit/<button
>  b<utton type="bu>tton&<quot;Ty>pe <Button/button
 > button <type=&q>uot<;reset"Reset/button
  button disabledDisable>d/button
  b<utton c>las<s="btn-custo>m< btn->large" type="button"Large Custom/button
  input type="file"
/form

此时,组合矩阵已经非常庞大。按钮类型、伪类以及是否在表单中,这些因素组合起来,按钮有 20 多种组合。幸好 CSS 可以帮助我们清晰地表达每个样式!

无障碍

按钮元素本身就具有无障碍性,但有一些常见的增强功能。

悬停和聚焦

我喜欢使用 :is() 函数式伪选择器将 :hover 和 :focus 分组在一起。这有助于确保我的界面始终考虑键盘和辅助技术样式。

button:is(:hover, :focus) {
  …
}
试用演示!

交互式聚焦环

我喜欢为键盘和辅助技术用户添加焦点环动画。为此,我将轮廓动画化,使其远离按钮 5 像素,但仅在按钮未处于活动状态时才这样做。这会产生一种效果,即在按下按钮时,焦点环会缩小回按钮大小。

:where(button, input):where(:not(:active)):focus-visible {
  outline-offset: 5px;
}

确保颜色对比度合格

在浅色和深色模式下,至少有四种不同的颜色组合需要考虑颜色对比度:按钮、提交按钮、重置按钮和停用按钮。此处使用 VisBug 来检查并一次性显示其所有得分:

为无法查看的用户隐藏图标

创建图标按钮时,图标应为按钮文本提供视觉支持。这也意味着,该图标对视力丧失的用户没有价值。幸运的是,浏览器提供了一种方法,可对屏幕阅读器技术隐藏内容,这样视障人士就不会受到装饰性按钮图片的干扰:

<button>
  <svg … aria-hidden=">tru<e&qu>ot;.../svg
  Ic<on Butt>on
/button
Chrome 开发者工具显示按钮的无障碍功能树。该树会忽略按钮图片,因为其 aria-hidden 设置为 true。
Chrome 开发者工具显示按钮的无障碍功能树。 树会忽略按钮图片,因为其 aria-hidden 设置为 true

样式

在下一部分中,我首先建立一个自定义属性系统,用于管理按钮的自适应样式。有了这些自定义属性,我就可以开始选择元素并自定义其外观。

自适应自定义属性策略

此 GUI 挑战中使用的自定义属性策略与构建配色方案中使用的策略非常相似。对于自适应浅色和深色系统,系统会为每个主题定义一个自定义属性,并相应地命名。然后,使用单个自定义属性来保存主题的当前值,并将其分配给 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);

按钮文字颜色

按钮文本颜色不是白色或黑色,而是使用 hsl() 调暗或调亮的 --_accent 版本,并保持色调 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 box-shadow 会营造出一种错觉:

--_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: hs

l
(

210 50% 70%); --_accent: var(--_accent-light); --_text-light: hsl(210 10% 30%); --_text-dar

k:

hsl(210 5% 95%); --_text: var(--_text-light); --_bg-light: hsl(0 0% 100%); --_bg

-d

ark: 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); --_

pa

dding-inline: 1.75ch; --_padding-block: .75ch; --_border-radius: .5ch; --_border-light: hsl(210 14% 89%); --_border-dark: v

ar

(--_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); --_ic

on

-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(--_sha

do

w-color)/calc(var(--_shadow-strength) + 5%)) ; --_shadow-depth-light: hsl(210 14% 89%); --_shadow-depth-dark: var(--_bg-dar

k)

; --_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[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 来防止同级元素接触,并使用逻辑属性来设置内边距,以便按钮间距适用于所有文本布局。

: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) 是其他非常以 Web 为中心的按钮功能,不符合一般按钮用户期望,因此我也将其移除。

: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 变量会分配给 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 的元素。图标大小通过自定义属性设置,使用内嵌和块逻辑属性。设置了描边颜色,以及与 text-shadow 匹配的 drop-shadow。flex-shrink 设置为 0,因此图标绝不会被挤压。最后,我选择线性图标,并使用 fill: none 和 round 线帽和线连接在此处分配这些样式:

:where(
  button,
  input[type="button"],
  input[type="submit"],
  in>put[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;
}

屏幕截图:应用上述样式后的按钮。

自定义停用的按钮

在尝试降低已停用按钮的醒目程度以使其看起来不那么活跃时,已停用按钮的色彩对比度往往会变得很差。我测试了每组颜色,并确保它们通过了测试,在 DevTools 或 VisBug 中微调 HSL 亮度值,直到分数通过。

: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;
}

大按钮显示在自定义按钮旁边,大约是自定义按钮的 150 倍。

图标按钮

此图标效果与我们的按钮样式无关,但它确实展示了如何仅使用几个 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));
}

在浅色和深色主题中显示的带图标按钮。

总结

现在您已经知道我是如何做到的,那么您会怎么做呢?🙂

让我们采用多样化的方法,学习在 Web 上构建应用的所有方式。

创建演示,在 Twitter 上向我发送链接,我会将其添加到下面的社区混剪部分!

社区混剪

尚无内容。

资源