假设您有五个按钮。每个按钮代表一个步骤。如果您点击第四个按钮,您将处于第 4 步(共 5 步),并且您希望显示这一点。
这种计数和显示方式可以硬编码,但这并不有趣。JavaScript 也可以完成这项工作。但是 CSS 呢?嗯。可以吗?CSS 有计数器,因此我们当然可以计算按钮的数量。但是我们如何仅计算到某个特定按钮呢?事实证明,这是可以做到的。
HTML
它不必须是按钮;它只需要是一些我们可以计数的兄弟元素。但我们将在本文中使用按钮
<div class="steps">
<button class="active">Shop</button>
<button>Cart</button>
<button>Shipping</button>
<button>Checkout</button>
<button>Thank You</button>
<div class="message"></div>
</div>
那里的空.message
div 将是我们将使用 CSS 内容输出步骤消息的地方。
CSS
诀窍是我们实际上将使用三个计数器
- 所有按钮的总数
- 当前步骤的计数
- 当前步骤之后剩余步骤的数量
.steps {
counter-reset:
currentStep 0
remainder 0
totalStep 0;
}
现在让我们真正进行计数。计算所有按钮很简单
button {
counter-increment: totalStep;
}
接下来,我们需要另一件事来计数,它也将计数按钮。我们可以使用一个伪元素,它的唯一目的是计数按钮
button::before {
content: "";
counter-increment: currentStep;
}
诀窍是停止在活动元素之后的所有元素上计算该伪元素。如果我们使用一个像这样的.active
类
button.active ~ button::before {
/* prevents currentStep from being incremented! */
counter-increment: remainder;
}
我们正在那里计算remainder
,这可能也有用,但因为我们仅递增了remainder
,这意味着我们没有计算currentStep
计数器。太棒了。
然后我们可以使用计数器输出我们的消息
message::before {
content: "Step: " counter(currentStep) " / " counter(totalStep);
}
就是这样!
那里有一点 JavaScript,所以您可以玩玩在按钮上移动活动状态,但计数和消息传递都是 CSS。
这可能很疯狂,但是您能否在此处使用“元素和`:checked`伪选择器技巧,而不是更新`active`类?也许这变得太模糊了,因为您已经在处理兄弟选择器。我的大脑疼…
谢谢。
我不明白为什么“counter-increment:currentStep;”对伪元素“before”一个接一个地起作用,而它不像“button”元素中的累积计数器那样起作用
此致
也许使用单选按钮和:checked 而不是 active 类来使其完全成为 css?我没有尝试。好技巧!
你好,Chris,
使用单选按钮而不是按钮,可以仅使用 CSS 完成此操作(无需 JS)。
我知道这是一个演示,实际上这些按钮可以是链接或切换。屏幕阅读器用户可能会使用`Tab`来导航控件,并且不会看到可见的计数器变化。但是使用
aria-current
,您可以以编程方式向他们传达当前步骤并使用它来代替类分配样式。现在,如果您的编程状态不匹配,开发人员将能够在视觉上识别出来。我当时也在想同样的事情,即 CSS 伪元素内容,无论是:before 还是:after,都只能用于装饰目的。这是一个违规行为,因为辅助技术可能无法访问使用 css 插入的内容。因此,必须添加一些想法来告知用户发生了什么。
你好,Adrian,
我们是否可以“免费获得”使用单选按钮而不是按钮?
使用不需要 ARIA 的标记是否更好(如果这些属性需要依赖于 JavaScript,则更是如此)?
@Martin,所有现代浏览器(以及 IE11 甚至追溯到 IE9)都将 CSS 生成的内容/伪内容(
::before
和::after
)公开给辅助技术。它们只是辅助功能树中的附加文本节点/叶子(叶子?) 。@Thierry,在原始示例中,
<button>
似乎旨在引导用户浏览视图。使用单选按钮引导用户浏览流程将是错误的用法,因为它们用于数据输入。选择一个单选按钮时屏幕发生变化也将违反 3.2.2 输入时 WCAG 准则。如果需要,可能值得使用
aria-pressed
升级按钮以将其变成切换按钮(我在我的评论中提到了这一点),但对于演示的上下文,普通的<button>
是可以的。我从上面分叉了我的版本并设置了
aria-pressed
;它更冗长,因此可能不适合所有用例。@Adrian
关于“引导用户浏览流程”的说法很好;我一开始没有这样看待它。