顾名思义,重叠图表在一个图表中可视化两组不同的数据。 这个想法是重叠条允许我们比较数据,例如,逐年比较。 它们对于跟踪目标的进度也很有用,其中一个条形代表目标,另一个条形显示当前数量。
但他们也很漂亮!
你的想法可能和我的一样,并且已经开始弄清楚你将如何开始并编写代码。 这就是我如何解决它。
HTML
我们将从标记开始,因为这就是我们知道什么需要样式的方式。
<div class="container">
<div class="chart">
<dl class="numbers">
<dd><span>100%</span></dd>
<!-- all the way to 0% -->
</dl>
<dl class="bars">
<div>
<dt>2018</dt>
<dd>
<div class="bar" data-percentage="50"></div>
<div class="bar overlap" data-percentage="53"></div>
</dd>
</div>
<div>
<!-- more bars -->
</dl>
</div>
</div>
我们将使用描述列表(<dl>
) 因为与标准有序列表和无序列表相比,它是一种更具语义化的方法。 另一个原因是我们在每个条中都包含一个标签。 与定义列表不同,普通列表中没有标签来添加标题或描述。 简单来说,它更有意义,也更具可读性。
第一个描述列表, .numbers
, 是 y 轴。 这 .bars
是数据可视化的地方,我也制作了一个定义列表来构建 x 轴。 每个列表项包含一个 .bar
和标签作为描述词(dt)。
数据是怎么回事 属性? 该 data-percentage
用于指定条形的高度,它最终表示它在 y 轴上的值。 我们可以为每个条在 CSS 中手动设置它,但这是重复的,并且有很多额外的代码可以用几行 CSS 替换。
基本图表样式
我们正在处理很多二维方向,所以 flexbox 将成为我们的朋友,让一切都排列整齐。 我们可以使 .chart
element 一种灵活的容器,将 y 轴标签和图表并排放置在 row
方向。
.chart {
display: flex;
}
我们甚至不需要指定方向,因为 flexbox 默认为 row
. 让我们这样做,然后将 flexbox 添加到沿 y 轴的标签列表中,因为我们知道这些将在 column
方向。
.numbers {
display: flex;
flex-direction: column;
list-style: none;
margin: 0 15px 0 0;
padding: 0;
}
信不信由你,我们可以再次对条形图使用 flexbox,因为它们也运行在 row
方向。
.bars {
display: flex;
flex: auto; /* fill up the rest of the `.chart` space */
gap: 60px;
}
我已经这样设置了 .bars
自动占用剩余的空间 y-axis
.numbers
.
您可能在 HTML 中注意到它,但“条”实际上是两个条,一个重叠另一个。 我把它们包装在一个通用的 <div>
我们可以使用另一个灵活的容器来保存定义项 (<dt>
)我们用作标签和描述细节(<dd>
) 包含两个条形值:
.bars > div {
align-items: center;
display: flex;
flex-direction: column;
flex: 1;
position: relative;
}
每个条将具有相同的宽度,因此 flex: 1
. 我们在处理元素时会相对定位元素,因为我们将绝对定位每个条,并且我们希望确保它们留在容器中。
每个条形都有一个百分比高度,对应于垂直 y 轴上的值。 你可能还记得我们给每个酒吧一个 data-percentage
属性——我们将使用一些 JavaScript 来使用这些值设置每个条的高度。
var bars = document.querySelectorAll("dd .bar");
bars.forEach((bar) => {
var height = bar.getAttribute("data-percentage");
bar.style.height = height + "%";
});
这就是我们的基本图表!
我们想把它带到我们可以看到条相互重叠的地方。 接下来就是了!
重叠条
让一个条与另一个条重叠的技巧很有趣,因为我们经常试图 防止 在 CSS 中视觉上重叠的东西。 但在这种情况下,我们实际上希望这种情况发生。
条形已经重叠; 很难说。 请注意 HTML 中的第二个 .bar
在每组有一个额外的 .overlap
班级。 让我们用它来区分条形。 您可以完全自由地为此选择自己的样式。 我正在为 .overlap
条,使它们比其他条更宽。 然后我正在使用调整堆叠顺序 z-index
所以这样 .overlap
酒吧位于其他酒吧下方。
让我们添加一个图例
传说。 这么棒的词,不是吗? 充满了各种含义。 在这种情况下,这不仅仅是一个不错的触感,因为从视觉上看,我们将两个小节卡在通常为一个小节保留的空间中。 图例提供了解释每个条形代表什么的上下文。
<figure class="legend">
<div class="type1">Estimate</div>
<div class="type2">Actual</div>
</figure>
使用 <figure>
对我来说感觉正确。 它们通常用于包装图像,但规范 说 它们用于“注释插图、图表、照片、代码列表等”。 我们正在使用图表。 我们可能可以使用无序列表来保存项目,但我选择了一个没有语义的 <div>
. 如果有人对标记这一点的最佳方式有意见,我会在评论中全神贯注!
再一次,造型完全取决于你:
可访问性注意事项
我们花了很多精力来决定重叠条形图的标记和样式。 到目前为止一切都很好,但我们肯定还没有完成,因为我们可以做更多的事情来让它变得更 无障碍 经验。 并非每个人都是有视力的网络冲浪者,因此需要做一些额外的工作来传达这些上下文中的内容。
具体来说,我们需要:
- 检查我们的颜色之间是否有足够的对比,
- 允许键盘用户跳到每个重叠栏,并且
- 确保屏幕阅读器宣布内容。
颜色对比
我们需要足够的对比:
- 重叠的条
- 条形图和图表背景
- 标签文本和背景
到目前为止,我对在我们所看到的示例中使用的颜色做了一些功课,确保有足够的颜色 前景和背景之间的对比 达到 WCAG AA 合规性。
这是我正在使用的:
- 重叠条:(
#25DEAA
和#696969
: 3.16:1 比例) - 条形图和图表背景 (
#696969
和#111
: 3.43:1 比例) - Y 轴标签文本和背景 (
#fff
和#333
: 12.63:1 比例)
栏之间的标签
为此,键盘用户可以使用 制表 关键,我们可以到达 HTML tabindex
属性。 我们可以在 for-each 函数中使用以下 JavaScript 将此属性添加到每个条形图(两者)。 我们将标签索引设置为 0
:
bar.setAttribute("tabindex", 0);
我们还可以添加一些 CSS 来改善我们在选择栏时的轮廓:
.bar:focus {
outline: 1.5px solid #f1f1f1;
}
在屏幕阅读器上宣布内容
可访问性的另一个重要方面是确保屏幕阅读器可以宣布条形图及其百分比。
我们将两个不同的图表合二为一:一个显示“估计”值的图表,另一个显示“实际”值。 如果用户知道要宣布哪个酒吧,那就太好了,所以让我们用 aria-label
属性:
<div class="bar" data-percentage="50" aria-label="Estimate">50%</div>
请注意,我们在 HTML 中也直接有 bar 的值。 这将被宣布,但我们仍然希望在视觉上隐藏它。 我们可以使用 transparent
文本,但另一种方法是使用 经典 .visually-hidden
招 通过将值包装在 span
:
<div class="bar" data-percentage="50" aria-label="Estimate">
<span class="visually-hidden">50%</span>
</div>
.visually-hidden {
clip: rect(0 0 0 0);
clip-path: inset(50%);
height: 1px;
overflow: hidden;
position: absolute;
white-space: nowrap;
width: 1px;
}
当我们谈论发布内容时,我们可能会阻止读取 y 轴标签。 这并不像用户缺少信息,因为每个条的实际百分比已经可用并公布。 我们可以使用 aria-hidden
属性:
<dl class="numbers" aria-hidden="true">
<dd><span>100%</span></dd>
<dd><span>80%</span></dd>
<dd><span>60%</span></dd>
<dd><span>40%</span></dd>
<dd><span>20%</span></dd>
<dd><span>0%</span></dd>
</dl>
我也认为屏幕阅读器可以忽略图例,因为它是一种视觉辅助:
<figure class="legend" aria-hidden="true">
<div class="type1">Estimate</div>
<div class="type2">Actual</div>
</figure>
最后的演示
这是一个包装!
我们开始了,一个带有重叠条的图表! 这是比较数据的好方法,我希望你能在某些项目中找到它的用途。
我们还有其他方法可以解决这个问题吗? 当然! 我们在这里介绍的所有内容都只是引导您完成我的思考过程。 我想你们中的一些人会采取不同的方法——如果是你,请分享! 很高兴看到其他 CSS 布局技术和关于确定可访问性的观点。