VuReact is a compiler toolchain for migrating from Vue to React — and for writing React with Vue 3 syntax. In this article, we will look at how Vue SFC <style scoped> blocks are compiled into React code.
Before We Start
To keep the examples easy to read, this article follows two simple conventions:
- All Vue and React snippets focus on core logic only, with full component wrappers and unrelated configuration omitted.
- The discussion assumes you are already familiar with scoped styles in Vue 3 SFCs.
Compilation Mapping
Scoped style conversion
VuReact compiles scoped styles into CSS that carries a scope identifier, then injects the corresponding data-css-{hash} attribute into matching DOM elements.
- Vue
<!-- Counter.vue -->
<template>
<div class="card">
<p>Header</p>
<p class="content">Content</p>
</div>
<button>Submit</button>
</template>
<style scoped>
.card {
border: 1px solid #e5e5e5;
border-radius: 8px;
}
.card:hover {
background: #2a8c5e;
}
.content {
font-size: 12px;
}
</style>
- Compiled React
// Counter.jsx
import './counter-abc1234.css';
function Counter() {
return (
<div className="card" data-css-abc1234>
<p data-css-abc1234>Header</p>
<p className="content" data-css-abc1234>Content</p>
</div>
<button data-css-abc1234>Submit</button>
);
}
/* counter-abc1234.css */
.card[data-css-abc1234] {
border: 1px solid #e5e5e5;
border-radius: 8px;
}
.card[data-css-abc1234]:hover {
background: #2a8c5e;
}
.content[data-css-abc1234] {
font-size: 12px;
}
As the example shows, Vue <style scoped> blocks are compiled into CSS files with scope markers, and React DOM elements receive the matching data-css-{hash} attribute.
Scoped attribute rules
The scope attribute is not applied to every selector in the same way. Vue's scoped-style exceptions are preserved through these compilation rules:
- Template elements do not receive scoped attributes.
- Slot content does not receive scoped attributes.
Scope isolation principles
- CSS selector rewriting:
.cardbecomes.card[data-css-hash]. - DOM attribute injection: matching elements receive the
data-css-hashattribute. - Style isolation: styles apply only to elements that share the same scope marker.
- Collision prevention: component styles remain isolated from each other.
Compilation summary
VuReact's scoped-style compilation shows a complete scoped selector transformation pipeline:
-
:global()is unwrapped and emitted as global CSS. -
:deep()is split so the left side keeps the scope marker while the inner selector remains penetrative. -
:slotted()is simplified, with full semantic handling still in progress. - Pseudo selectors such as
:hover,::before, and:not()are preserved with scope added before the pseudo selector. - Nested selectors work naturally with SCSS/Less-style nesting syntax.
Supported penetrative selectors:
| Selector | Status | Notes |
|---|---|---|
:deep() |
Supported | Scoped on the left, penetrative on the right |
:global() |
Supported | Emits global CSS without scope wrapping |
:slotted() |
Partial | De-structuring handled, full semantics still evolving |
VuReact keeps Vue's scoped-style isolation semantics while still allowing flexible penetrative selectors where needed.
Top comments (0)