CSS魔法!如何将任意CSS类型转换为数值?

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

在 CSS 中有各式各样的类型值例如 1rem、10vw、100cqw等等这些相对值给与了 CSS 强大的适应能力。但有时候我们还需要知道这些相对值所对应的真实值也就是px值比如在移动端我们经常会设置这样的根字号

:root{
  font-size: max(12px, min( 12px + (100vw - 320px) / 55 * 4, 20px ));
}
p{
  font-size: 2rem;
}

那么p此时的真实px值应该是多少呢

在以往我们只能通过 JS去获取但是现在仅仅凭 CSS也能做到一起了解一下吧

一、CSS 三角函数

从理论上来讲将一个长度除以1px就应该得到具体的数值相当于将这个长度以1px被分成了多少份。

2rem / 1px

但是大家可能都知道calc在进行除法运算时除数是不能带单位的。

calc(2rem / 1px) /*不合法*/

不排除浏览器以后会支持。

不过现在终于迎来了转机在 Chrome 111中CSS 新增了一系列三角函数。

  • sin()[1]正弦
  • cos()[2]余弦
  • tan()[3]正切
  • asin()[4]反正弦
  • acos()[5]反余弦
  • atan()[6]反正切
  • atan2()[7]反正切

这里我们不聊三角函数的作用只是作为一个桥梁中转一下。

关于「正切函数」这里简单回顾一下高中数学

在「直角三角形」中其中一个锐角的「对边」和「临边」的比值就是这个角的「正切值」「反正切」就是通过两条直角边反向去求出该角的「弧度值」示意如下

这些函数本身没什么特别的业界通用但有一个非常例外那就是atan2它和atan作用是一样的都是反正切函数。唯一的区别是atan2支持两个值

前端中的 atan 就是数学中的 arctan。

atan2(y, x)

例如

transform: rotate(atan2(3, 2));
/*等同于*/
transform: rotate(atan(1.5));

看似好像没啥意义直接用tan不就好了

transform: rotate(atan2(3/2));

和JS不同的是CSS 中还能「支持单位」如下

transform: rotate(atan2(1rem, 20px));
/*等同于?*/

这就不得了了如果此时的1rem是16px那么浏览器会根据1rem的真实长度和20px做对比相当于让两个带单位的长度做除法运算。

也就是说y/x的值可以得到两个CSS长度之间的真实比值而无需额外转换。

然后通过正切函数tan将括号里面的值解析出来。

tan(atan2(1rem, 20px)) /*.8*/

这一点其实在 JS 中也可以验证一下只是 CSS 可以带单位的值。

如果将后面的值设置为1px就相当于把任意长度按照1px进行切分也就得到了任意长度的px数值如下

tan(atan2(1rem, 1px)) /*16*/

有了这个不带单位的绝对值我们就可以做很多事情了下面举几个例子。

二、CSS 获取当前字号

回到文章开头的问题如何通过 CSS 获取当前字号呢

根据上一节的原理只要通过tan 和 atan2就可以将任意长度转换为数值了。

:root{
  font-size: max(12px, min( 12px + (100vw - 320px) / 55 * 4, 20px ));
}
body{
  --px-font: tan(atan2(1rem, 1px));
}

这样--px-font就得到了真实的px数值。

然后我们还可以借助 CSS计数器将这个数字渲染到页面。

body::after{
  counter-reset: font var(--px-font);
  content: "当前根字号" counter(font);
}

结果...效果如下

好像不太对貌似是浏览器的 bug这种情况下忽略了tan(atan2(1rem, 1px))中的1rem单位。

要修复这个问题其实很容易需要通过@property定义一个CSS变量类型为长度然后将需要计算的值赋给这个变量如下

@property --font {
  syntax: "<length>";
  initial-value: 1px;
  inherits: false;
}
:root{
  font-size: max(12px, min( 12px + (100vw - 320px) / 55 * 4, 20px ));
}
body::after{
  --font: 1rem; /*定义好的CSS变量*/
  --px-font: tan(atan2(var(--font), 1px));
  counter-reset: font var(--px-font);
  content: "当前根字号" counter(font);
}

这样就正常了在改变屏幕尺寸时会自动渲染出当前字号。

你也可以访问在线链接

  • CSS font-size (juejin.cn)[8]
  • CSS font-size (codepen.io)[9]

三、实时显示容器尺寸

CSS容器查询中出现了几个新的尺寸单位。这里只介绍下面两种。

关于容器查询可以参考这篇文章介绍2022最期待且已正式支持的CSS container容器查询 « 张鑫旭-鑫空间-鑫生活 (zhangxinxu.com)本文并不涉及具体容器查询语句。

  • 「cqw」 容器查询宽度Container Query Width占比。「1cqw等于容器宽度的1%」。假设容器宽度是1000px则此时1cqw对应的计算值就是10px。
  • 「cqh」 容器查询高度Container Query Height占比。「1cqh等于容器高度的1%」。

利用前面的技巧可以将cqw、cqh这些单位转换为具体的px值。

假设有这样一个容器。

.box{
  display: grid;
  place-content: center;
  width: 200px;
  height: 200px;
  background-color: #fff;
}

为了使容器尺寸生效必须声明容器类型。

.box{
  /**/
  container-type: size;
}

然后用同样的技巧在伪元素中通过计数器将宽高渲染出来。

.box::before{
  --w: 100cqw;
  --h: 100cqh;
  --px-width: tan(atan2(var(--w), 1px));
  --px-height: tan(atan2(var(--h), 1px));
  counter-reset: w var(--px-width) h var(--px-height);
  content: counter(w) " x " counter(h);
}

别忘了修复 bug。

@property --w {
  syntax: "<length>";
  initial-value: 100px;
  inherits: false;
}
@property --h {
  syntax: "<length>";
  initial-value: 100px;
  inherits: false;
}

效果如下完全没有任何 JS。

你也可以访问在线链接

  • CSS resize (juejin.cn)[10]
  • CSS resize (codepen.io)[11]

四、自适应文本的头像

下面看一个自适应文本的头像当文本较多时会自动缩放让文本可以完整展示如下

原理其实是通过容器尺寸的映射关系来动态设置文本大小关键实现如下

.avator-container span {
  font-size: calc( 24px - 10cqw );
}

但是通过文字大小来缩放有一个限制在PC上一般会有最小字号限制通常是12号所以更好的方式应该是通过scale来实现。

现在我们可以通过上面的技巧将容器尺寸转换成scale能够识别的数值通过文本宽度和容器尺寸的比值来确实缩放比例关键实现如下

.avator-container span {
  --w: 100cqw;
  --scale: tan(atan2(30px, var(--w)));
  transform: scale(var(--scale));
}

这样就得到了完全自适应尺寸的文本头像了。

完整代码可以访问在线链接

  • CSS auto text avator (juejin.cn)[12]
  • CSS avator auto scale (codepen.io)[13]

五、总结一下

以上就是本文的全部内容了介绍了一个非常巧妙并且有用的 CSS 小技巧下面总结一下

  • CSS 有很多类型的尺寸这些尺寸给与了 CSS 强大的适应能力。
  • 从理论上讲将一个长度除以 1px 就可以得到具体的数值但是calc不支持。
  • CSS 反正切函数 atan2(y,x) 支持两个参数并且还支持带CSS单位。
  • 通过 tan(atan2(y,x))可以得到y/x的比值如果x是1px可以得到y的实际px值。
  • 利用这个技巧可以将任意类型值转换为数值。
  • 纯数值可以在各个地方都可以使用了比如scale(var(--n))如果需要 px直接calc(var(--n) * 1px )。

参考资料

[1]sin() https://developer.mozilla.org/zh-CN/docs/Web/CSS/sin。

[2]cos() https://developer.mozilla.org/zh-CN/docs/Web/CSS/cos。

[3]tan() https://developer.mozilla.org/zh-CN/docs/Web/CSS/tan。

[4]asin() https://developer.mozilla.org/zh-CN/docs/Web/CSS/asin。

[5]acos() https://developer.mozilla.org/zh-CN/docs/Web/CSS/acos。

[6]atan() https://developer.mozilla.org/zh-CN/docs/Web/CSS/atan。

[7]atan2() https://developer.mozilla.org/zh-CN/docs/Web/CSS/atan2。

[8]CSS font-size (juejin.cn) https://code.juejin.cn/pen/7289041195483791416。

[9]CSS font-size (codepen.io) https://codepen.io/xboxyan/pen/XWoObZX。

[10]CSS resize (juejin.cn) https://code.juejin.cn/pen/7289046442864279591。

[11]CSS resize (codepen.io) https://codepen.io/xboxyan/pen/MWZLYZz。

[12]CSS auto text avator (juejin.cn) https://code.juejin.cn/pen/7289095309752270906。

[13]CSS avator auto scale (codepen.io) https://codepen.io/xboxyan/pen/qBLLexW。

来源前端侦探

最后推荐一款应用开发神器

扯个嗓子关于目前低代码在技术领域很活跃

低代码是什么一组数字技术工具平台能基于图形化拖拽、参数化配置等更为高效的方式实现快速构建、数据编排、连接生态、中台服务等。通过少量代码或不用代码实现数字化转型中的场景应用创新。它能缓解甚至解决庞大的市场需求与传统的开发生产力引发的供需关系矛盾问题是数字化转型过程中降本增效趋势下的产物。

这边介绍一款好用的低代码平台——JNPF快速开发平台。近年在市场表现和产品竞争力方面表现较为突出采的是最新主流前后分离框架SpringBoot+Mybatis-plus+Ant-Design+Vue3。代码生成器依赖性低灵活的扩展能力可灵活实现二次开发。

以JNPF为代表的企业级低代码平台为了支撑更高技术要求的应用开发从数据库建模、Web API构建到页面设计与传统软件开发几乎没有差异只是通过低代码可视化模式减少了构建“增删改查”功能的重复劳动还没有了解过低代码的伙伴可以尝试了解一下。

应用https://www.jnpfsoft.com/?csdn

有了它开发人员在开发过程中就可以轻松上手充分利用传统开发模式下积累的经验。所以低代码平台对于程序员来说有着很大帮助。

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: CSS