关于CSS选择器的两个技术问题:attr()选择id与通过aria-errormessage关联元素的条件显示
嗨,我来帮你搞定这个问题!你想通过input的aria-errormessage属性找到对应的错误提示元素,还得在输入框处于:user-invalid状态时才显示它,这个需求完全能用CSS实现,但你之前写的选择器语法不对,咱们一步步来修正。
首先得说清楚:你用的&[#attr(aria-errormessage)]这种写法是无效的,CSS里根本没有这种“引用其他元素属性值来匹配当前元素id”的原生选择器逻辑,而且&是Sass/LESS这类预处理器的父选择器语法,原生CSS不支持哦。
那纯CSS里怎么实现你的需求呢?咱们分情况来聊:
情况1:错误提示是input的同级兄弟元素(你的HTML结构正好符合这个条件)
因为你的错误提示p标签和input是同一个div的子元素,属于同级兄弟,那我们可以利用兄弟选择器+属性选择器的组合来实现,核心思路是通过结构关系来关联元素,而不是直接读取属性值匹配id。
基础实现方案(依赖结构特性)
如果你的表单结构里,只有错误提示元素带有id(其他兄弟元素比如label没有id),那可以这么写:
/* 默认隐藏所有带id的input兄弟元素(也就是错误提示) */ input ~ [id] { display: none; } /* 当input被用户输入且验证无效时,显示对应的兄弟错误提示 */ input:user-invalid ~ [id] { display: inline-flex; }
要是想更严谨,避免误判其他带id的兄弟元素,你可以直接指定错误提示的标签类型(比如你的是p标签):
input ~ p[id] { display: none; } input:user-invalid ~ p[id] { display: inline-flex; }
更健壮的方案(推荐)
如果担心后续结构变化,比如新增了其他带id的兄弟元素,那最好给错误提示加个专属类名(比如error-message),这样选择器的精准度会高很多,也不容易出问题:
<!-- 先给错误提示加个类 --> <div role="group" class="form-field"> <label for="email">Email</label> <input type="email" name="email" aria-errormessage="error-message" aria-invalid="true" /> <p id="error-message" class="error-message">Invalid email</p> </div>
对应的CSS:
/* 默认隐藏错误提示 */ .error-message { display: none; color: #dc2626; /* 加个红色更直观 */ } /* 只有用户交互后输入无效时才显示 */ input:user-invalid ~ .error-message { display: inline-flex; }
情况2:你必须通过aria-errormessage的属性值关联(不依赖结构)
这里得说实话:纯原生CSS目前做不到直接“读取input的aria-errormessage值,自动匹配对应id的元素”,因为CSS选择器是静态解析的,不支持跨元素的动态属性值引用。
如果一定要这种强关联,那只能借助一点点JS来辅助:比如监听input的状态变化,拿到它的aria-errormessage值,然后给对应id的元素加/移除类名来控制显示隐藏,但这就不是纯CSS方案了。
另外补充个小知识点::user-invalid比:invalid更友好,它只会在用户和输入框交互过(比如聚焦后失焦)才触发,不会在页面刚加载时就显示错误提示,用户体验更好。
给你个完整的可运行示例,结合你的原始HTML结构:
<div role="group" class="form-field"> <label for="email">Email</label> <input type="email" name="email" aria-errormessage="error-message" aria-invalid="true" /> <p id="error-message">Invalid email</p> </div>
input ~ p[id] { display: none; color: #dc2626; } input:user-invalid ~ p[id] { display: inline-flex; }
这样就能实现你要的效果:默认错误提示隐藏,用户输入无效内容后,错误提示自动显示。
内容来源于stack exchange

