Skip to content

feat(scoped-css): support :deep() and :slotted() in <style scoped> #165

@Huxpro

Description

@Huxpro

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:

  1. Transform [data-v-xxx] attribute selectors to .v-xxx class selectors (Lynx supports class selectors)
  2. 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions