顾名思义,重叠图将两组不同的数据可视化在一张图中。这个想法是,重叠的条形图使我们能够比较数据,例如,同比。它们对于跟踪目标的进展也很有用,比如一个条形图代表目标,另一个条形图显示当前的数量。
但它们也很美

你的想法可能和我一样,已经开始琢磨你如何去编码了。下面是我如何解决这个问题的。
CodePen嵌入回退
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 元素成为一个灵活的容器,将Y轴标签和图表在row 方向上彼此相邻:
.chart {
display: flex;
}
我们甚至不需要指定方向,因为flexbox默认为row 。让我们这样做,然后在Y轴上的标签列表中添加flexbox,因为我们知道这些标签将沿column 方向运行:
.numbers {
display: flex;
flex-direction: column;
list-style: none;
margin: 0 15px 0 0;
padding: 0;
}
CodePen嵌入回退
信不信由你,我们可以再次对条形图使用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 。我们相对定位元素,因为我们要绝对定位每个条形图,我们要确保它们留在它们的容器中。
CodePen嵌入回退
每个条形图都有一个百分比高度,与沿垂直y轴的数值相对应。你可能还记得,我们给了每个条形图一个data-percentage 属性--我们要撒上一点JavaScript,用这些值设置每个条形图的高度:
var bars = document.querySelectorAll("dd .bar");
bars.forEach((bar) => {
var height = bar.getAttribute("data-percentage");
bar.style.height = height + "%";
});
这就是我们的基本图表!
CodePen嵌入回退
我们想把这个变成我们可以看到条形图相互重叠的地方。这就是下一步!
重叠的条形图
让一个条形图与另一个条形图重叠的技巧很有趣,因为我们经常试图在CSS中防止事物在视觉上重叠。但在这种情况下,我们实际上希望这种情况发生。
这些条形图已经在重叠了;只是很难说出来。注意在HTML中,每组中的第二个.bar ,有一个额外的.overlap 类。让我们用它来区分这些条形图。你完全可以自由选择你自己的风格。我正在给.overlap 条添加一点填充物,以便它们比其他条宽。然后我使用z-index ,调整堆叠顺序,使.overlap 条位于其他条的下面。
CodePen嵌入回退
让我们添加一个图例
图例这样一个伟大的词,不是吗?充满了各种意义。在这种情况下,它不仅仅是一个漂亮的点缀,因为从视觉上看,我们在通常为一个柱子保留的空间里塞进了两个柱子。图例提供了背景,解释了每个条形代表的内容。
<figure class="legend">
<div class="type1">Estimate</div>
<div class="type2">Actual</div>
</figure>
使用<figure> ,对我来说是正确的。它们通常被用来包装图像,但规范说它们被用来 "注释插图、图表、照片、代码列表等",而我们正在处理一个图表。我们也许可以用一个无序列表来容纳这些项目,但我选择了一个非语义的<div> 。如果有人对标记这个的最佳方式有什么意见,我在评论中洗耳恭听。
再一次,造型完全取决于你。
CodePen嵌入回退
可访问性考虑
我们已经花了很多精力为我们的重叠条形图的标记和造型做决定。到目前为止,这很好,但我们绝对没有完成,因为我们还可以做更多的事情,使其成为一个更容易访问的体验。不是每个人都是视力良好的网络冲浪者,所以还有一些额外的工作要做,以在这些情况下传达内容。
具体来说,我们需要:
- 检查我们的颜色之间是否有足够的对比。
- 允许键盘用户在每个重叠的条上做标签,以及
- 确保屏幕阅读器能够显示内容。
颜色的对比度
我们需要在以下方面有足够的对比:
- 重叠的条形图
- 条形图和图表背景
- 标签文本和背景
我事先做了一点功课,在我们到目前为止所看的例子中使用的颜色,确保前景和背景之间有足够的对比,以达到WCAG AA标准。
以下是我所使用的:
- 重叠的条形图: (
#25DEAA和#696969: 3.16:1 的比例) - 条形图和图表背景 (
#696969和#111: 3.43:1 的比例) - Y轴标签文本和背景 (
#fff和#333: 12.63: 1 的比例)
条形图之间的标签
为了让键盘用户可以用Tab键选择每个单独的条,我们可以使用HTMLtabindex 属性。我们可以在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中也直接列出了栏的值。这将被公布,但我们仍然想在视觉上隐藏它。我们可以使用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布局技术和对可访问性的看法,那就更好了。