MDN在3月份推出了新的设计,这已经不是什么秘密了。它非常漂亮!其中有一些可爱的CSS-y宝石,让人看了很有趣。其中一个宝石是卡片组件如何处理截断的文本。
很酷,是吗?我想把它拆开来看看,但有几件事真的很吸引我去看这个方法:
- 这是一个有意截断内容的例子。我们在其他地方将其称为CSS数据丢失。虽然数据丢失通常是一件坏事,但我喜欢它在这里的使用方式,因为摘录的目的是作为完整内容的一个预告。
- 这与用 "截断 "来截断文字是不同的。
[text-overflow: ellipsis](https://css-tricks.com/almanac/properties/t/text-overflow/)截断文本,这是最近出现的一个话题,当时Eric Eggert分享了他对它的担忧。反对它的主要理由是,没有办法恢复被截断的文本--辅助技术会公布它,但视力好的用户没有办法恢复它。MDN的方法在这方面提供了更多的控制,因为截断只是视觉上的。
那么,MDN是如何做到的?就HTML而言,这里没有太多花哨的东西,只是一个带有段落的容器:
<div class="card">
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Inventore consectetur temporibus quae aliquam nobis nam accusantium, minima quam iste magnam autem neque laborum nulla esse cupiditate modi impedit sapiente vero?</p>
</div>
我们可以在一些基线样式中加入一些东西来支撑。
同样,没有太多花哨的东西。我们的目标是在例如第三行之后将内容切断。我们可以在该段上设置一个max-height ,并隐藏溢出的内容。
.card p {
max-height: calc(4rem * var(--base)); /* Set a cut-off point for the content */
overflow: hidden; /* Cut off the content */
}
哇哦,这calc() 的东西是怎么回事?请注意,我在前面设置了一个--base 变量,可以作为一个普通的乘法器使用。我用它来计算font-size 、line-height 、padding ,现在又计算了该段的max-height 。我发现用一个常数来工作更容易,特别是当我需要的尺寸确实是基于这样的比例。我注意到MDN使用了一个类似的--base-line-height 变量,可能也是为了同样的目的。
让第三行的文字淡出?这是在pargraph的:after 伪元素上的一个经典linear-gradient() ,它被钉在卡片的右下角。所以,我们可以把它设置好:
.card p:after {
content: ""; /* Needed to render the pseudo */
background-image: linear-gradient(to right, transparent, var(--background) 80%);
position: absolute;
inset-inline-end: 0; /* Logical property equivalent to `right: 0` */
}
注意我正在调用一个--background 变量,该变量被设置为与.card 本身使用的背景颜色值相同。这样一来,文字看起来就会淡化到背景中。我发现我需要调整渐变中的第二个色块,因为当渐变一直融合到100%时,文本并没有完全隐藏。我发现80% ,对我的眼睛来说是一个甜蜜点。
而且,是的,:after 需要一个height 和width 。height 是--base 变量重新发挥作用的地方,因为我们想让它按比例变成该段的line-height ,以便用:after 的高度覆盖文本:
.card p:after {
/* same as before */
height: calc(1rem * var(--base) + 1px);
width: 100%; /* relative to the .card container */
}
额外增加一个像素的高度似乎可以做到这一点,但当我偷看DevTools的时候,MDN能够在没有它的情况下完成。然后,我也没有用top (或inset-block-start )来抵消那个方向的渐变。 🤷♂️
现在,p:after 是绝对定位的,我们需要明确地在该段上声明相对定位,以保持:after 在其流程中。否则,:after 将被完全从文档流中拉出,并被缠绕在卡片之外。这就成为.card 段落的完整CSS。
.card p {
max-height: calc(4rem * var(--base)); /* Set a cut-off point for the content */
overflow: hidden; /* Cut off the content */
position: relative; /* needed for :after */
}
我们完成了,对吗?没有!没有!没有这该死的梯度似乎并不在正确的位置上。
我承认我在这个问题上动了脑筋,在MDN上启动了DevTools,看看我到底错过了什么。哦,是的,:after ,需要作为一个块元素显示。当给它添加一个红色边框时,就很清楚了。🤦♂️
.card p:after {
content: "";
background: linear-gradient(to right, transparent, var(--background) 80%);
display: block;
height: calc(1rem * var(--base) + 1px);
inset-block-end: 0;
position: absolute;
width: 100%;
}
现在都在一起了!
而且,是的,看起来听起来像VoiceOver尊重完整的文本。不过我还没有测试过其他的屏幕阅读器。
我还注意到,MDN的实现方式把 [pointer-events](https://css-tricks.com/almanac/properties/p/pointer-events/)从p:after 。这可能是一个很好的防御策略,以防止选择文本时出现奇怪的行为。我把它加了进去,至少在Safari、Firefox和Chrome中,选择文本确实感觉更顺畅了一些。