容器查询 cqw 和 CSS 数学函数 max
到今天,我们重新审视这个问题。看看到今天,我们可以如何更加简单便捷的解决这个问题!
首先,我们的问题其实可以抽象成:
- 判断文本宽度与容器宽度的大小差异,文本宽度是否大于容器宽度
- 如果超出,则设置来回位移动画,位移的幅度为容器宽度与文本宽度的差值
那么,我们一步一步来。
假设我们的 HTML 结构如下:
html
<div class="marquee">
<span>Lorem ipsum dolor sit amet elit. Animi, aliquid.<span>
</div>
其中,div 为容器,span 为文本内容。同时,我们利用容器查询,设置父容器 marquee
为容器查询的容器,并且将基于容器的inline-size
维度。
css
.marquee {
white-space: nowrap;
container-type: inline-size;
}
继续,我们如何能够在 span 中得知,当前 span 的内容长度与父容器宽度谁比较大呢?
在之前,这是很难办到的,但是现在,我们有了 容器查询 后,可以靠容器查询单位 cqw 完成。
首先,什么是容器查询?容器查询它给予了 CSS,在不改变浏览器视口宽度的前提下,只是根据容器的宽度变化,对布局做成调整的能力。
容器查询带来了很多新的单位,其中有:
- cqw 容器查询宽度(Container Query Width)占比。1cqw 等于容器宽度的 1%。假设容器宽度是 1000px,则此时 1cqw 对应的计算值就是 10px。
- cqh 容器查询高度(Container Query Height)占比。1cqh 等于容器高度的 1%。
- cqi 表示容器查询内联方向尺寸(Container Query Inline-Size)占比。这个是逻辑属性单位,默认情况下等同于 cqw
- cqb 容器查询块级方向尺寸(Container Query Block-Size)占比。同上,默认情况下等同于 cqh
- cqmin 容器查询较小尺寸的(Container Query Min)占比。取 cqw 和 cqh 中较小的一个
- cqmax 表示容器查询较大尺寸的(Container Query Min)占比。取 cqw 和 cqh 中较大的一个
本文,我们会运用到其中的 cqw,1cqw 等于容器宽度的 1%。那么,当前容器的宽度,其实就是 100 cqw。
那么:
width: 100%
,对于 span 行内元素而言,其文本长度就是其整个的宽度,100% 代表的就是文本内容的长度width: 100cqw
表示的是设置了容器查询的.marquee
的宽度(也就是父容器的宽度)
OK,有了 100%
和 100cqw
怎么比较他们谁大谁小呢?其实我们的关键不是谁大谁小,而是:
- 如果当前容器的宽度(也就是文本宽度)大于父容器宽度,需要得到一个动画位置值
- 如果当前容器的宽度(也就是文本宽度)小于父容器宽度,无需动画,也就是动画位移值为 0
那么,我们的核心就变成了,0 与两个宽度差值的比较。刚好,CSS 中提供了比较大小数学函数 max()
和 min()
。
铺垫了这么久,最终,我们得到最为核心的一行代码:
css
max(100% - 100cqw, 0px)
当然,换一种思维,使用 min()
也是可以的:
css
min(100cqw - 100%, 0px)
如果 span 内容长度,大于容器宽度,也就是 100% - 100cqw
大于 0px
,那么其实也就得到了跑马灯效果应该位移的距离。
我们顺便也就将整个效果的代码写完了,完整的代码:
scss
.marquee {
overflow: hidden;
white-space: nowrap;
width: 200px;
resize: horizontal;
container-type: inline-size;
}
.marquee span {
animation: marquee 3s linear infinite both alternate;
}
@keyframes marquee {
to {
transform: translateX(min(100cqw - 100%, 0px));
}
}
效果如下:
这样,到今天,我们可以轻易的实现:
- 文本内容不超过容器宽度,正常展示
- 文本内容超过容器的情况,内容可以进行跑马灯来回滚动展示
也就是如下的效果:
当然,硬要说的话,本方案还是存在一个缺陷,就是动画的时长是固定的,没法根据内容的长短响应式的进行适配。可能更适合文本内容相差不大的场景使用。