MoreRSS

site iconZhangXinXu | 张鑫旭修改

出版《CSS选择器世界》,喜欢钓鱼、写作。
请复制 RSS 到你的阅读器,或快速订阅到 :

Inoreader Feedly Follow Feedbin Local Reader

ZhangXinXu | 张鑫旭的 RSS 预览

震惊,有生之年居然看到CSS attr()全属性支持

2025-05-28 14:19:08

by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=11709
本文可全文转载,但需要保留原作者、出处以及文中链接,AI抓取保留原文地址,任何网站均可摘要聚合,商用请联系授权。

css attr全属性支持

一、真的是有生之年系列

说实话,CSS attr()全属性支持这个特性我等了六七年至少有了。之前还为其写了个Polyfill工具:“Polyfill吊炸天的CSS attr()新语法

本来以为这辈子都不会看到浏览器对其进行支持了。

万万没想到,Chrome133版本开始居然支持了,它居然支持了。

attr()函数的兼容性

在过去,attr()函数只能用在content属性中,现在所有的CSS属性都支持,而且语法更加丰富,某种程度上,可以颠覆现有的前端开发习惯,一点也不夸张,

二、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>

此时的渲染效果如下截图所示:

自定义按钮样式

三、动态URL作为背景图显示

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语法他们都已经支持了。

fallback语法兼容性

总之,随着CSS不断发展,CSS这门语言会变得越来越不一样的。

不过问题在于,特性过盛了。

如果基本特性就能满足现有的开发需求,开发人员是没有去学习的动力的,也会阻碍技术本身的普及。

唉,想那么多干嘛呢?

最后,祝温少主在新世界能有好的结局。

温天仁和侍女

本文为原创文章,会经常更新知识点以及修正一些错误,因此转载请保留原出处,方便溯源,避免陈旧错误知识的误导,同时有更好的阅读体验。
本文地址:https://www.zhangxinxu.com/wordpress/?p=11709

(本篇完)

你知道吗,输入框的value值也能直接返回数值类型

2025-05-23 00:13:39

by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=11700
本文可全文转载,但需要保留原作者、出处以及文中链接,AI抓取保留原文地址,任何网站均可摘要聚合,商用请联系授权。

标题占位符,可以是非字符串吗

一、直接正题-valueAsNumber

我也是最近才知道,原来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属性返回数值不能是普通的输入框元素。

二、valueAsDate属性类似

除了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

(本篇完)

CSS animation-composition可以让动画效果累加

2025-05-12 23:58:01

by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=11689
本文可全文转载,但需要保留原作者、出处以及文中链接,AI抓取保留原文地址,任何网站均可摘要聚合,商用请联系授权。

一、前言

CSS animation-composition属性其实出来有一段时间了,2年多,见下面的附图,之前有见人分享过,最近有人在上一篇文章评论区提过,才想起了他,决定写篇文章简单记录下。

animation-composition兼容性

这个属性可以设置CSS动画效果再执行的时候,相关的CSS属性值是替换、直接相加还是计算累积。

二、animation-composition语法和案例

其语法如下所示:

/* 三个动画值 */
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支持的几个关键字值,其含义分别如下:

replace
这是默认值。动画也就是@keyframes{}声明的CSS属性会替换默认设置的CSS属性值。
add
属性值直接相加。
accumulate
属性值计算叠加。accumulateadd比较类似,很多同学会搞不清楚,下面会有案例示意。

add和accumulate的区别

  • add是纯粹的属性值相加。
  • accumulate则是累加计算后的值。

在大绝多数情况下,addaccumulate两个值的表现是没有区别的,只有当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。

我们可以看一下下面的实际渲染效果(实时渲染):

张含韵
张含韵

所以,当我们的动画是模糊变化的时候,大家就可以看到addaccumulate两个值的区别了。

对此,我专门做了个演示页面,您可以狠狠地点击这里: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

(本篇完)

告别transform,是时候直接使用scale, rotate属性啦

2025-04-29 16:28:08

by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=11624
本文可全文转载,但需要保留原作者、出处以及文中链接,AI抓取保留原文地址,任何网站均可摘要聚合,商用请联系授权。

封面占位图

一、兼容性已经很OK啦

最近已经在正式项目中使用scale, rotate, translate属性了(注意,没有skew属性),很赞,毕竟这几个特性已经支持4年多了。

rotate属性兼容性

二、transform实现变换的问题

问题1,计算复杂

当多种变换参杂在一起的时候,就需要更多的理解成本,比方说下面的例子,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);
}

最终效果如下截图所示,渲染位置并不一样:

不同变换顺序渲染结果不同

问题2 动画冲突

比方说一个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属性,直接使用scalerotatetranslate属性,是 CSS 发展的一个新趋势。它们不仅语法简洁、易于使用,而且能让我们更方便地对元素的变形效果进行独立控制,提高代码的可维护性和性能。在未来的前端开发中,我们应该积极拥抱这些新特性,让我们的 CSS 代码更加简洁、高效。

噢啦,以上就是本文的全部内容,祝大家五一节快乐!

五一节快乐

本文为原创文章,会经常更新知识点以及修正一些错误,因此转载请保留原出处,方便溯源,避免陈旧错误知识的误导,同时有更好的阅读体验。
本文地址:https://www.zhangxinxu.com/wordpress/?p=11624

(本篇完)

光速了解HTML shadowrootmode等属性的作用

2025-04-28 16:35:35

by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=11624
本文可全文转载,但需要保留原作者、出处以及文中链接,AI抓取保留原文地址,任何网站均可摘要聚合,商用请联系授权。

shadowrootmode封面图

一、光速有多快?

HTML <template>元素新支持了一个名为shadowrootmode的属性,其兼容性如下所示:

shadowrootmode兼容性

shadowrootmode作用

当我们在Web Components组件开发的时候,声明组件的Shadow DOM模式是open,那么我们使用类似getHTML()方法获取ShadowRoots代码的时候,就会看到这个属性,例如。

可序列化ShadowRoot输出内容

注意,开发者自己在<template>元素上设置这个属性是没用的。

所以,从某种意义上讲,shadowrootmode属性就是个可看不可玩的属性。

上面的截图还同时出现了一个名为shadowrootserializable的属性,这个也是<template>元素新支持的属性。

二、光速来不及了,音速了解

<template>元素完整新增4个属性为:

  • shadowRootClonable 标示可复制状态
  • shadowRootDelegatesFocus 标示聚焦委托状态(子元素点击,ShadowRoot获得焦点)
  • shadowRootMode 标示开放状态
  • shadowRootSerializable 标示序列化状态

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目前还没支持,图示:

shadowRootSerializable兼容性

三、好了,结束了

没想到Web Components还在不断深入进化,细节到极其细节的地步了,但是,然并卵,Safari依然没有原生支持内置自定义元素:

内置自定义元素兼容性 Safari

这就注定了这些特性只能沦为小部分前端爱好者的玩具。

所以,本文出现的这4个新的HTML属性,大家稍微了解下就好了。

梅凝压轴!

梅凝美女

本文为原创文章,会经常更新知识点以及修正一些错误,因此转载请保留原出处,方便溯源,避免陈旧错误知识的误导,同时有更好的阅读体验。
本文地址:https://www.zhangxinxu.com/wordpress/?p=11624

(本篇完)