16

Polyfill吊炸天的CSS attr()新语法

 3 years ago
source link: https://www.zhangxinxu.com/wordpress/2020/10/css-attr-polyfill/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

byzhangxinxu from https://www.zhangxinxu.com/wordpress/?p=9535

本文欢迎分享与聚合,全文转载就不必了,尊重版权,圈子就这么大,若急用可以联系授权。

eAfEjie.jpg!mobile

一、CSS attr()指定值类型的新语法简介

传统的 attr() 语法只能让HTML属性作为字符串使用,且只能使用在伪元素中,例如:

<span data-title="提示">按钮</span>
span:hover::after {
    content: attr(data-title);
}

但是全新的 attr() 语法那可就完全不得了了,可以让HTML属性值转换成任意的CSS数据类型。

例如如下所示的HTML和CSS语句:

<button bgcolor="skyblue" radius="4">按钮</button>
<button bgcolor="#00000040" radius="1rem">按钮</button>
<button bgcolor="red" radius="50%">按钮</button>
<button bgcolor="orange" radius="100% / 50%" title="by zhangxinxu(.com)">按钮</button>
button {
    background-color: attr(bgcolor color);
    border-radius: attr(radius px, 4px);
}

也就是几个按钮的样式使用了新的 attr() 语法进行设置,平常的按钮颜色、圆角都是在CSS中设定好的,这个例子中则不一样,颜色和圆角全部都是外部的HTML属性控制的。

理论上,上面的代码会有如下图所示的效果。

qErYraZ.png!mobile

可以看出,如果浏览器支持了 attr() 函数的值类型新语法,那么我们日常的组件开发就会迎来巨大的颠覆,许多组件的接口可以直接交给CSS完成,以及我们的开发会更灵活,可以节省大量的CSS代码和书写CSS的时间,例如:

[ml] { margin-left: attr(ml px, 0); }
[mt] { margin-top: attr(ml px, 0); }
[mr] { margin-right: attr(mr px, 0); }
[mb] { margin-bottom: attr(mb px, 0); }
[pl] { padding-left: attr(pl px, 0); }
[pt] { padding-top: attr(pt px, 0); }
[pr] { padding-right: attr(pr px, 0); }
[pb] { padding-bottom: attr(pb px, 0); }

那么元素的 marginpadding 设置就不需要专门写在CSS样式中,直接在HTML中设置即可,支持任意的 marginpadding 大小,例如:

<div mt="10">上间距10px</div>

喔噢,看上去很厉害哦,HTML和CSS会一下子变得非常灵活与高效。

只可惜, attr() 函数的新语法目前没有任何浏览器支持,而且在我看来很长一段时间浏览器都不会支持,安全、性能等方面的影响太深远了。

bmyQB3q.png!mobile

不死心的我就琢磨着有没有什么办法让浏览器可以支持CSS attr() 函数的这个新语法呢?

然后想到了可以借助CSS变量作为信使实现Polyfill实现。

二、Polyfill attr()新语法

CSS变量有一个特性,那就是CSS自定义属性值支持各种表达式和函数值,哪怕这个表达式是不知所云的东西。

例如随便自定义一个名叫 keyword() 的函数,然后使用如下所示的CSS调用:

body {
    --keyword: keyword(red, 50%); 合法
    color: var(--keyword);
}

结果浏览器认为语法是合法的(比方说下图语句没有出现删除线,说明语句是合法的):

BFBrQfB.png!mobile

//zxx: 如果你看到这段文字,说明你现在访问是体验糟糕的垃圾盗版网站,你可以访问原文获得很好的体验:https://www.zhangxinxu.com/wordpress/?p=9535(作者张鑫旭)

于是我们就可以利用CSS变量的这个特性Polyfill attr() 函数,原理如下。

实现原理

  1. CSS自定义属性作为信使传递 attr() 函数,保证语法的合法性,例如:
    button {
        --attr-bg: attr(bgcolor color);
        background-color: var(--attr-bg);
    }
  2. 获取⻚⾯所有的包含 attr() 函数的⾃定义属性;
  3. 遍历并观察所有DOM,如果设置了对应的⾃定义属性,将 attr() 语法转换成浏览器识别的常规自定义属性语法。

基于上述原理,我写了个JavaScript脚本,大家只需要在页面中引入下面这段HTML代码,就可以畅快自如地使用 attr() 函数的新语法了。

如何使用

页面头部引入下面下面这个JS文件。

<script src="./css-attr.js"></script>

css-attr.js这个JS文件下载可以访问这里:css-attr.js

然后正常使用CSS变量来实现 attr() 效果即可,例如——

Polyfill测试

假设已经引入了css-attr.js,然后页面中有如下所示的HTML和CSS代码:

<button bgcolor="skyblue" radius="4">按钮</button>
<button bgcolor="#00000040" radius="1rem">按钮</button>
<button bgcolor="red" radius="50%">按钮</button>
<button bgcolor="orange" radius="100% / 50%">按钮</button>
button {
    border: 0;
    padding: .5em 1em;
}
button {
    --attr-bg: attr(bgcolor color);
    background-color: var(--attr-bg);
    --attr-radius: attr(radius px, 4px);
    border-radius: var(--attr-radius);
}

结果就有如下图所示的效果,按钮表现出了符合预期的效果。

mYfyee7.png!mobile

同时,如果我们手动修改按钮元素的 bgcolorradius 属性值,按钮的样式也会同步变化,眼见为实,您可以狠狠地点击这里: attr() polyfill后的按钮demo

实际开发中,按钮元素往往需要一个默认的主样式,此时可以通过属性选择器进行区分,例如:

button {
    color: #fff;
    background-color: deepskyblue;
}
button[bgcolor] {
    --attr-bg: attr(bgcolor color);
    background-color: var(--attr-bg);
}
button[radius] {
    --attr-radius: attr(radius px, 4px);
    border-radius: var(--attr-radius);
}

这样自定义的HTML属性无论设置还是不设置都不会影响按钮的正常显示了。

其他

然后这里还有个测试页面,风格粗犷的那种,您可以狠狠地点击这里: CSS attr() polyfill测试demo

点击按钮会修改HTML属性,大家可以看到样式同步变化了,如下图所示:

VJR73uy.png!mobile

三、结束语

CSS var() 函数的这种任意表达式特性还适用于CSS自定义语法支持的实现上,关于这个,我会下一篇文章专门介绍,敬请期待。

以上就是自己研究出来的一点小东西,旨在抛砖引玉,欢迎交流!

另外,Polyfill实现的attr()语法比原生的语法要更强大,因此支持复合的HTML属性值,例如:

<div m="10px 20px 30px 40px">上间距10px</div>
[m] {
    --m: attr(m);
    margin: var(--m);
}

可以同时指定多个分享的margin属性。

然后兼容性这块,凡是支持CSS变量的浏览器都支持这里的 attr() 新语法。

好,就说这么多,

如果你觉得本文的内容还算有趣,欢迎分享。

UNreUf.png!mobile

本文为原创文章,欢迎分享,勿全文转载,如果实在喜欢,可收藏,永不过期,且会及时更新知识点及修正错误,阅读体验也更好。

本文地址: https://www.zhangxinxu.com/wordpress/?p=9535

(本篇完)


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK