Problem
:deep() and :slotted() pseudo-selectors don't work with vue-lynx's cssId-based scoping.
:deep() -- Vue compiles .parent :deep(.child) to .parent[data-v-xxx] .child. After stripping [data-v-xxx], the rule is inside @cssId, but the target .child element (in a child component) has a different cssId and can't see the rule.
:slotted() -- Vue compiles :slotted(.item) using a -s suffix variant [data-v-xxx-s]. This slot-context concept has no equivalent in Lynx's cssId model.
Proposed Solution: Hybrid cssId + class-hash approach
Use native @cssId for the fast path (regular scoped styles) and fall back to class-based hash selectors for :deep() / :slotted() rules in the common fragment:
Build-time
For :deep() / :slotted() rules:
- Transform
[data-v-xxx] attribute selectors to .v-xxx class selectors (Lynx supports class selectors)
- Route these rules to the common CSS fragment (no
@cssId wrapping)
Vue compiler: .parent[data-v-8f634878] .child { color: red; }
↓ transform [data-v-xxx] → .v-xxx
Our output: .parent.v-8f634878 .child { color: red; }
→ placed in common fragment (visible to all elements)
Runtime
setScopeId() adds a hash class in addition to calling __SetCSSId:
setScopeId(el, id) {
pushOp(OP.SET_SCOPE_ID, el.id, scopeIdToCssId(id)); // native fast path
pushOp(OP.ADD_CLASS, el.id, scopeIdToClass(id)); // "data-v-xxx" → "v-xxx"
}
Vue already calls setScopeId with -s suffix for slot content, so :slotted() would naturally get class v-xxx-s matching the transformed selector .item.v-xxx-s.
Result
| Feature |
CSS location |
Selector |
Scoped by |
| Regular scoped |
@cssId "N" { .foo {} } |
.foo |
Native cssId (fast) |
:deep() |
common fragment |
.parent.v-xxx .child |
Class hash |
:slotted() |
common fragment |
.item.v-xxx-s |
Class hash |
No engine changes required. The engine's CSS fragment dependency system already handles common fragment imports.
Related
Problem
:deep()and:slotted()pseudo-selectors don't work with vue-lynx's cssId-based scoping.:deep()-- Vue compiles.parent :deep(.child)to.parent[data-v-xxx] .child. After stripping[data-v-xxx], the rule is inside@cssId, but the target.childelement (in a child component) has a different cssId and can't see the rule.:slotted()-- Vue compiles:slotted(.item)using a-ssuffix variant[data-v-xxx-s]. This slot-context concept has no equivalent in Lynx's cssId model.Proposed Solution: Hybrid cssId + class-hash approach
Use native
@cssIdfor the fast path (regular scoped styles) and fall back to class-based hash selectors for:deep()/:slotted()rules in the common fragment:Build-time
For
:deep()/:slotted()rules:[data-v-xxx]attribute selectors to.v-xxxclass selectors (Lynx supports class selectors)@cssIdwrapping)Runtime
setScopeId()adds a hash class in addition to calling__SetCSSId:Vue already calls
setScopeIdwith-ssuffix for slot content, so:slotted()would naturally get classv-xxx-smatching the transformed selector.item.v-xxx-s.Result
@cssId "N" { .foo {} }.foo:deep().parent.v-xxx .child:slotted().item.v-xxx-sNo engine changes required. The engine's CSS fragment dependency system already handles common fragment imports.
Related
<style scoped>support (Support<style scoped>in Vue SFCs #78):global()support tracked separately in feat(scoped-css): support:global()inside<style scoped>#164<style scoped>in Vue SFCs #151 documents these as known limitations