CSS按钮样式指南(附代码示例)

1,667 阅读6分钟

本指南将探讨如何为链接和按钮元素设计一个可访问、可扩展的按钮外观。

涉及的主题包括:

  • 重置样式:abutton
  • 显示、视觉、尺寸和文本样式
  • 无障碍造型的考虑
  • 常见情况下的扩展样式

哦,按钮(或者它是一个链接?)从等待第二张图片加载的悬停延迟时代开始,我就一直在与按钮作斗争,通过图片精灵,然后当border-radiusbox-shadow 和梯度出现在现场时,我感到无比的欣慰。

但是......我们把按钮的样式设计得太远了,而且在某个地方,我们完全忽视了作为一个按钮的真正含义,更不用说一个无障碍的按钮(或链接)。

我们将看看在视觉上为abutton 创建一个按钮外观需要哪些属性,以及为确保它们被创建和使用的无障碍性所需要的额外细节。


重置默认样式

这是我们的基线--在Chrome中呈现的本地浏览器样式,目前唯一的变化是链接继承了主体上的自定义字体设置,而且我还将font-size

default link and button styles

如果你在家里玩的话,HTML是这样的:

<a href="javascript:;">Button Link</a>
<button type="button">Real Button</button>

我将javascript:; 字符串用于href 值,这样我们就可以在不触发导航的情况下测试状态。同样地,由于这个按钮不是用来提交表单的,它需要明确的类型button ,以防止触发获取请求和页面重载。

重置样式

注意:通常情况下,我将Normalize重置应用于CodePens,但在本课中,我们将从头开始学习对按钮和链接的重置要求。使用Normalize或其他流行的重置为你做一些这样的事情。

首先,我们将为链接和按钮添加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 值也有一些差异,但我们很快就会把它改成一个独特的选项。

有了这些重置样式,我们现在有了这样的外观。

link and button with reset styles

显示样式

我发现在许多情况下效果最好的是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);
}

现在我们的链接和按钮开始看起来更像了:

link and button with visual styles

按钮对比度

在创建初始的按钮样式时,有两个层次的对比度:

  1. 按钮的背景颜色和它所显示的背景之间至少要有3:1的对比。
  2. 按钮文本和按钮背景之间至少有4.5:1(对于小于18.66px粗体或24px的文本)或3:1(对于大于这些尺寸的文本)。

下面是我制作的一张信息图,展示了按钮的颜色与它们的对比关系:

An infographic showing a "default" button that is a midrange shade of purple with white letters next to it's "focus" state which is a darker purple. Icons and labels show that the contrast of the default purple to the page background (a light yellow) is 4.17, and contrast of the default purple to the white button text is 4.5. For the focus button, there is a 3.02 contrast between the default purple background and the focus purple background, and 13.62 between focus purple and the white button text, and 12.57 between the focus purple and the page background light yellow.

假设一个白色的页面背景,我们的按钮颜色选择以4.54:1通过。

大小

我们故意漏掉了 "视觉 "分类下的一个属性,你在看到进度截图时可能会错过。padding.

box-model由于padding ,我们把它留给了尺寸部分。

让我们应用尺寸值,然后再讨论:

a.button,
button.button {
  // ... existing styles
  padding: 0.25em 0.75em;
  min-width: 10ch;
  min-height: 44px;
}

我们使用padding ,使用em 单位,这是一个偏好,允许填充物与应用的font-size 按比例调整大小。

接下来,我们使用ch 单位来设置min-width ,该单位大致等于所应用字体的0 字符的宽度和font-size 。这个建议是一个视觉节奏的护栏。考虑一下你有两个并排的按钮,一个是短标签,一个是长标签,例如 "分享 "和 "了解更多"。如果没有min-width ,"分享 "按钮会突然比 "了解更多 "短。

min-height 是基于确保按钮在触摸设备上是一个足够大的目标,以满足WCAG 2.1的成功标准2.5.5 - 目标尺寸

样式已经开始形成,但我们还没有完成。

link and button with size styles

文本样式

基于上一张进度截图,你可能会想跳过文本样式。

但看看当我们缩小视口尺寸并触发响应行为时会发生什么。

link and button within reduced viewport

正如你所看到的,我们有不同的对齐方式,line-height ,也可以进行调整。

我故意跳过了在重置样式中修复文本对齐方式,所以我们现在要确保它在两者中都是居中的。然后,我们还可以降低行高--这可能需要根据使用的字体来调整:

a.button,
button.button {
  // ... existing styles
  text-align: center;
  line-height: 1.1;
}

好了,看起来不错

link and button with text styles

状态样式

现在,用户在试图与按钮互动时收到的唯一视觉反馈是光标变成了 "指针 "的变化。

我们需要确保有三种状态存在。

:hover#

通常得到最多关注的是hover ,所以我们将从这里开始。

悬停时的一个典型更新是改变背景颜色。由于我们相当接近于4.5,我们将想把颜色变深。

我们可以利用Sass的优势,使用我们在 "视觉 "部分定义的$btnColor 变量,为我们计算这个颜色。

a.button,
button.button {
  // ... existing styles
  &:hover {
    background-color: scale-color($btnColor, $lightness: -20%);
  }
}

这种效果有点刺眼,但我们有另一个现代的CSS工具来缓和这种情况,恰当地命名为transitiontransition 属性需要添加到hover 规则之外,以便它同时适用于 "over "和 "out"。

a.button,
button.button {
  // ... existing styles

  transition: 220ms all ease-in-out;

  // ...&:hover
}

demo of hover transition

:focus#

对于键盘用户来说,我们需要确保focus 的状态是可以清楚区分的。

默认情况下,浏览器会对获得焦点的元素应用一种 "光晕 "效果。一个不好的做法是简单地删除渲染这种效果的outline 属性,而不去替换它。

我们将用一个使用box-shadow 的自定义焦点状态来替换轮廓。像outlinebox-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 的颜色还要深一些。这是因为一个按钮可以同时处于hoverfocus 状态。

demo of link and button focus

感谢 @overflowhidden提供了一个解决方案,以确保在Windows高对比度模式下的用户可感知的:focus 状态

:active#

最后,特别是对于 "真正的按钮",最好是定义一个:active 状态的样式。

对于链接来说,这在点击/敲击的 "向下 "过程中会出现一个短暂的时间。

对于按钮来说,这可以显示更长的时间,因为按钮可以用空格键来触发,而空格键可以无限期地按住。

我们将把:active 添加到我们现有的:hover 样式中。

&:hover,
&:active {
  background-color: scale-color($btnColor, $lightness: -20%);
}

风格变化

勾勒出的("幽灵")按钮是另一个话题,但有两个变化,我们将快速添加。

小按钮

使用BEM格式,我们将创建button--small 类来简单地减少字体大小。由于我们将padding设置为em ,这将按比例调整大小。而我们的min-height ,将确保按钮仍然是一个足够大的触摸目标。

&--small {
  font-size: 1.15rem;
}

阻止按钮

有的时候,你可能确实需要block ,而不是内联,所以我们将添加width: 100% ,以允许这个选项,而不是改变display ,因为我们仍然希望在按钮内容上进行柔性对齐。

&--block {
  width: 100%;
}

陷阱:Flex列的子项

考虑到按钮是Flex列的一个子节点,当按钮扩展到全宽时,即使没有button--block

为了防止这种情况的发生,你可以在基本的按钮样式中添加align-self: start ,或者为每个flex/grid对齐的属性值创建实用样式。start,center, 和end