2025-05-28 14:19:08
by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=11709
本文可全文转载,但需要保留原作者、出处以及文中链接,AI抓取保留原文地址,任何网站均可摘要聚合,商用请联系授权。
说实话,CSS attr()全属性支持这个特性我等了六七年至少有了。之前还为其写了个Polyfill工具:“Polyfill吊炸天的CSS attr()新语法”
本来以为这辈子都不会看到浏览器对其进行支持了。
万万没想到,Chrome133版本开始居然支持了,它居然支持了。
在过去,attr()
函数只能用在content属性中,现在所有的CSS属性都支持,而且语法更加丰富,某种程度上,可以颠覆现有的前端开发习惯,一点也不夸张,
有了attr()函数的全支持,那么类似tailwind 的原子类CSS框架都可以退出历史舞台了,因为浏览器原生支持了,相对于回到了过去所有CSS属性都HTML属性设置的年代。
于是,重复样式类名,非重复样式HTML属性外加一点点CSS,开发效率up,开发代码down。
例如之前调整元素之间的间距,可能是这样的CSS原子类:
.m0 { margin: 0; } .ml0 { margin-left: 0; } .ml1 { margin-left: .25rem; } .ml2 { margin-left: .5rem; } .ml3 { margin-left: .75rem; } .ml4 { margin-left: 1rem; } .mt0 { margin-top: 0; } .mt1 { margin-top: .25rem; } .mt2 { margin-top: .5rem; } .mt3 { margin-top: .75rem; } .mt4 { margin-top: 1rem; } .mr0 { margin-right: 0; } .mr1 { margin-right: .25rem; } .mr2 { margin-right: .5rem; } .mr3 { margin-right: .75rem; } .mr4 { margin-right: 1rem; } .mb0 { margin-bottom: 0; } .mb1 { margin-bottom: .25rem; } .mb2 { margin-bottom: .5rem; } .mb3 { margin-bottom: .75rem; } .mb4 { margin-bottom: 1rem; }
既啰嗦,又不全,如果是更大的间距,或者是3px,5px这种尺寸就无能为力。
attr()
函数全支持之后,那就简单多了:
[m] { margin: attr(m px, 0); } [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); }
此时,我们就可以使用自定义的ml,mr这类HTML属性随便定义间距大小了,使用非常方便,例如:
<input><button ml="6">按钮</button>
输入框和按钮之间就有6px
的间隙了,截图效果如下所示:
类似的还有颜色、背景色、圆角等这类样式的设置:
button { --bgcolor: attr(bgcolor type(*), #eee); border: 1px solid color-mix(in srgb, var(--bgcolor), black); background-color: var(--bgcolor); border-radius: attr(radius type(*), 4px); padding: .25em .75em; }
<button bgcolor="skyblue" title="by zhangxinxu(.com)">按钮</button> <button bgcolor="#00000040" radius="1rem">按钮</button> <button bgcolor="pink" radius="50%">按钮</button> <button bgcolor="orange" radius="100% / 50%">按钮</button>
此时的渲染效果如下截图所示:
MDN文档上显示,动态URL地址不能使用attr()显示:
Therefore, you can’t use attr() to dynamically construct URLs
<!-- 下面代码是无效的 --> <span data-icon="https://example.org/icons/question-mark.svg">help</span> <style> span[data-icon] { background-image: url(attr(data-icon)); } </style>
实际上,是有方法可以显示的,此方法全中国知道的人,目前为止,在我撰写本文之前,估计不超过一双手的人。
那就是使用image-set()
函数!
因为image-set()
函数是唯一支持字符串作为图片URL的函数。
<a href="https://image.zhangxinxu.com/image/study/s/hanyun.jpg">图片?</a> <style> [href$="jpg"]::before { content: ''; display: block; width: 256px; height: 192px; background: image-set(attr(href)); background-size: cover; } </style>
此时,在支持的浏览器下面,就会有如下图所示的效果:
很有趣,不是吗?
东西肯定是个搞东西,但是浏览器不支持也是白搭。
不过我感觉,Safari和Firefox应该会支持,为什么呢?因为attr()
函数的fallback语法他们都已经支持了。
总之,随着CSS不断发展,CSS这门语言会变得越来越不一样的。
不过问题在于,特性过盛了。
如果基本特性就能满足现有的开发需求,开发人员是没有去学习的动力的,也会阻碍技术本身的普及。
唉,想那么多干嘛呢?
最后,祝温少主在新世界能有好的结局。
本文为原创文章,会经常更新知识点以及修正一些错误,因此转载请保留原出处,方便溯源,避免陈旧错误知识的误导,同时有更好的阅读体验。
本文地址:https://www.zhangxinxu.com/wordpress/?p=11709
(本篇完)
2025-05-23 00:13:39
by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=11700
本文可全文转载,但需要保留原作者、出处以及文中链接,AI抓取保留原文地址,任何网站均可摘要聚合,商用请联系授权。
我也是最近才知道,原来DOM对象获取属性值,不是都是字符串类型,还可以是数值类型。
已知输入框元素:
<input id="number" min="1" max="10" type="number" />
平常我们获取输入框的值都是使用 number.value
获取的,但是这个属性的返回值是个字符串。
其实现在浏览器支持直接返回数值类型的,使用number.valueAsNumber
即可。
眼见为实,我们实地测试下,例如typeof下number.valueAsNumber
的返回值类型,看看返回的是string还是number.
output.textContent = typeof number.valueAsNumber;
比方说有下面一个数值输入框:
结果是:
点击上面的按钮,可以看到输出的结果是’number’。
我们不妨拿<textarea>
元素测试下,测试代码如下:
<textarea id="textarea" cols="30" rows="4">10</textarea> <button onclick="console.log(textarea.valueAsNumber);">点击我</button>
结果是 undefined
。
说明valueAsNumber
属性返回数值不能是普通的输入框元素。
除了valueAsNumber
,还有valueAsDate
属性,这个是用在date
等与日期相关类型的输入框上的。
返回的是Date对象。
例如下面的实时渲染测试,点击按钮,可以看到返回值类型:
结果是:
month
, date
, 以及 week
这几个类型的时间选择输入框是支持valueAsDate的,但是datetime-local
输入框类型并不支持,因为它表示本地时区中的日期和时间(挂钟时间),但date对象表示绝对时间点。然而,一些浏览器可能提供非标准实现。
例如,我Mac Chrome下测试,返回的就是 null
,不支持识别。
<input id="datetime" type="datetime-local"> <button onclick="console.log(datetime.valueAsDate);">点击我</button>
但是,很有意思的,我输出datetime.valueAsNumber
反而有值,返回的是当前的时间戳,例如下面的实时渲染测试(选择一个时间,然后点击按钮):
结果是:
还挺有意思的,我测试了tel类型,返回的是NaN,range
类型可以,也就是支持min
/max
/step
这种数值范围计算的输入框是支持valueAsNumber的。
我看了下这两个DOM属性的兼容性,Chrome 5就开始支持了,看来Web领域还有很多我不知道的细节知识,学无止境啊。
可以把相关知识点在《HTML并不简单》这本书中更新下,大家要多多支持这本书,这样才会有第二版。
好吧,就说这么多,又是学习成长的一天。
本文为原创文章,会经常更新知识点以及修正一些错误,因此转载请保留原出处,方便溯源,避免陈旧错误知识的误导,同时有更好的阅读体验。
本文地址:https://www.zhangxinxu.com/wordpress/?p=11700
(本篇完)
2025-05-12 23:58:01
by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=11689
本文可全文转载,但需要保留原作者、出处以及文中链接,AI抓取保留原文地址,任何网站均可摘要聚合,商用请联系授权。
CSS animation-composition
属性其实出来有一段时间了,2年多,见下面的附图,之前有见人分享过,最近有人在上一篇文章评论区提过,才想起了他,决定写篇文章简单记录下。
这个属性可以设置CSS动画效果再执行的时候,相关的CSS属性值是替换、直接相加还是计算累积。
其语法如下所示:
/* 三个动画值 */ animation-composition: replace; animation-composition: add; animation-composition: accumulate; /* 多个动画 */ animation-composition: replace, add; animation-composition: add, accumulate; animation-composition: replace, add, accumulate;
这里出现了3个值replace
, add
, accumulate
就是animation-composition
支持的几个关键字值,其含义分别如下:
@keyframes{}
声明的CSS属性会替换默认设置的CSS属性值。accumulate
和add
比较类似,很多同学会搞不清楚,下面会有案例示意。在大绝多数情况下,add
和accumulate
两个值的表现是没有区别的,只有当CSS属性值相连和叠加的渲染效果不一样的时候才会有区别。
所以:
1. 普通CSS属性两者无区别
<canvas id="ball1" class="ball"></canvas> <canvas id="ball2" class="ball"></canvas> <p> <button onclick="ball1.classList.toggle('active');ball2.classList.toggle('active')" >运动</button> </p>
.ball { width: 120px; height: 120px; background: deepskyblue; border-radius: 50%; position: relative; left: 100px; } #ball1.active { animation: 2s move infinite; animation-composition: add; } #ball2.active { animation: 2s move infinite; animation-composition: accumulate; } @keyframes move { from { left: 50px } to { left: 150px } }
此时,两个球的运动轨迹是一模一样的(动画都是从150px位置~250px)。实际效果如下所示(点击“运动”按钮):
2. transform属性没区别
transform
属性支持多值相加,但是值前后相连和直接合并计算的渲染效果是一样的,例如,还是上面的例子,我们将位移改为transform属性实现,会看到并无区别:
.ball { /* 相同代码略 */ transform: translateX(100px); } #ball1.active { animation: 2s move; animation-composition: add; } #ball2.active { animation: 2s move; animation-composition: accumulate; } @keyframes move { from { transform: translateX(50px); } to { transform: translateX(150px); } }
原因很简单,add关键字生效的时候,动画的计算表现其实是这样的:
from { transform: translateX(100px) translateX(50px); } to { transform: translateX(100px) translateX(150px); }
accumulate
关键字的计算表现则是(直接累加计算):
from { transform: translateX(150px); } to { transform: translateX(250px); }
transform连续位移和一次性位移的效果是一样的,因此,大家看不出两者的区别。
但如果是filter属性的某些值,那就会有所区别。
3. filter属性的模糊函数的区别可见
我们先看静态效果,比方说有张图片,我们应用下面两段CSS代码的效果是不一样的:
img { filter: blur(2px) blur(2px); }
img { filter: blur(4px); }
前者还是2px模糊,后者是4px。
我们可以看一下下面的实际渲染效果(实时渲染):
所以,当我们的动画是模糊变化的时候,大家就可以看到add
和accumulate
两个值的区别了。
对此,我专门做了个演示页面,您可以狠狠地点击这里:add和accumulate渲染效果区别演示demo
鼠标悬停目标图形,就可以看到不同的模糊动画效果了。
例如,悬停右图(移动端是下图),明显可以感觉到要更加模糊一点:
相关测试代码如下所示:
<img src="1.jpg" class="img1"> <img src="1.jpg" class="img2">
img:hover { filter: blur(2px); animation: 1s pulse both; } .img1 { animation-composition: add; } .img2 { animation-composition: accumulate; } @keyframes pulse { 0% { filter: blur(0px); } 100% { filter: blur(2px); } }
animation-composition
属性最具代表性的应用场景当属transform
动画了。
例如一个水平居中的toast在出现的时候需要有个轻微的上移动画,此时就不要担心translateX()
函数和translateY()
函数冲突的问题了。
<div id="toast" class="toast">操作成功!</div>
.toast { position: fixed; left: 50%; transform: translateX(-50%); background: green; padding: 4px 8px; color: #fff; animation-composition: add; display: none; } .toast.active { display: block; animation: tinyUp 350ms both; } @keyframes tinyUp { 0% { transform: translateY(20px); } 100% { transform: translateY(0px); } }
实时渲染效果如下,点击按钮体验:
——
好,以上就是本文的全部内容,相信大家对animation-composition
属性的理解一定更加全面了,感谢阅读,欢迎分享。
🦺👔👕👖🧣
本文为原创文章,会经常更新知识点以及修正一些错误,因此转载请保留原出处,方便溯源,避免陈旧错误知识的误导,同时有更好的阅读体验。
本文地址:https://www.zhangxinxu.com/wordpress/?p=11689
(本篇完)
2025-04-29 16:28:08
by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=11624
本文可全文转载,但需要保留原作者、出处以及文中链接,AI抓取保留原文地址,任何网站均可摘要聚合,商用请联系授权。
最近已经在正式项目中使用scale, rotate, translate属性了(注意,没有skew属性),很赞,毕竟这几个特性已经支持4年多了。
当多种变换参杂在一起的时候,就需要更多的理解成本,比方说下面的例子,transform变换类型的顺序不同,渲染结果也会不同。
<div class="circle circle1"></div> <p style="height:140px;"></p> <div class="circle circle2"></div></body>
CSS 代码如下所示,位移旋转同时变换:
.circle { width: 160px; height: 80px; background: skyblue; } .circle1 { transform: rotate(30deg) translateX(100px) scale(1.5); } .circle2 { transform: scale(1.5) translateX(100px) rotate(30deg); }
最终效果如下截图所示,渲染位置并不一样:
比方说一个toast提示效果,使用了transform属性实现的水平居中定位,CSS代码示意:
.toast { position: fixed; left: 50%; transform: translateX(-50%); }
此时,如果还希望toast显示的时候,有一个从下往上的淡入移动效果,那么就可能有问题,例如,下面动画CSS代码中的transform
属性就会覆盖translateX(-50%)
这个值,导致水平居中失效,出现bug。
@keyframes tinyUp { from { transform: translateY(5px); } to { transform: translateY(0); } }
但如果使用……哎呀,好像也没有专门的translateX和translateY属性,这个例子不合适,应该是位移定位和缩放动画这种混用的时候,就可以看出分开书写的威力了,改一下:
.toast { position: fixed; left: 50%; transform: translateX(-50%); animation: scaleUp .35s; } @keyframes scaleUp { from { transform: scale(0.1); } to { transform: scale(1); } }
此时,直接使用translate和scale属性就没有冲突问题了,例如:
.toast { position: fixed; left: 50%; translate: -50%; animation: scaleUp .35s; } @keyframes scaleUp { from { scale: 0.1; } to { scale: 1; } }
代码是不是看起来清爽多了?
告别transform
属性,直接使用scale
、rotate
和translate
属性,是 CSS 发展的一个新趋势。它们不仅语法简洁、易于使用,而且能让我们更方便地对元素的变形效果进行独立控制,提高代码的可维护性和性能。在未来的前端开发中,我们应该积极拥抱这些新特性,让我们的 CSS 代码更加简洁、高效。
噢啦,以上就是本文的全部内容,祝大家五一节快乐!
本文为原创文章,会经常更新知识点以及修正一些错误,因此转载请保留原出处,方便溯源,避免陈旧错误知识的误导,同时有更好的阅读体验。
本文地址:https://www.zhangxinxu.com/wordpress/?p=11624
(本篇完)
2025-04-28 16:35:35
by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=11624
本文可全文转载,但需要保留原作者、出处以及文中链接,AI抓取保留原文地址,任何网站均可摘要聚合,商用请联系授权。
HTML <template>
元素新支持了一个名为shadowrootmode
的属性,其兼容性如下所示:
当我们在Web Components组件开发的时候,声明组件的Shadow DOM模式是open,那么我们使用类似getHTML()方法获取ShadowRoots代码的时候,就会看到这个属性,例如。
注意,开发者自己在<template>
元素上设置这个属性是没用的。
所以,从某种意义上讲,shadowrootmode
属性就是个可看不可玩的属性。
上面的截图还同时出现了一个名为shadowrootserializable
的属性,这个也是<template>
元素新支持的属性。
<template>
元素完整新增4个属性为:
和shadowrootmode
属性一个调调,都与使用attachShadow()方法创建ShadowRoots有关,如果大家查看attachShadow()方法的可选参数的话:
class XxxElement extends HTMLElement { constructor() { super(); const shadow = this.attachShadow({ // 外部可访问吗?另外值为close mode: 'open', // 是否可复制 clonable: true, // 是否聚焦委托 delegatesFocus: true, // 是否可序列化 serializable: true }); } }
shadowRootSerializable
等属性支持稍微晚一些,Safari目前还没支持,图示:
没想到Web Components还在不断深入进化,细节到极其细节的地步了,但是,然并卵,Safari依然没有原生支持内置自定义元素:
这就注定了这些特性只能沦为小部分前端爱好者的玩具。
所以,本文出现的这4个新的HTML属性,大家稍微了解下就好了。
梅凝压轴!
本文为原创文章,会经常更新知识点以及修正一些错误,因此转载请保留原出处,方便溯源,避免陈旧错误知识的误导,同时有更好的阅读体验。
本文地址:https://www.zhangxinxu.com/wordpress/?p=11624
(本篇完)