likes
comments
collection
share

全新 CSS 数学:pow()、sqrt() 和指数朋友

作者站长头像
站长
· 阅读数 2

大家好,这里是大家的林语冰。坚持阅读,自律打卡,每天一次,进步一点

免责声明

本文属于是语冰的直男翻译了属于是,略有删改,仅供粉丝参考。英文原味版请传送 The New CSS Math: pow(), sqrt(), and exponential friends

本期共享的是 —— CSS 添加了一大坨新型的数学函数,用来补充旧版功能(比如 calc())。它们最终都表示一个数值,但它们工作方式的细微差别并非一目了然。截至 2024 年 2 月,这些 CSS 函数可以在最新的 Edge、Chrome、Safari 和 Firefox 浏览器中使用。

pow() 的基本原理

数学中的幂运算(power)允许我们指定一个数字与其自身相乘的次数。

现在 CSS 也可以,pow() 函数采用两个参数:我们的初始数字和要应用的指数值。

line-height: pow(3, 1); /* 3 */
line-height: pow(3, 2); /* 9 */
line-height: pow(3, 3); /* 27 */

这对应 JS 由来已久的 Math.pow() 提供的功能。

console.log(Math.pow(3, 1)) // 3 ** 1= 3
console.log(Math.pow(3, 2)) // 3 ** 2 = 9
console.log(Math.pow(3, 3)) // 3 ** 3 = 27

与一大坨其他全新 CSS 数学函数不同,pow() 能且仅能支持原始数字。换而言之,我们无法在函数内部应用单位,为了获取单位,我们需要将 pow()calc() 结合使用。

font-size: calc(1rem * pow(3, 2)); /* 1rem * 9 = 9rem */
rotate: calc(10deg * pow(3, 2)); /* 10deg * 9 = 90deg */

求根的基本原理

类似于 JS 的 Math.sqrt(),CSS 中现在也有 sqrt() 来求数字的平方根。Math.sqrt() 需要一个参数,与 pow() 一样,它能且仅能支持数字,不适用于长度、百分比和其他具有单位的类型。

line-height: sqrt(1); /* 1 */
line-height: sqrt(4); /* 2 */
line-height: sqrt(9); /* 3 */

如果我们想求非平方根,比如立方根等,我们仍然需要使用 pow()。如果使用分数作为指数,我们就会得到根,比如立方根的指数是 1/3

实际使用场景

与一大坨全新的数学函数一样,它们在日常工作中的使用场景并非一目了然。

在 CSS 规范中,展示了一个使用 pow() 定义字体大小和模块化比例的示例。举个栗子,这样每个标题就可以与相同的根大小相关。虽然此处并非一定需要使用 pow(),因为也可以计算值然后粘贴进去,但由于展示 pow() 时的编程意图更清晰,因此有助于维护可读性。

<html>
  <head>
    <style>
      h1,
      h2,
      h3 {
        font-size: calc(1rem * pow(1.5, var(--heading-exponent)));
      }
      h1 {
        --heading-exponent: 4;
      }
      h2 {
        --heading-exponent: 3;
      }
      h3 {
        --heading-exponent: 2;
      }
    </style>
  </head>
  <body>
    <h1>一级标题</h1>
    <h2>二级标题</h2>
    <h3>三级标题</h3>
  </body>
</html>

或者我们可以跳出思维的框架。结合 @property 和自定义属性,我们可以创建一个感觉像是有缓动的线性动画。换而言之,动画应该随着时间的推移均匀地进行,但是通过使用指数,我们的动画感觉像是开始缓慢然后加速。

我们可以使用线性计时函数将变量从 1 动画化到 10。然后我们将该变量应用为旋转或平移等某些变换的 pow() 的指数。动画会从 110 均匀分布,但变换的值会呈指数增长,从而加快产生的视觉运动。

<html>
  <head>
    <style>
      .demo {
        animation: power-of-love 10000ms infinite alternate linear;
        transform: translateX(calc(var(--exponent, 0) * 9.25vw - 45vw));
      }
      .pow {
        transform: translateX(
          calc(pow(var(--value, 2), var(--exponent, 0)) * 0.05vw - 45vw)
        );
      }
      @keyframes power-of-love {
        0% {
          --exponent: 0;
        }
        100% {
          --exponent: 11;
        }
      }
      .demo {
        margin: auto;
        font-size: calc(1rem);
        width: 30vmin;
        height: 30vmin;
        border: 1.2vmin solid hsl(343 100% 50%);
        border-right-color: hsl(173 100% 50%);
        border-bottom-color: hsl(43 100% 50%);
        border-left-color: hsl(283 100% 50%);
        background-color: hsl(343 100% 50% / 0.12);

        display: grid;
        place-items: center;
        z-index: -1;
      }
      @property --exponent {
        syntax: '<number>';
        inherits: false;
        initial-value: 1;
      }
      body {
        display: flex;
        flex-direction: column;
        min-height: 100vh;
        background: #16161c;
        color: #fbfbf8;
        font-family: system-ui, sans-serif;
      }
      * {
        box-sizing: border-box;
        margin: 0;
        padding: 0;
      }
    </style>
  </head>
  <body>
    <div class="demo">reference</div>
    <div class="demo pow">pow()</div>
    <script>
      if (
        window?.CSS?.supports('opacity: pow(2,2)') &&
        window?.CSS?.registerProperty !== undefined
      ) {
        document.documentElement.classList.add('supported')
      }
    </script>
  </body>
</html>

其他指数函数

还有其他三个与指数相关的函数需要了解。

e 作为 exp() 的幂

exp() 函数采用一个参数,表示应用于数学常数 e 的指数。所以 exp(3) 相当于 pow(e, 3),并且像 pow() 一样,它也不允许单位。这与 JS 中的 Math.exp() 类似。

log() 对数

相关地,log() 采用两个参数,第二个参数是可选的,并用来表示对数。

在 JS 中,Math.log 有且仅有一个参数,它表示作为参数传递的数字的自然对数。该对数的底是 e

CSS 为 log() 添加的第二个可选参数允许我们把基数 e 更改为新数字。

opacity: log(2); /* 基数为 e 的 log 2 = .693147 */
opacity: log(2, 10); /* 基数为 10 的log 2 = .30103 */

JS 中没有第二个参数,因此 CSS 添加了基本更改,更方便使用。CSS log(number, base) 的等价物可以在 JS 中实现为 Math.log(number) / Math.log(base)

hypot() 求平方和的平方根

虽然字数很多,但这是一个有趣的、小众的功能。

在直角三角形的几何中,我们可以通过以下过程找到斜边(与直角相对的边)的长度:

  1. 求其余两条边的平方
  2. 将这些值加在一起
  3. 对上一步的总和求平方根

因此,使用 CSS 的 hypot() 函数,以及 JS 中的 Math.hypot() 方法,我们可以传入任意数量的参数。然后,该函数将计算所有参数的平方,将它们累加在一起,并取平方根。

animation-iteration-count: hypot(2); /* 2 */
animation-iteration-count: hypot(3, 4); /* 5 = sqrt(9 + 16) = sqrt(25) */
line-height: hypot(1, 2, 3, 4); /* ~5.4772 = sqrt(1 + 4 + 9 + 16) = sqrt(30) */
line-height: hypot(-2); /* 2 */
width: hypot(30px, 40px); /* 50px = sqrt(900px + 1600px) = sqrt(2500px) */

全新 CSS 数学:pow()、sqrt() 和指数朋友

这是本文中讨论的唯一一个允许使用单位的函数,因为所有项目都属于同一类型。

本期话题是 —— 你最常用的 CSS 函数是哪一个,有什么奇技淫巧?

欢迎在本文下方群聊自由言论,文明共享。谢谢大家的点赞,掰掰~

《前端 9 点半》每日更新,坚持阅读,自律打卡,每天一次,进步一点

全新 CSS 数学:pow()、sqrt() 和指数朋友

转载自:https://juejin.cn/post/7340077302432595987
评论
请登录