Why Vue 3 Deprecates /deep/ and >>> and How :deep() Really Works
This article explains the problems of using deprecated deep combinators in Vue scoped CSS, shows concrete code examples, walks through the Vue compiler’s AST transformation, demonstrates the correct :deep() syntax, and proves that nested :deep selectors are not supported.
When a scoped style needs to modify a third‑party component, developers traditionally rely on deep combinators such as /deep/ or >>>. Adding rules outside the scoped block works but pollutes the global stylesheet and can cause conflicts later.
Deprecated combinators
Without deep:
<style lang="less">
.container {
.el-button {
background: #777;
}
}Using /deep/ (deprecated):
.container1 {
/deep/ .el-button {
background: #000;
}
}Using >>> (deprecated):
.container2 >>> .el-button {
background: #222;
}In Vue 3, the console prints the warning:
the >>> and /deep/ combinators have been deprecated. Use :deep() instead.The deprecation is due to compatibility problems in Less/SCSS and the desire for a unified syntax.
Correct syntax with :deep
Typical usage:
.container3 {
:deep(.el-button) {
background: #444;
}
}Developers often wonder whether nesting :deep works:
.container4 {
:deep(.el-button) {
:deep(.el-icon) {
color: #f00;
}
}
}How the compiler transforms /deep/ and >>>
The compiled CSS becomes:
.no-deep .container1[data-v-f5dea59b] .el-button { background: #000; }The relevant source snippet shows the AST node handling:
if (n.type === 'combinator' && (n.value === '>>>' || n.value === '/deep/')) {
n.value = ' '
n.spaces.before = n.spaces.after = ''
warn('the >>> and /deep/ combinators have been deprecated. Use :deep() instead.')
return false
}During style compilation, Vue parses selectors into an AST. For a selector like /deep/ .el-button, the parser creates a node { type: 'combinator', value: '/deep/' }. The compiler then replaces the combinator with a space, effectively moving the child selector under the parent component’s scoped attribute.
How the compiler transforms :deep
The resulting CSS for the earlier :deep example is:
.no-deep .container3[data-v-f5dea59b] .el-button { background: #444; }The transformation code inserts a space combinator when needed, removes the original :deep node, and rewrites the selector:
let last = n;
selector.insertAfter(last, ss);
last = ss;
// ensure a space before the next selector if missing
if (!prev || !isSpaceCombinator(prev)) {
selector.insertAfter(n, selectorParser.combinator({ value: ' ' }));
}
selector.removeChild(n);When nesting :deep, the compiler cannot find an ancestor for the inner selector, so the inner :deep remains unchanged. The final CSS for the nested example is:
.no-deep .container4[data-v-f5dea59b] .el-button :deep(.el-icon) { color: #f00; }Thus, Vue does not support nested :deep selectors; the inner selector is emitted as‑is, leading to unexpected output.
References
https://github.com/cnmapos/react-native-mapa
https://github.com/cnmapos/mapboxgl-syncto-any
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Rare Earth Juejin Tech Community
Juejin, a tech community that helps developers grow.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
