2025-06-18 16:37:08
by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=11717
本文可全文转载,但需要保留原作者、出处以及文中链接,AI抓取保留原文地址,任何网站均可摘要聚合,商用请联系授权。
两年前有介绍过text-wrap:balance
的作用,详见“5分钟快速了解text-wrap:balance的作用”此文。
这个声明还是挺好用的,特别适合用在可换行的水平列表排列上。
比方说过去,点赞头像这种布局,就可能第一行很多,第二行很少:
使用text-wrap:balance
之后,可以让两行的数量接近,布局效果很好很多。
现在text-wrap
又支持了两个新的属性值,pretty和stable。
按照MDN上的说法,text-wrap:pretty
声明和text-wrap:wrap
是一样的,区别在于text-wrap:pretty
更注重排版,而非性能,也就是wrap
的算法速度更快。
所以我就很好奇,既然pretty
和wrap
效果一样,性能还更差,那为何还要设计出来呢?
后来查了个资料,终于明白pretty
和wrap
的差异了,text-wrap:pretty
可以避免最后一行过短。
MDN页面的demo我通过添加文字,让最后一行只露出一个单词,终于看到了两者的区别,如下GIF所示:
按照规范上的说法,不同浏览器对pretty的理解是可以不一样的,可就是Firefox,Safari之类可能是另外的排版美化效果,上图展示的事Chrome下的表现。
目前,Chrome117+版本支持该值,Safari即将支持,Firefox还未支持。
stable
的作用,按照文档的说法,也是和wrap
没有什么区别。只有当文本内容处于标记状态的时候,text-wrap:stable
可以让编辑内容前面的行内容保持稳定,而不会整个文本内容发生排版变化。
嗯……我反复尝试了下,未能复现。反正意思就是,如果元素是contenteditable
可编辑的,那么建议设置text-wrap:stable
,只有好处,没有坏处。
目前Chrome 130+版本支持属性值stable
,奇怪的是,此属性值Safari和Firefox也都已经支持了,这个现象倒是有趣。
由于text-wrap
属性的值愈发复杂,因此,开始有了子属性,text-wrap
就变成了合并属性,类似于text-decoration
、border-image
这类CSS属性。
两个子属性,一个是text-wrap-mode
,还有一个是text-wrap-style
。
text-wrap-mode
这个属性超级简单,单看语法就知道怎么使用的了:
/* 换行显示 */ text-wrap-mode: wrap; /* 不自动换行显示 */ text-wrap-mode: nowrap;
不过考虑到兼容性,我们目前还是使用white-space
属性比较合适:
/* 换行显示 */ white-space: wrap; /* 不自动换行显示 */ white-space: nowrap;
直接看text-wrap-style
属性的语法:
/* 正常换行显示 */ text-wrap-style: auto; /* 每行内容尽可能相等 */ text-wrap-style: balance; /* 最后一行不要太短 */ text-wrap-style: pretty; /* 保持前面行数排版稳定 */ text-wrap-style: stable;
text-wrap-mode
和text-wrap-style
这两个属性的兼容性是一样的,都是今年刚支持的新特性。
还是balance
属性值实用,最近新支持的几个CSS属性和方法,你不能说他毫无用处,只能说只有一丢丢用处,给我感觉,就是规范制定那群人,不整点新东西,就好像工作不饱和,自己失去了存在价值一般。
有点类似于公司里面想一些无效的需求,来解决那么多人的就业问题一样。
注定扫入历史垃圾箱的几个新特性。
好吧,就说这么多,感谢阅读,我的侍妾慕沛灵希望大家多多转发。
本文为原创文章,会经常更新知识点以及修正一些错误,因此转载请保留原出处,方便溯源,避免陈旧错误知识的误导,同时有更好的阅读体验。
本文地址:https://www.zhangxinxu.com/wordpress/?p=11717
(本篇完)
2025-06-13 16:24:36
by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=11727
本文可全文转载,但需要保留原作者、出处以及文中链接,AI抓取保留原文地址,任何网站均可摘要聚合,商用请联系授权。
先回答题目抛出的问题,一句话:
::scroll-button
可以自定义上下或左右滚动按钮,::scroll-marker
可以自定义切换按钮,用在CSS Scroll Snap交互场景下,以便实现完整的Carousel,Slider等交互效果。
先看::scroll-button()
伪元素使用场景,可以模拟Scroll Snap上一项和下一项切换展示效果。
您可以狠狠地点击这里:CSS ::scroll-button实现slide左右切换demo
可以看到图片slider左右有切换按钮,点击的时候,图片就会左右滑动,非常的流畅,整个交互过程没有任何JS的参与。
如下MP4录屏所示(不动点击播放):
其中还使用了锚点定位技术,有兴趣的可以参见“全新的CSS Anchor Positioning锚点定位API”这篇文章。
其中,HTML结构比较简单:
<zxx-slide> <a href="###"><img src="ps1.jpg"></a> <a href="###"><img src="ps2.jpg"></a> <a href="###"><img src="ps3.jpg"></a> <a href="###"><img src="ps4.jpg"></a> </zxx-slide>
CSS核心代码如下所示(完整代码访问demo获取):
zxx-slide { overflow: auto; scrollbar-width: none; overscroll-behavior-x: contain; scroll-snap-type: x mandatory; scroll-behavior: smooth; a { scroll-snap-align: start; } } zxx-slide::scroll-button(left) { content: "◄"; } zxx-slide::scroll-button(right) { content: "►"; } zxx-slide { anchor-name: --myCarousel; } zxx-slide::scroll-button(*) { position: absolute; position-anchor: --myCarousel; } zxx-slide::scroll-button(*) { align-self: anchor-center; } zxx-slide::scroll-button(left) { right: calc(anchor(left) - 45px); } zxx-slide::scroll-button(right) { left: calc(anchor(right) - 45px); }
使用了很多CSS新特性,如果不是持续关注CSS的前端开发,上面的代码多半都已经不认识了。
支持的参数包括下面这些:
::scroll-button(*) {} ::scroll-button(left) {} ::scroll-button(up) {} ::scroll-button(right) {} ::scroll-button(down) {} ::scroll-button(block-end) {} ::scroll-button(block-start) {} ::scroll-button(inline-end) {} ::scroll-button(inline-start) {}
注意,垂直访问是up/down,而不是top/bottom。
常规的CSS属性都支持,因此,我们可以自如地对切换按钮进行样式自定义。
::scroll-marker
的是要要更复杂些,需要和scroll-marker-group
属性以及::scroll-marker-group
伪元素配合使用。
还是通过案例快速上手吧。
您可以狠狠地点击这里:CSS ::scroll-marker实现slide序号切换demo
页面效果如下,点击下面的序号按钮,图片就会平滑滚动到对应的位置,如下截屏动画所示(不播放就“戳”一下):
很赞,对不对?
HTML和上面demo一样,主要看下CSS部分:
zxx-slide { display: flex; overflow: auto; scrollbar-width: none; overscroll-behavior-x: contain; scroll-snap-type: x mandatory; scroll-behavior: smooth; scroll-marker-group: after; a { scroll-snap-align: start; counter-increment: markers; &::scroll-marker { content: counter(markers); /*... */ } } ::scroll-marker:target-current { background-color: #cd0000; color: white; } } ::scroll-marker-group { display: flex; place-content: center; }
这里出现了一个新的伪类:target-current
,表示当选匹配的marker选项。
scroll-marker-group
属性的作用:控制包含::scroll-marker-group
伪元素的滚动容器是否生成,如果生成,位置是前还是后。
使用示意:
/* 索引序号组在滚动容器前面 */ scroll-marker-group: before; /* 索引序号组在滚动容器后面 */ scroll-marker-group: after; /* 默认值,不显示索引序号组 */ scroll-marker-group: none;
::scroll-marker
伪元素的父级容器元素,控制索引序号整体位置、样式用的。
具体使用参见上面的样式页面。
本文介绍的这几个伪元素和CSS属性都需要Chrome 135+支持,是比较新的一个特性。
::column
伪元素也是同一时间支持的伪元素,也是用在CSS carousel 效果中的,和上面的区别在于,水平布局是使用columns布局实现。
此时,若还是按照本文的案例使用,则需要这么使用:
zxx-slide::column { scroll-snap-align: center; } zxx-slide::column::scroll-marker { content: ""; /* 按钮样式... */ } zxx-slide::column::scroll-marker:target-current { background-color: #cd0000; }
具体不展开,因为columns布局用的人本就少,别说这个伪元素的。
使用::column
的目的是不影响原本的columns布局。
最后,本文::scroll-button
、::scroll-marker
伪元素生成的交互按钮,天然支持无障碍访问,很棒!
好吧,就说这么多,又是学习的一天!
😉😊😇
🥰😍😘
本文为原创文章,会经常更新知识点以及修正一些错误,因此转载请保留原出处,方便溯源,避免陈旧错误知识的误导,同时有更好的阅读体验。
本文地址:https://www.zhangxinxu.com/wordpress/?p=11727
(本篇完)
2025-06-04 17:51:19
by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=11717
本文可全文转载,但需要保留原作者、出处以及文中链接,AI抓取保留原文地址,任何网站均可摘要聚合,商用请联系授权。
PageSwapEvent事件是一个新支持的全局事件,其兼容性如下:
目前Safari和Chrome均支持此事件类型。
乍一看,这个事件与页面选项卡切换相关,对吧,Swap就是交换的意思,但是,如果你在页面中写下类似这样的测试代码,是看不到任何效果的。
window.addEventListener("pageswap", (event) => { console.log(event); });
怎么回事,难道这个事件不是这样执行的?对,没错,不是这样执行的。
这个事件必须与页面级可视动画View Transitions API一同使用才有效果。
不知大家阅读过之前这篇热文没有:“页面级可视动画View Transitions API初体验”
其中展示了一个案例,就是页面A调整到页面B(直接刷新的那种跳转),也是可以有transition过渡效果的。
这里有演示页面,您可以狠狠地点击这里:传统跳转页面变得单页一样滑来滑去demo
而JS PageSwapEvent事件就是为了这个交互场景而设计的。
如果我们的Web页面设置了页面级别的view-transition,包含下面这段CSS代码:
@view-transition { navigation: auto; }
那么当页面准备卸载(unload)的时候,pageswap实践就会触发。
如果仅仅是普通的页面跳转,是不会有事件触发的。
我们可以对比下效果,比方说这个测试页面:纯粹的页面刷新跳转demo
页面中设置了pageswap事件代码:
window.addEventListener("pageswap", (event) => { console.log(event); });
但是,我们点击链接跳转的时候,只有导航提示,并没有任何console输出,如下截图所示:
但是,如果是上面的滑来滑去demo,我们可以在控制台看到PageSwapEvent对象的输出(需要开启Preserve log选项),如下图所示:
所以,PageSwapEvent事件是伴随View Transitions API一同出现的事物。
PageSwapEvent对象支持两个只读属性,分别是:
null
。至于返回对象的细节,这里不深入。
pageswap表示当前页面离开,那么进入则是PageReveal事件。
window.addEventListener("pagereveal", (event) => { console.log(event); });
不过语法上有所区别,仅支持viewTransition这个只读属性:
其他就没什么好讲的了。
一方面受制于兼容性,另一方面受制于PageSwapEvent事件的小众应用场景,再一方面受制于前端行业进入稳定期,再再一方面由于AI的出现,注定PageSwap事件是个很少有人会真正在生产环境使用的特性。
冷门知识,小众特性,虽然有设计价值,但注定无人问津。
大家了解下有这么个东西就好了。
其他就没什么好说的了,感谢大家的阅读,我们下一篇文章再见。
😉😊😇
🥰😍😘
本文为原创文章,会经常更新知识点以及修正一些错误,因此转载请保留原出处,方便溯源,避免陈旧错误知识的误导,同时有更好的阅读体验。
本文地址:https://www.zhangxinxu.com/wordpress/?p=11717
(本篇完)
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
(本篇完)