IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    时隔两年,Chrome也支持round等CSS数学函数了

    张 鑫旭发表于 2024-09-25 16:04:18
    love 0

    by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=11363 鑫空间-鑫生活
    本文欢迎分享与聚合,全文转载就不必了,尊重版权,圈子就这么大,若急用可以联系授权。

    封面占位图

    一、CSS又更强了一点

    好消息,时隔两年,原本仅Safari浏览器支持的mod()/rem()/round()现在Chrome浏览器也支持啦。

    数学函数兼容性

    mod()函数

    CSS mod()函数返回第一个参数除以第二个参数的取模结果,类似于JavaScript余数运算符(%)。

    使用示意:

    /* 数值,无单位 */
    line-height: mod(7, 2); /* 1 */
    line-height: mod(14, 5); /* 4 */
    line-height: mod(3.5, 2); /* 1.5 */
    
    /* 百分比或者带单位的尺寸 */
    margin: mod(15%, 2%); /* 1% */
    margin: mod(18px, 4px); /* 2px */
    margin: mod(19rem, 5rem); /* 4rem */
    margin: mod(29vmin, 6vmin); /* 5vmin */
    margin: mod(1000px, 29rem); /* 72px - 如果根字号是16px */
    
    /* 正负值 */
    rotate: mod(100deg, 30deg); /* 10deg */
    rotate: mod(135deg, -90deg); /* -45deg */
    rotate: mod(-70deg, 20deg); /* 10deg */
    rotate: mod(-70deg, -15deg); /* -10deg */
    
    /* 计算*/
    scale: mod(10 * 2, 1.7); /* 1.3 */
    rotate: mod(10turn, 18turn / 3); /* 4turn */
    transition-duration: mod(20s / 2, 3000ms * 2); /* 4s */

    这个CSS函数日常开发使用的机会并不大。

    rem()函数

    CSS rem()函数返回第一个参数除以第二个参数后的余数,类似于JavaScript余数运算符(%)。

    使用示意:

    /* U数值,无单位 */
    line-height: rem(21, 2); /* 1 */
    line-height: rem(14, 5); /* 4 */
    line-height: rem(5.5, 2); /* 1.5 */
    
    /* 百分比或者带单位的尺寸 */
    margin: rem(14%, 3%); /* 2% */
    margin: rem(18px, 5px); /* 3px */
    margin: rem(10rem, 6rem); /* 4rem */
    margin: rem(26vmin, 7vmin); /* 5vmin */
    margin: rem(1000px, 29rem); /* 72px - if root font-size is 16px */
    
    /* 正负值 */
    rotate: rem(200deg, 30deg); /* 20deg */
    rotate: rem(140deg, -90deg); /* 50deg */
    rotate: rem(-90deg, 20deg); /* -10deg */
    rotate: rem(-55deg, -15deg); /* -10deg */
    
    /* 计算*/
    scale: rem(10 * 2, 1.7); /* 1.3 */
    rotate: rem(10turn, 18turn / 3); /* 4turn */
    transition-duration: rem(20s / 2, 3000ms * 2); /* 4s */

    rem和mod的区别

    mod 函数生成一个为零或与除数具有相同符号的结果。
    rem 函数生成一个为零或与被除数具有相同符号的结果。

    这两个数学函数日常开发鲜有机会出场。

    但是有个数学函数是例外,那就是round()函数,这个函数的语法更加复杂,但同时也更加实用。

    二、实用必学round()函数

    很多人以为round()函数就是简单的四舍五入,其实这个函数设计得非常巧妙,通过不同的参数设置,可以实现多种取值方法,例如(以JS API示意):

    • Math.ceil()
    • Math.floor()
    • Math.round()
    • Math.trunc()

    都怎么实现的呢?看案例。

    模拟Math.ceil()取值

    Math.ceil()是向上取整,使用CSS语法表示则是:

    canvas {
      border: round(up, 1.01px, 1px) solid;
    }

    结果渲染的边框宽度则是2px,实时渲染效果如下所示:

    其中,up表示向上取整,第三个参数表示最终计算值需要可以被此数值整除,例如round(up, 2.01px, 2px)的计算值就是4px。

    canvas {
      border: round(up, 2.01px, 2px) solid;
    }

    实时渲染效果如下所示:

    模拟Math.floor()取值

    Math.floor()是向下取整,因此,下面CSS代码的边框大小就是1px。

    canvas {
      border: round(down, 1.99px, 1px) solid;
    }

    模拟Math.round()取值

    语法:

    round( nearest, <valueToRound> , <roundingInterval> )

    或者直接:

    round( <valueToRound> , <roundingInterval> )

    就是我们常说的四舍五入。

    模拟Math.trunc()取值

    语法:

    round( to-zero, <valueToRound> , <roundingInterval> )

    表示将valueToRound舍入为roundingInterval接近/接近零的最接近整数倍。

    例如:

    canvas {
      border: round(to-zero, 5.5px, 2px) solid;
    }

    边框宽度是4px,因为5.5px往0走,最靠近2px倍数的值就是4px。

    效果示意:

    而round(to-zero, 5.5px, 3px)的计算值就是3px,比5.5px小的又是3px备注的最大值就是3px。

    效果示意:

    二、round()函数的实际应用

    举两个实用案例吧。

    1. 让响应式font-size永远是整数

    移动端开发会使用rem单位和屏幕尺寸关联,例如:

    html {
      font-size: clamp(16px, calc(100% + 4 * (100vw - 375px) / 105), 20px);
    }

    此时,1rem对应的尺寸就有可能是小数。

    小数就会有什么问题,例如一些SVG图标尺寸使用rem表示,由于出现了小数,图标边缘就很可能出现缝隙。

    又或者是圆角边缘,或者box-shadow边缘出现很微小的缝隙风。

    此时,就可以使用round()函数让尺寸取整,以规避这些问题。

    使用示意:

    <ul>
      <li>HTML并不简单</li>
      <li>CSS新世界</li>
      <li>好书推荐</li>
    </ul>
    ul {
      font-size: round(1rem, 1px);
    }

    此时,<ul>列表的字号大小一定是整数。

    如果没有round四舍五入,则字号大小则就可能是小数。

    参见下图GIF动态示意(不应用round是小数18.2476px,应用round()函数则是整数18px):

    字号round取整示意

    2. 模拟animation的steps()步阶函数效果

    round()函数的最后一个参数表示取舍的最小数值单元,试想下,如果是一个0-100的动画,如果我们设置取整的单元是20,那岂不是应用round()函数后,最终的计算值只可能是0、20、40、60、80和100,不就和CSS动画中的steps()步阶函数很像了么?

    例如有个静态的loading图标:

    <img src="loading.png" class="spin" />

    实际渲染效果如下,是个静态的:

    则下面这段CSS代码就可以让此图标loading旋转效果:

    .spin {
      transform: rotate(round(calc(var(--seed) * 3.6deg), 45deg));
      animation: seed 1s linear infinite;    
    }
    @property --seed {
      syntax: "<integer>";
      inherits: false;
      initial-value: 0;
    }
    @keyframes seed {
      from { --seed: 0; }    
      to { --seed: 100; }    
    }

    眼见为实,您可以狠狠地点击这里:使用CSS round()函数模拟steps动画demo

    效果截图如下所示:

    demo动画loading效果截图

    是不是实现得非常巧妙!

    虽然steps()函数可以实现一样的效果,但是steps()的学习和理解成本要比round()函数高多了,唯一的优势就是兼容性了。

    不过这个例子也可以看出round()函数的应用潜力。

    四、结语巴拉巴拉

    目前,规范里面提及的数学函数大部分都已经支持了吧。

    首先第一批支持的是min()/max()/clamp()这些数学函数,详见“了解CSS min()/max()/clamp()数学函数”一文。

    再然后就是,sin()/cos()这些函数支持,去年开始支持的,之前也介绍过,参见“CSS sin()/cos()等数学三角函数简介与应用”一文。

    其他数学函数,如求平方根的sqrt()函数,幂指数的pow()函数,返回给定数字的幂的数学常数e的特殊指数函数exp(),返回数字对数的log()函数,则是去年底支持的,算是第3波吧。

    sqrt函数兼容性

    然后就是本文这几个数值取舍函数,属于第4批次。

    最后一波应该就是绝对值abs()函数,正负零判断的sign()的函数。

    总之很奇怪,不知道为何Chrome浏览器不一次性支持,而是分5波进行。

    好吧,就说这么多吧。

    感谢阅读,欢迎!

    凌玉灵

    本文为原创文章,欢迎分享,勿全文转载,如果实在喜欢,可收藏,永不过期,且会及时更新知识点及修正错误,阅读体验也更好。
    本文地址:https://www.zhangxinxu.com/wordpress/?p=11363

    (本篇完)



沪ICP备19023445号-2号
友情链接