Chromium系浏览器中::part()与其他选择器链式失效的替代方案咨询
问题描述
尝试将:disabled、:not([disabled])和/或:not([aria-label=''])与::part()链式使用时,在Chrome、Edge这类Chromium系浏览器中无法生效,而客户仅使用这两款浏览器。需要匹配Shadow Root中同时拥有part属性和disabled(或明确未禁用)属性的元素,比如:
<td role="gridcell" part="date" tabindex="-1" aria-label="1 Czerwiec 2024, sobota">1</td>
示例中,禁用状态的按钮本应通过.app-1::part(button-1):disabled将文本设为橙色,但该选择器无效;而.app-1::part(label-1):hover能正常作用于标签:
let template = document.querySelector('.temp-1').innerHTML; let shadowElement = document.querySelector('.app-1'); let shadow = shadowElement.attachShadow({ mode: 'open' }); shadow.innerHTML = template;
<template class="temp-1"> <div part="label-1"> Label encapsulated in Shadow DOM </div> <button part="button-1" disabled> Click me! </button> </template> <style> .app-1 { color: green; background-color: lightblue; } .app-1::part(label-1):hover { color: orange; } .app-1::part(button-1) { color: lime; } .app-1::part(button-1):disabled { color: orange; } </style> <div class="app-1"></div>
替代方案
1. Shadow DOM内部编写状态样式
直接在Shadow Root内部的样式中针对元素状态编写规则,完全规避外部选择器的兼容性问题,这也是最符合Shadow DOM封装逻辑的方案:
<template class="temp-1"> <style> [part="button-1"]:disabled { color: orange; } </style> <div part="label-1"> Label encapsulated in Shadow DOM </div> <button part="button-1" disabled> Click me! </button> </template>
2. 给元素添加带状态的part名称
如果必须从外部控制样式,可以给元素设置包含状态信息的part属性(支持多值),然后在外部通过组合part名称选择:
<template class="temp-1"> <div part="label-1"> Label encapsulated in Shadow DOM </div> <button part="button-1 disabled" disabled> Click me! </button> </template> <style> .app-1::part(button-1 disabled) { color: orange; } </style>
若状态是动态变化的,需用JS监听状态变更并更新part属性:
const button = shadow.querySelector('[part="button-1"]'); // 监听禁用状态变化(示例逻辑,可根据实际场景调整) button.addEventListener('disabledchange', () => { button.part.toggle('disabled', button.disabled); });
3. 利用宿主元素状态传递样式
如果自定义元素本身带有disabled属性,可以通过:host()伪类在Shadow内部关联元素样式,同时保留part属性供外部扩展:
<template class="temp-1"> <style> :host(:disabled) [part="button-1"] { color: orange; } </style> <div part="label-1"> Label encapsulated in Shadow DOM </div> <button part="button-1" disabled> Click me! </button> </template>
然后给宿主元素.app-1添加disabled属性,即可触发内部样式生效。
内容的提问来源于stack exchange,提问作者Arkadiusz Górecki
相关产品推荐
相关产品推荐

