发布于 2026-01-06 1 阅读
0

无障碍设计优先:拨动开关

无障碍设计优先:拨动开关

在开始之前,我想说这篇文章的灵感来自@lkopacz的文章。

我在这里展示的很多东西都与她的设计模式相似,只是加入了一些我自己的改动,当然,最终结果是一个开关,而不是一个复选框。

我们想要创造什么?

我们的目标是制作一个受 Material Design 启发、兼容键盘交互的切换开关。我们不会使用 JavaScript,因为我认为对于这么简单的东西来说没有必要。

标记

我们将使用标准的复选框,因为它自带所有无障碍功能,无需重复造轮子。我们会用一个标签将其包裹起来,以便我们可以根据需要与文本进行交互,也可以与我们即将创建的切换按钮进行交互。

我觉得使用一个可以自定义样式的 span 元素来控制切换按钮更容易些。以下是我最终使用的代码。

<label class="md_switch">
  <input type="checkbox" />
  <span class="md_switch__toggle"></span>
  Toggle switch
</label>
Enter fullscreen mode Exit fullscreen mode

如果我们的 CSS 出现问题,这将加载一个标准的复选框,并且完全可用,这正是我们应该始终努力追求的目标。

款式

切换开关有几种状态,我们需要为每种状态设计样式。这些状态包括:

  • 默认/未选中
  • 已检查
  • 已禁用
  • 重点

默认

设置

我们先来看看标签的外观。你可能还记得,我们的标签带有一个类名.md_switch。这是一个 Material Design 项目,所以我们会使用 Open Sans 字体,你不一定要用,但我这里会用。我们希望标签是内联的,但同时又希望元素内部使用 Flexbox 布局,所以我们会将 display 属性设置为 0。inline-flex这意味着我们可以垂直对齐元素内部的所有元素,align-items: center这对我们来说很有利。我们还需要增加上下边距,因为我们的切换按钮会比标准的复选框稍大一些,我这里设置的是 5px。

@import url(http://fonts.googleapis.com/css?family=Open+Sans);

.md_switch {
  display: inline-flex;
  font-family: "Open Sans";
  align-items: center;
  margin: 5px 0;
}
Enter fullscreen mode Exit fullscreen mode

当鼠标悬停在切换按钮上时,我们希望光标显示它是可以点击的,所以让我们把光标改成指针。

.md_switch .md_switch__toggle {
  cursor: pointer;
}
Enter fullscreen mode Exit fullscreen mode

切换开关

接下来我们来制作实际的开关。像这样的开关由两部分组成:背景层和顶部的旋钮/开关。背景层自然而然地就成了开关::before,旋钮作为开关也很合理,::after所以这部分很简单。

修改前后的样式都需要包含内容值、背景颜色、边距和过渡效果。所有值都相同,所以我们将它们组合在一起,如下所示。

.md_switch .md_switch__toggle::before,
.md_switch .md_switch__toggle::after {
  content: '';
  background: #BDBDBD;
  margin: 0 3px;
  transition: all 100ms cubic-bezier(0.4, 0.0, 0.2, 1);
  display: block;
}
Enter fullscreen mode Exit fullscreen mode

你会注意到我还添加了一个显示属性,虽然从技术上讲两者都不需要它,但添加它也没有什么坏处。

我从材料设计规范中获取了三次贝塞尔曲线和时间,链接在此

现在我们来看看切换按钮的背景部分。你可以随意调整大小,但我会解释我为什么选择这些设置。

.md_switch .md_switch__toggle::before {
  height: 1.3em;
  width: 3em;
  border-radius: 0.65em;
  opacity: 0.6;
}
Enter fullscreen mode Exit fullscreen mode

我把高度设置得略高于行高,这样看起来就像填满了整行;宽度略大于高度的两倍,这样看起来既长又不会太长;圆角半径是高度的一半,使其呈药丸状;不透明度为 0.6,使其看起来比开关部分(不透明度为 1)更远。这些只是我觉得合适的数值,您可以根据自己的喜好随意更改。

最后,在这个部分,我们将开关放在顶部。我们希望它使用绝对定位,所以需要将父元素的定位设置为相对定位,.md_switch .md_switch__toggle不过父元素本身就是一个元素,所以没问题。

我们希望开关是圆形的,比背景略高一些,并且垂直居中;为了增加一些深度,我们再添加一个阴影。

.md_switch .md_switch__toggle::after {
  position: absolute;
  top: 50%;
  transform: translate(0, -50%);
  height: 1.7em;
  width: 1.7em;
  border-radius: 50%;
  box-shadow: 0 0 8px rgba(0,0,0,0.2), 0 0 2px rgba(0,0,0,0.4);
}
Enter fullscreen mode Exit fullscreen mode

我用transform这种方法是为了方便以后制作动画。

Material Design 切换默认视图

已检查

接下来的几部分就容易多了,大部分前期工作都是在默认视图下完成的。

对于选中的项,我们希望将两个位的背景颜色更改为我们想要的active颜色。

.md_switch [type=checkbox]:checked+.md_switch__toggle::before,
.md_switch [type=checkbox]:checked+.md_switch__toggle::after{
  background: #00897B;
}
Enter fullscreen mode Exit fullscreen mode

但我们还想把开关移到背景药片的另一侧。如果我们把旋钮沿着药片的整个长度移动,然后再往回移动它自身的宽度,我们应该就能紧贴右边缘了——像这样的变换calc(3em - 100%)应该可以做到。而且它确实做到了。

.md_switch [type=checkbox]:checked+.md_switch__toggle::after {
  transform: translate(calc(3em - 100%), -50%);
}
Enter fullscreen mode Exit fullscreen mode

Material Design 切换仅 HTML

已禁用

如果某个元素被禁用,我们希望以某种方式告知用户他们无法与其交互。我的做法是添加一个灰度滤镜并降低其不透明度,同时移除该元素的阴影,使其看起来更平坦。

我们还可以设置光标,not-allowed以便鼠标用户也能收到消息。

.md_switch [type=checkbox]:disabled+.md_switch__toggle {
  cursor: not-allowed;
  filter: grayscale(100%);
  opacity: 0.6;
}

.md_switch [type=checkbox]:disabled+.md_switch__toggle::after {
  box-shadow: none;
}
Enter fullscreen mode Exit fullscreen mode

Material Design 切换仅 HTML

重点

这是我们需要考虑的最终状态:当复选框获得焦点时,我们希望向用户表明他们已选中我们的元素。这段代码与@lkopacz使用的代码完全相同,因为它效果非常好。

.md_switch [type=checkbox]:focus+.md_switch__toggle {
  outline: #5d9dd5 solid 1px;
  box-shadow: 0 0 8px #5e9ed6;
}
Enter fullscreen mode Exit fullscreen mode

即将结束

我们已经实现了切换功能,而且看起来也挺美观的,但我们仍然需要隐藏原来的复选框。过去,很多人会使用 `display: none`,但这其实是个糟糕的主意,它会完全隐藏元素,并将其从标签页索引中移除,这意味着键盘用户将无法访问该元素。那么我们该怎么办呢?

有很多方法可以隐藏元素并使其保留在标签页索引中。我个人比较喜欢的方法是让它不占用任何空间,降低不透明度并关闭指针事件,但你可以使用任何你喜欢的方法。

.md_switch [type=checkbox] {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}
Enter fullscreen mode Exit fullscreen mode

欢迎在下方评论区告诉我你们会如何改进,我很期待听到大家的想法。

文章来源:https://dev.to/link2twenty/accessibility-first-toggle-switches-3obj