CSS按钮样式指南
这是我撰写的系列文章的第九篇,旨在探讨现代 CSS 解决方案如何解决我过去 13 年多前端开发工作中遇到的问题。访问ModernCSS.dev查看整个系列文章及其他资源。
本指南将探讨如何为链接和按钮元素设计易于访问、可扩展的按钮外观。
涵盖的主题包括:
- 重置
a样式button - 显示、视觉、大小和文本样式
- 易于接受的造型考量
- 常见场景的扩展样式
哦,那个按钮(或者说是链接?)。从鼠标悬停延迟等待第二张图片加载的时代,到图像精灵,再到渐变效果出现之后border-radius,我一直都在与按钮作斗争,直到box-shadow它出现,我才如释重负。
但是……我们对按钮样式的重视程度过高,以至于完全忘记了按钮的真正含义,更不用说一个易于访问的按钮(或链接)了。
等等!快去读读这篇精彩的文章:《现代 Web 应用中的链接与按钮》,了解何时应该使用链接,何时应该使用
a按钮。button
我们将探讨为按钮a和按钮创建视觉外观所需的属性button,以及确保按钮的创建和使用具有可访问性所需的其他细节。
重置默认样式
这是我们的基准样式——Chrome 中渲染的原生浏览器样式,目前唯一的更改是链接继承了 body 元素上设置的自定义字体,我还提高了字体大小font-size:
如果你在家跟着做,HTML代码是:
<a href="javascript:;">Button Link</a>
<button type="button">Real Button</button>
我使用javascript:;字符串作为href值,这样我们就可以在不触发导航的情况下测试状态。同样地,由于此按钮并非用于表单提交,因此需要明确指定类型,button以防止触发 GET 请求和页面重新加载。
重置样式
注意:通常我会对 CodePen 应用Normalize重置,但本课我们将从零开始,学习如何重置按钮和链接。使用Normalize或其他常用的重置方法可以自动完成其中一些操作。
首先,我们将把 class 添加button到链接和按钮上,以强调本课中样式应用的位置。
<a href="javascript:;" class="button">Button Link</a>
<button type="button" class="button">Real Button</button>
box-sizing
请确保您的样式包含以下重置 - 如果您不希望它全局生效(您应该这样做),您可以将其作用域限定在我们的按钮类中。
* {
box-sizing: border-box;
}
简而言之,这条规则可以防止边框和内边距等元素扩大预期的元素大小(例如,25% 的宽度仍然是 25%,而不是 25% + 边框宽度 + 内边距)。
a
对于该链接,我们只需要进行一次重置:
a.button {
text-decoration: none;
}
这会直接去掉下划线。
button
接下来,我们还需要遵守以下几条规则才能重置按钮:
button.button {
border: none;
background-color: transparent;
font-family: inherit;
padding: 0;
cursor: pointer;
@media screen and (-ms-high-contrast: active) {
border: 2px solid currentcolor;
}
}
不同浏览器之间的数值也存在一些差异display,但我们很快会将其更改为统一的选项。
重置样式后,我们现在得到这样的外观:
感谢@overflowhidden提供解决方案,确保在启用 Windows 高对比度模式的情况下,用户能够看到按钮边框。
显示样式
我发现,在很多情况下,效果最好的方法是,display: inline-flex它能提供 flexbox 的内容对齐功能,但又位于 DOM 的inline-block行为中。
a.button,
button.button {
display: inline-flex;
align-items: center;
justify-content: center;
}
如果您将来添加图标或设置宽度限制,弹性对齐方式会非常有用。
视觉样式
接下来,我们将应用一些标准视觉样式,您当然可以根据自己的喜好进行调整。这是最灵活的一组样式,您可以省略某些样式box-shadow和/或某些元素border-radius。
$btnColor: #3e68ff;
a.button,
button.button {
// ... existing styles
background-color: $btnColor;
color: #fff;
border-radius: 8px;
box-shadow: 0 3px 5px rgba(0, 0, 0, 0.18);
}
现在我们的链接和按钮看起来越来越像了:
按钮对比度
创建初始按钮样式时,需要考虑两个层次的对比:
- 按钮背景颜色与其显示背景颜色之比至少为 3:1
- 按钮文本与按钮背景之间至少应保持 4.5:1 的比例(对于小于 18.66 像素粗体或 24 像素的文本)或 3:1 的比例(对于大于这些尺寸的文本)。
以下是我制作的信息图,用来展示按钮颜色与其对比度之间的关系:
假设页面背景为白色,我们的按钮颜色选择符合 4.54:1 的比例要求。
试试 ButtonBuddy,它可以帮你创建易于访问的按钮颜色。我开发的这款网页应用能帮你轻松掌控按钮调色板中的所有对比度。
尺寸
我们特意省略了“视觉”类别下的一个属性,您在查看进度截图时可能没有注意到:padding。
由于padding它是其中的一部分box-model,我们将其留给了尺寸部分。
让我们先应用这些尺寸值,然后再进行讨论:
a.button,
button.button {
// ... existing styles
padding: 0.25em 0.75em;
min-width: 10ch;
min-height: 44px;
}
我们采用padding单位制em,这是一种允许填充与应用的单位成比例调整大小的偏好font-size。
接下来,我们min-width使用ch单位来设置宽度,该单位大致等于0所应用字体的字符宽度font-size。此建议旨在维护视觉节奏。设想一下,您有两个并排的按钮,一个标签较短,一个标签较长,例如“分享”和“了解更多”。如果没有设置宽度min-width,“分享”按钮的宽度会明显短于“了解更多”。
这min-height是基于确保按钮在触摸设备上的目标足够大,以满足 WCAG 2.1 2.5.5 - 目标大小的成功标准。
各种风格开始融合,但我们还没有完成:
文本样式
根据上一张进度截图,你可能会想跳过文本样式部分。
但是,看看当我们缩小视口尺寸并触发响应式行为时会发生什么:
如您所见,我们有不同的对齐方式,而且line-height也可以进行调整。
我特意跳过了重置样式中的文本对齐方式调整,所以现在我们要确保两者的文本都居中。然后我们还可以减小行高——这可能需要根据所使用的字体进行调整。
a.button,
button.button {
// ... existing styles
text-align: center;
line-height: 1.1;
}
好的,看起来很棒!
州风格
目前,用户在尝试与按钮交互时唯一获得的视觉反馈是光标变为“指针”样式。
我们需要确保三个状态都存在。
:hover
最常受到关注的是hover,所以我们就从这里开始吧。
鼠标悬停时的典型更新之一是更改背景颜色。由于我们之前的版本已经非常接近 4.5,所以我们需要加深背景颜色。
我们可以利用 Sass,使用我们$btnColor在“视觉”部分定义的变量来计算这种颜色:
a.button,
button.button {
// ... existing styles
&:hover {
background-color: scale-color($btnColor, $lightness: -20%);
}
}
这种效果可能有点突兀,但我们还有另一个现代 CSS 工具可以柔化它,它的名字也恰如其分地叫做 `setOver` transition。这个transition属性需要添加到hover规则之外,以便它同时适用于“over”和“out”两种情况。
a.button,
button.button {
// ... existing styles
transition: 220ms all ease-in-out;
// ...&:hover
}
:focus
对于键盘用户,我们需要确保状态focus能够清晰区分。
默认情况下,浏览器会对获得焦点的元素应用一种“光晕”效果。一种不好的做法是直接移除outline实现该效果的属性,而没有进行相应的替换。
我们将使用自定义的焦点状态替换原有的轮廓box-shadow。与类似outline,box-shadow它不会改变元素的整体大小,因此不会导致布局偏移。而且,由于我们已经应用了焦点状态transition,因此该自box-shadow定义焦点状态也会继承该状态,从而产生额外的醒目效果。
a.button,
button.button {
// ... existing styles
// ...&:hover
&:focus {
outline-style: solid;
outline-color: transparent;
box-shadow: 0 0 0 4px scale-color($btnColor, $lightness: -40%);
}
}
我们再次使用了该scale-color函数,这次是为了使颜色比默认颜色更深一些hover。这是因为按钮可以同时处于“开启”hover和“关闭”两种状态。focus
感谢@overflowhidden提供解决方案,确保:focus启用 Windows 高对比度模式的用户能够获得可感知的状态。
:active
最后,特别是对于“真正的按钮”,最好定义一个:active状态样式。
对于链接,此效果会在点击/轻触的“按下”瞬间短暂出现。
对于按钮来说,由于可以通过空格键触发按钮,而空格键可以无限期地按住,因此按钮的显示时间可以更长。
我们将对:active现有:hover样式进行补充:
&:hover,
&:active {
background-color: scale-color($btnColor, $lightness: -20%);
}
风格变化
关于轮廓(“幽灵”)按钮的话题我们改天再谈,但这里我们快速补充两种变体。
小按钮
我们将使用 BEM 格式创建一个button--small类来简单地缩小字体大小。由于我们将内边距设置为 0 em,因此字体大小会按比例调整。我们的样式min-height表将确保按钮保持足够大的触摸目标。
&--small {
font-size: 1.15rem;
}
屏蔽按钮
有时您可能希望block按钮内容采用行为式布局而不是内联布局,因此我们将添加width: 100%此功能以允许此选项,而不是更改display属性,因为我们仍然希望按钮内容采用弹性对齐:
&--block {
width: 100%;
}
陷阱:Flex Columns 的子元素
如果按钮是弹性列的子元素,即使没有设置类,按钮也会扩展到全宽,这可能会让您措手不及button--block。
为了应对这种情况,您可以align-self: start向基本按钮样式添加样式,或者为每个 flex/grid 对齐属性值创建实用样式:start,,center和end。








