共计 5557 个字符,预计需要花费 14 分钟才能阅读完成。
在 CSS 中,存在许多数学函数,这些函数可能通过简略的计算操作来生成某些属性值,例如在古代 CSS 解决方案:CSS 数学函数一文中,咱们具体介绍了
- calc():用于计算任意长度、百分比或数值型数据,并将其作为 CSS 属性值。
- min() 和 max():用于比拟一组数值中的最大值或最小值,也能够与任意长度、百分比或数值型数据一起应用。
- clamp():用于将属性值限度在一个范畴内,反对三个参数:最小值、推荐值和最大值。
在 古代 CSS 解决方案:CSS 原生反对的三角函数 一文中,给大家介绍了从 Chrome 111 开始也逐步开始原生反对的三角函数:
- sin()
- cos()
- tan()
而本文,咱们将介绍另外一个十分有意思的数学函数 – round()。
何为 round()?
简略来说,round() CSS 函数的作用就是 依据选定的舍入策略返回舍入数。
举个例子,在 JavaScript 中,咱们能够应用 Math.round()
返回一个数字四舍五入后最靠近的整数。
譬如:
x = Math.round(20.49); //20
x = Math.round(20.5); //21
x = Math.round(-20.5); //-20
x = Math.round(-20.51); //-21
当初,CSS 借助 round() 函数也有了雷同的能力:
line-height: round(2.2, 1); /* 2 */
line-height: round(14.82, 1); /* 15 */
line-height: round(5.5, 1); /* 6 */
也就是说,round(2.2, 1)
中的 2.2 四舍五入后,最初的计算值是 2。
round() 残缺语法
round() 的残缺语法规定还是比较复杂的。残缺的介绍能够看 MDN – round()。
应用它,能够完满实现相似于 JavaScript 中的如下几个办法:
- Math.ceil()
- Math.floor()
- Math.round()
- Math.trunc()
它的残缺语法规定:
<round()> = round( <rounding-strategy>?, <valueToRound> , <roundingInterval>)
能够看到,它最多能够接管 3 个参数,并且第一个参数是可选参数:
-
<rounding-strategy>
:可选参数,示意舍入策略。这可能是以下值之一:up
: 相当于 JavaScript Math.ceil() 办法,将 valueToRound 向上舍入到 roundingInterval 最靠近的整数倍。这相当于 JavaScript Math.ceil() 办法。down
:将 valueToRound 向下舍入为 roundingInterval 最靠近的整数倍。这相当于 JavaScript Math.floor() 办法。nearest
:将 valueToRound 舍入为 roundingInterval 的最靠近的整数倍,该倍数能够高于或低于该值。如果 valueToRound 是上方和下方舍入指标之间的一半,则会向上舍入。相当于 JavaScript Math.round()。to-zero
:将 valueToRound 舍入为 roundingInterval 靠近 / 靠近零的最靠近整数倍。这相当于 JavaScript Math.trunc() 办法。
<valueToRound>
:须要被四舍五入的值。必须是<number>
、<dimension>
或<percentage>
,或者解析为这些值之一的数学表达式。<roundingInterval>
:舍入的距离规定。这是一个<number>
、<dimension>
或<percentage>
,或者解析为这些值之一的数学表达式。
基于此,举几个例子:
<div class="box-1"></div>
<div class="box-2"></div>
<div class="box-3"></div>
<div class="box-4"></div>
<div class="box-5"></div>
:root {--rounding-interval: 25px;}
div {
width: 100px;
background: rgba(255, 100, 0, .8);
}
div.box-1 {height: round(nearest, 110px, var(--rounding-interval)); /* 最终计算值:100px */
}
div.box-2 {height: round(up, 110px, var(--rounding-interval)); /* 最终计算值:125px */
}
div.box-3 {height: round(down, 120px, var(--rounding-interval)); /* 最终计算值:100px */
}
div.box-4 {height: round(to-zero, 120px, var(--rounding-interval)); /* 最终计算值:100px */
}
div.box-5 {height: round(120px, var(--rounding-interval)); /* 最终计算值:125px */
}
后果如下:
<img width=”603″ alt=”image” src=”https://github.com/chokcoco/iCSS/assets/8554143/4c594a70-3719-4158-842a-88befc9f40f0″>
图中背景一个格子的大小是
25px
残缺的 DEMO 能够看这里 CodePen Demo – CSS Math Function Round() Demo
round 能解决什么问题?
OK,铺垫了那么久,咱们上面进入实战环节。
那么,round()
函数在 CSS 中有什么具体的作用吗?能利用到什么中央?
解决基于 transform 的含糊问题
在之前的 疑难杂症:使用 transform 导致文本含糊的景象探索 这篇文章中,咱们介绍了一种基于 transform 的含糊问题。
咱们来回顾一下问题景象:
在咱们的页面中,常常会呈现这样的问题,一块区域内的文本或者边框,在展现的时候,变得特地的含糊,如下(数据通过脱敏解决):
失常而言,应该是这样的:
emmm,可能大图不是很显著,咱们取一细节比照,就十分直观了:
那么?什么时候会触发这种问题呢?在 Google 上,其实咱们能搜到十分多相似的案例,总结而言:
- 当文本元素的某个先人容器存在
transform: translate()
或者transform: scale()
等transform
操作时,容易呈现这种问题
当然,这只是必要条件,不是充分条件。持续深刻探索,会发现,必须还得同时满足一些其它条件:
- 元素作用了
transform: translate()
或者transform: scale()
后的计算值产生了非整数
譬如,上述案例触发的 CSS 代码如下:
.container {
position: absolute;
width: 1104px;
height: 475px;
top: 50%;
transform: translateY(-50%);
// ...
}
因为元素的高度为 475px
,translateY(-50%)
等于 237.5px
,非整数,才导致了外部的字体含糊。
然而,须要留神的是,并非所有产生的非整数都会导致了外部的字体含糊。
这里有个简略的示意:
还是上述的例子,当高度从 477px
始终调整到 469px
的过程中,只有 477px
和 475px
导致了含糊,而 473, 471, 469
则没有。所以,这也只是引发含糊的一个必要条件。
- 文本内容是否含糊还与屏幕无关,高清屏(dpr > 2)下不容易触发,更多产生在一般屏幕下(dpr = 1)
在我实测的过程中还发现,这个景象根本只会产生在 dpr 为 1 的一般屏幕下。
相似于 MAC 的高清屏幕则不太会触发这个问题。
dpr = 物理像素 / 设施独立像素,示意设施像素比。这个与咱们通常说的视网膜屏(多倍屏,Retina 屏)无关。设施像素比形容的是未缩放状态下,物理像素和设施独立像素的初始比例关系。
- 并非所有浏览器都是这个体现,根本产生在 chromium 内核。
那么,为何会产生这种景象?针对这个问题,没有找到特地官网的答复,广泛的认为是因为:
因为浏览器将图层拆分到 GPU 以进行 3D 转换,而非整数的像素偏移,使得 Chrome 在字体渲染的时候,不是那么的准确。
对于这个问题,感兴趣的能够再看看这两个探讨:
- Chromium Bugs — Issue 521364: Transformed text at fractional offsets is very blurry.
- Serious bug: Slick Slider turns off subpixel font rendering on the entire site in Chrome #2275
应用 round() 函数解决含糊问题
在之前,下面的这个基于 transform 的问题根本是无解的,想要不含糊,就须要替换掉 transfrom
办法。
而在有了 round()
后,咱们能够通过 round()
函数,保障作用了 transform: translate()
或者 transform: scale()
后的计算值肯定是正整数,从而防止含糊问题。
譬如,本来的 CSS 如下:
.container {
width: 50vw;
height: 50vh;
transform: translate(-50%, -50%);
}
此时,transform: translate()
的理论最终计算值是会呈现小数的。因而,咱们能够应用 round()
函数进行取整:
.container {
width: 50vw;
height: 50vh;
transform: translate(round(-50%, 1px), round(-50%, 1px));
}
咱们能够应用如下 JavaScript 代码,打印出 transform 实时的计算值。
window.addEventListener("resize", () => {const transform = getComputedStyle(document.querySelectorAll("div")[0]).transform;
console.log("transform:", transform);
});
如果应用 transform: translate(-50%, -50%)
resize 整个页面,能够看到如下打印值:
能够看到,此时,transform: matrix(1, 0, 0, 1, -50.5, -106.75)
的中的后两位,其实就是 transform: translate(-50.5px, 106.75px)
,是存在小数值的。
而应用了 transform: translate(round(-50%, 1px), round(-50%, 1px))
后,将不会再呈现小数值:
残缺的代码,你能够戳这里试一试:CodePen Demo — round() Demo
借由 round()
函数,咱们胜利的解决了始终以来,Chrome 中十分辣手的一个含糊问题!
应用 round() 模仿步骤缓动动画
round()
还有一个乏味用法。咱们能够应用 round()
实现相似于 CSS Animation 中的 steps()
步骤动画的成果。
咱们来看这么一个 DEMO:
<div></div>
@property --angle {
syntax: '<angle>';
inherits: false;
initial-value: 0deg;
}
div {
width: 200px;
height: 200px;
border-radius: 50%;
background: conic-gradient(#fc0, #fc0 15deg, transparent 15deg, transparent 30deg);
transform: rotate(var(--angle));
animation: propertyRotate 2s infinite linear;
}
@keyframes propertyRotate {
100% {--angle: 360deg;}
}
这里,咱们实现了这么一个动画成果:
咱们能够利用 round()
,把一个连贯动画,拆解成步骤动画:
div {
// ...
// transform: rotate(var(--angle));
transform: rotate(round(var(--angle), 30deg));
}
下面,咱们应用 transform: rotate(round(var(--angle), 30deg))
替换了 transform: rotate(var(--angle))
。
而 round(var(--angle), 30deg)
保障了其取值只能是 30deg 的倍数或者 0deg。因而,咱们能够失去和应用 stpes()
步骤动画一样的成果:
下面应用了 round()
的动画,和如下的动画成果是统一的:
div {transform: rotate(round(var(--angle), 30deg));
}
// 等同于
div {transform: rotate(var(--angle));
animation: propertyRotate 2s infinite steps(12);
}
因而,应用 round()
,咱们也能够轻松的实现相似如下的 Loading 动画成果:
残缺的代码,你能够戳这里进行理解:CodePen Demo — CSS Math Function Round() Animation Demo
最初
好了,本文到此结束,心愿本文对你有所帮忙 :)
更多精彩 CSS 技术文章汇总在我的 Github — iCSS,继续更新,欢送点个 star 订阅珍藏。
如果还有什么疑难或者倡议,能够多多交换,原创文章,文笔无限,满腹经纶,文中若有不正之处,万望告知。