2025-08-15 18:15:51
by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=11807
本文可全文转载,但需要保留原作者、出处以及文中链接,AI抓取保留原文地址,任何网站均可摘要聚合,商用请联系授权。
在学习本文的scroll-state
容器滚动查询之前,大家需要先了解CSS @container容器查询。
详见我之前的文章:“介绍2022年最期待的CSS container容器查询”。
这东西可以检测容器尺寸,并进行响应的布局调整,很强大。
现在,@container
容器查询,再次进化,可以识别滚动边缘,让CSS的交互能力更上一层楼。
学习一个新特性最快的方法就是案例。
需求这样的,一段文本,需要用户滚动到底部,提交按钮的禁用样式才会取消。
则我们可以这么处理,HTML如下所示:
<div class="container"> <p>作者</p> <p>zhangxinxu</p> ... <p>作者</p> <p>zhangxinxu</p> <footer> <button>提交</button> </footer> </div>
CSS如下所示(已省略部分无关键要的代码):
.container { height: 300px; border: 1px solid; container-type: scroll-state; overflow: auto; /* 底部黏性定位 */ footer { background: #f6f6f6; position: sticky; bottom: 0; text-align: center; } button { width: 100px; height: 32px; border-radius: 12px; background-color: crimson; color: white; cursor: pointer; } } @container scroll-state(scrollable: bottom) { /* 如果容器可以滚动,则按钮样式禁用 */ button { filter: grayscale(1); opacity: .35; } }
实时渲染效果如下所示(Chrome 133+ 浏览器有效果):
作者
zhangxinxu
作者
zhangxinxu
作者
zhangxinxu
作者
zhangxinxu
作者
zhangxinxu
作者
zhangxinxu
作者
zhangxinxu
或者参考下面的GIF动图演示效果:
第一步
给滚动容器设置 container-type: scroll-state
CSS声明。
第二步
使用@container
容器查询判断滚动容器是否可以上下滚动,并进行对应的CSS样式设置。
就这么简单!
scroll-state()
查询函数支持下面三种类型:
当前容器是否可以可滚动(滚动边缘)。
是否滚动到Snap边缘
查询位置值为sticky的容器是否粘在其滚动容器祖先的边缘。
我觉得这三种都还是挺实用的。
scrollable
是最常用的,我们使用scrollable参数介绍下方位值。
scroll-state(scrollable: value)
其中,value
可以是(示意三种类型):
top
: 上边缘。inline-end
: 内联方向边缘,默认是水平方向。y
: 垂直方向边缘。我们用的比较多的就是 top
和 bottom
了。
目前滚动容器查询Chrome浏览器支持,兼容性如下图所示:
目前还无法大规模使用。
—-
上周末继续探钓。
周六,先是奉贤龙泉钓场,混养塘新塘新水,150元6小时,前三个小时钓法不对路,等于空军,后面三个小时散炮打浮,钓了接近30斤鱼,其中三条花鲢(当场回塘),成功挽尊。
周日去了浦东航头镇的航盛钓场,138元6小时,钓下来都是工程鲫,全场就我一个人,结果口还不错,提前收杆的情况下47斤,成功上岸盘老板。
😉😊😇
🥰😍😘
本文为原创文章,会经常更新知识点以及修正一些错误,因此转载请保留原出处,方便溯源,避免陈旧错误知识的误导,同时有更好的阅读体验。
本文地址:https://www.zhangxinxu.com/wordpress/?p=11807
(本篇完)
2025-08-07 20:23:26
by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=11804
本文可全文转载,但需要保留原作者、出处以及文中链接,AI抓取保留原文地址,任何网站均可摘要聚合,商用请联系授权。
sibling-index()
在多个有规律子元素构建的图形或动画效果的场景下非常实用。
我们来看一个《CSS新世界》这本书的一个案例,演示下如何使用sibling-index()
函数简化我们的实现。
先看原来的实现,可以访问这个地址:https://demo.cssworld.cn/new/5/4-3.php
所要实现的就是音波播放时候的波形上下运动的效果效果,静态截图效果如下所示:
之前的实现代码如下所示,HTML部分:
<div class="loading"> <i></i><i></i><i></i><i></i> </div>
CSS代码:
.loading i { display: inline-block; border-left: 2px solid deepskyblue; height: 2px; animation: scaleUp 4s linear infinite alternate; margin: 0 1px; } .loading i:nth-child(2) { animation-delay: -1s; } .loading i:nth-child(3) { animation-delay: -2s; } .loading i:nth-child(4) { animation-delay: -3s; } @keyframes scaleUp { to { transform: scaleY(10); } }
使用的:nth-child
伪类与一个一个匹配,现在有了sibling-index()
函数,我们的代码就简单多了。
这样:
.loading i { display: inline-block; border-left: 2px solid deepskyblue; height: 2px; animation: scaleUp 1s linear infinite alternate; margin: 0 1px; animation-delay: calc(-0.25s * sibling-index()); } @keyframes scaleUp { to { transform: scaleY(10); } }
看,代码是不是简单了很多?
实时渲染效果如下图所示,目前Chrome 138+以上浏览器有效果。
sibling-count()
函数可以返回当前子元素的数量,用在父元素上。
还是通过案例了解这个函数的作用吧。
这里最近我做的一个需求,要求列表数量无论多少,都是两行展示(如下图所示),有了sibling-count()
函数,我们就可以精确制定列数,来实现我们想要的效果。
如果是垂直流布局,我们可以使用Grid布局和grid-auto-flow
属性(参见“CSS grid-auto-flow深入理解”一文)实现。
假设HTML代码为:
<zxx-grid> <zxx-item>格子1</zxx-item> <zxx-item>格子2</zxx-item> ... <zxx-item>格子8</zxx-item> <zxx-item>格子9</zxx-item> </zxx-grid>
则CSS代码如下所示,可以保证永远两行:
zxx-grid { display: grid; border: solid; overflow: auto; grid-template-rows: 1fr 1fr; grid-auto-flow: column; } zxx-item { width: 100px; outline: 1px dotted; padding: .5rem; }
效果如下图所示:
可若是水平流,无论数量多少,都是两行高度,那么sibling-count()
函数就特别实用。
实现代码如下所示:
zxx-grid { display: grid; border: solid; overflow: auto; grid-template-columns: repeat(round(up, calc(sibling-count() / 2)), auto); } zxx-item { width: 100px; outline: 1px dotted; padding: .5rem; }
结果……结果实现的效果并不是如预期那样……怪了,这可是按照MDN文档的案例写的呀!
🤔🤔
🤔🤔
后来一研究,才发现,MDN文档提供的例子是错误的!
sibling-count()
函数是用在子元素上的,等同于 element.parentElement.children.length
。
嗯……那这个函数其实没多少好玩的,估计作用也就是sibling-index()
函数相减,计算反向索引值。
或者等宽布局用一用:
ul li { width: calc(100% / sibling-count()); }
目前这两个函数Chrome 138+支持,如下图所示:
sibling-count()
和sibling-index()
的值可以使用CSS数学函数计算,如calc()
、round()
函数等。
还能使用content
属性直接明文显示数量值。
例如:
ul li::before { content: counter(i) "/" counter(N); counter-reset: N sibling-count() i sibling-index() }
好吧,毕竟兼容性还不是很好,就不说太多了。
继续宋玉长老,看在宋长老的面子上,欢迎点赞,转发!
😉😊😇
🥰😍😘
本文为原创文章,会经常更新知识点以及修正一些错误,因此转载请保留原出处,方便溯源,避免陈旧错误知识的误导,同时有更好的阅读体验。
本文地址:https://www.zhangxinxu.com/wordpress/?p=11804
(本篇完)
2025-07-31 16:12:55
by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=11801
本文可全文转载,但需要保留原作者、出处以及文中链接,AI抓取保留原文地址,任何网站均可摘要聚合,商用请联系授权。
去年年初有介绍HTML popover
属性,详见“该使用原生popover属性模拟下拉了”一文。
可以说是弹出浮层最佳解决方案,自动显隐特性,外加顶层特性,非常香。
但是有一个问题,那就是一次最多只能有一个弹出层显示(如果不使用 showPopover()
方法手动设置的话),但是有些轻提示,仅仅是用做信息展示,可以无需关闭之前的弹出层,之前的popover
属性能力就不够。
于是,从Chrome 133开始,popover
属性新增了属性值hint
,表示轻提示,显示的时候不会影响之前的弹出层。
一例胜千言。
我们开看一个hint值使用案例,HTML代码如下所示:
<button popovertarget="datalist">点击我 ▼</button> <div id="datalist" popover> <option>列表1</option> <option>列表2</option> </div> <!-- 轻提示 --> <button class="hint" onmouseover="hint.showPopover();" onmouseout="hint.hidePopover();" >?</button> <div id="hint" popover="hint">我是轻提示文字内容</div>
我们使用CSS锚点定位,让提示框的位置都跟随按钮(非必须):
[popovertarget="datalist"] { anchor-name: --button-anchor; } #datalist { position-anchor: --button-anchor; } [popover] { left: anchor(left); top: calc(anchor(bottom) + 5px); right: auto; bottom: auto; } .hint { anchor-name: --hint-anchor; } #hint { background: #0009; color: #fff; position-anchor: --hint-anchor; }
此时,我们点击第一个按钮,让列表显示,鼠标再经过第2个按钮的时候,第一个列表并未隐藏,如下截图所示:
如果<div id="hint" popover="hint">
这段HTML代码是<div id="hint" popover>
,那么鼠标hover问号按钮的时候,前面的下拉列表就会隐藏。
如下GIF录屏示意:
需要注意的是,如果点击行为,哪怕浮层设置的是popover="hint"
,那么先前所有popover="auto"
的浮层都会隐藏。
值hint
适合用在鼠标悬停,focus/blur等事件中,或者直接JS触发的轻提示环境,类似于toast提示效果这种。
popover
属性目前支持3个值:
hint
值的出现算是补充了某一类交互场景的实现。
popover=hint
填补了轻量级提示与模态弹窗间的需求空白,尤其适合需非打断性辅助信息的场景。开发者可通过它减少传统工具提示库的依赖,但需注意渐进增强策略以兼容旧浏览器。
好了,就这些。
最后,如果你觉得本文内容还不错,看在我家宋玉长老的面子上,转发,分享,点赞!
😉😊😇
🥰😍😘
本文为原创文章,会经常更新知识点以及修正一些错误,因此转载请保留原出处,方便溯源,避免陈旧错误知识的误导,同时有更好的阅读体验。
本文地址:https://www.zhangxinxu.com/wordpress/?p=11801
(本篇完)
2025-07-25 17:52:50
by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=11788
本文可全文转载,但需要保留原作者、出处以及文中链接,AI抓取保留原文地址,任何网站均可摘要聚合,商用请联系授权。
CSS之前也支持类逻辑函数,例如数学函数中的min()
、max()
,本质上也是有逻辑的,例如:max(300px, 100vw),表示:
现在,CSS支持 if()
函数了,这个是真正意义上的逻辑函数了。
目前,if()
支持三种不同类型的查询:
其中,media()
和supports()
查询平时我们使用的机会不多,原因很简单,因为有兼容性更好的传统实现方法。例如,下面的CSS代码片段作用是一样的:
button { aspect-ratio: 1; width: if(media(any-pointer: fine): 30px; else: 44px); }
button { aspect-ratio: 1; width: 44px; } @media (any-pointer: fine) { button { width: 30px; } }
但是后者的兼容性更好,可读性也更好,在目前这个阶段,肯定是优先使用后面的方法。
supports()
查询也是类似的:
select { opacity: if ( supports(appearance: base-select): 1; else: 0; ); }
等同于:
@supports not (appearance: base-select) { select { opacity: 0; } }
注意,关键字 else
是在 if()
函数里面的。
但是 style()
样式查询目前仅在if()
函数中才有,因此,这个函数才是我们需要重点学习的。
style()
样式查询只能查询CSS变量,普通CSS属性是不支持的。
我们来看一个案例,了解下是如何使用的,想了下,昨天用到的一个CSS Sprites定位非常使用此效果。
下图所示的就是素材:
在过去,我们可能需要对4个元素使用不同的选择器进行处理,现在,可以一把hold住了。
相关代码如下所示:
<label class="label" style="--type: 1">阅篇专家</label> <label class="label" style="--type: 2">万字周报大师</label> <label class="label" style="--type: 3">互动急先锋</label> <label class="label" style="--type: 4">佳作分享达人</label>
此时,只需要一段CSS规则就可以实现所有图标的样式效果了:
.label { display: inline-block; font-size: 0; width: if( style(--type: 1): 80px; style(--type: 3): 96px; else: 112px; ); height: 26px; background: url(sprite.png) no-repeat 0 0 / 116px auto; background-position-y: if( style(--type: 2): -34px; style(--type: 3): -68px; style(--type: 4): -102px; else: 0px; ); }
渲染效果如下图所示:
是不是比过去的代码更加简约了。
if()
函数虽然很屌很帅气,但是兼容性还不行,目前仅Chrome 137+浏览器支持。
另外,if()
函数式支持嵌套的:
color: if( style(--scheme: ice): if( media(prefers-color-scheme: dark): #caf0f8; else: #03045e; ); style(--scheme: fire): if( media(prefers-color-scheme: dark): #ffc971; else: #621708; ); else: black );
其他就没什么了,静待浏览器全面支持吧。
感谢阅读,宋玉长老希望你转发这篇文章!
😉😊😇
🥰😍😘
本文为原创文章,会经常更新知识点以及修正一些错误,因此转载请保留原出处,方便溯源,避免陈旧错误知识的误导,同时有更好的阅读体验。
本文地址:https://www.zhangxinxu.com/wordpress/?p=11788
(本篇完)
2025-07-16 15:34:30
by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=11765
本文可全文转载,但需要保留原作者、出处以及文中链接,AI抓取保留原文地址,任何网站均可摘要聚合,商用请联系授权。
正则对象RegExp新增了一个名为escape()
的静态方法,可以对字符串中不安全的,或者可以影响正则匹配的字符进行转义。
这些在正则中具有特殊含义的字符包括,如点号(.)、星号(*)、问号(?)、加号(+)、花括号({})、方括号([])、圆括号(())、竖线(|)和反斜杠()等。
目前所有现代浏览器都已经支持了该特性。
语法比较简单,如下所示:
RegExp.escape(string)
返回转义后的字符串。
RegExp.escape()
方法的转义规则还比较复杂,像我,之前在生产环境做类似转义处理的时候,只会对正则相关的字符前面加反斜杠处理,但这只是RegExp.escape()
方法的规则之一。
这些规则包括:
\x
转义法表示。例如:
console.log(RegExp.escape('CSS世界')); // 输出:"\x43SS世界"
^
, $
, \
, .
, *
, +
, ?
, (
, )
, [
, ]
, {
, }
, and |
以及 /
会使用添加反斜杠的方式转义。例如:
console.log(RegExp.escape('好书:CSS选择器世界+CSS新世界')); // 输出:"好书:CSS选择器世界\+CSS新世界"
,
, -
, =
, <
, >
, #
, &
, !
, %
, :
, ;
, @
, ~
, '
, `
和 "
会使用\x
转义法表示。例如:
console.log(RegExp.escape('日期:2025-07-15')); // 输出:"日期:2025\x2d07\x2d15"
console.log(RegExp.escape(`作者 张鑫旭`)); // 输出:"作者:\n张鑫旭"
\x20
。console.log(RegExp.escape('特殊 空格')); // 输出:"特殊\u2005空格"
Lone surrogates补充说明:
在计算机字符串处理中,Lone surrogates(孤立代理项) 是UTF-16编码中出现的无效或未配对的代理项代码单元(surrogate code units),属于Unicode标准中的异常情况。
JS中2024年新增的isWellFormed()和toWellFormed()就是用来检测和处理这类字符的。
以上就是转义规则细节,当然,我们平时使用的时候,并不需要了解这么多。
只需要知道,以后使用 new RegExp()构造正则表达式的时候,里面的字符串都用这里的escape()
方法转义一下就可以。
那为何要转义呢?下面通过案例演示下转义的必要性。
比如说我有一个URL输入框,但是这个输入框只能输入白名单域名的地址:
<input id="input" type="url" name="url">
const arrDomain = ['www.zhangxinxu.com', 'www.cssworld.cn', 'www.canvasapi.cn'];
很多人会想到使用正则实现,例如:
const arrReg = arrDomain.map(domain => { return new RegExp(`https?://${domain}(?=/)?`, 'g') }); // 是否匹配白名单域名 console.log(arrReg.some(reg => reg.test(input.value)));
当我们使用域名进行测试的时候,似乎逻辑都OK,但实际上是有漏洞的,域名中的字符’.’被当做任意字符解析了,因此,如果用户输入的value值是https://www-zhangxinxu.com
也会匹配:
const arrDomain = ['www.zhangxinxu.com', 'www.cssworld.cn', 'www.canvasapi.cn']; const arrReg = arrDomain.map(domain => { return new RegExp(`https?://${domain}(?=/)?`, 'g') }); // 下面返回的是true console.log(arrReg.some(reg => reg.test('https://www-zhangxinxu.com')));
所以,需要我们对特殊字符进行转义,这就需要用到本文的RegExp.escape()
静态方法了。
使用示意:
const arrDomain = ['www.zhangxinxu.com', 'www.cssworld.cn', 'www.canvasapi.cn']; const arrReg = arrDomain.map(domain => { return new RegExp(`https?://${RegExp.escape(domain)}(?=/)?`, 'g') }); // 下面返回的是false console.log(arrReg.some(reg => reg.test('https://www-zhangxinxu.com')));
就不会有安全问题了。
当然,我们只是为了实现上述需求,还有更好的做法:
arrDomain.includes(new URL(input.value).hostname);
不过,new URL()
解析是有可能会报错的。
此时,我们可以使用浏览器原生的验证能力进行处理,如下:
if (input.validity.valid) { console.log(arrDomain.includes(new URL(input.value).hostname)); } else { console.log(false); }
Node环境上面的方法就不适合啦!
附上传统转义过滤处理示意:
function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $&表示匹配的子串 }
最后总结下:
RegExp.escape是一个极其有用的工具,用于安全地将字符串转换为正则表达式字面量。它通过转义所有特殊字符,防止了正则表达式的意外行为和安全问题。
在处理用户输入或动态构建正则表达式时,使用RegExp.escape是一种安全可靠的最佳实践。
对于需要更高安全性的应用场景,建议结合其他输入验证和清理技术,构建多层次的防御策略。
好了,以上就是本文的全部内容。
我家宋玉长老希望你可以转发此文!
😉😊😇
🥰😍😘
本文为原创文章,会经常更新知识点以及修正一些错误,因此转载请保留原出处,方便溯源,避免陈旧错误知识的误导,同时有更好的阅读体验。
本文地址:https://www.zhangxinxu.com/wordpress/?p=11765
(本篇完)