> ## Content Index
> Fetch the complete content index at: https://blog.hinablue.me/llms.txt
> Use this file to discover other available public pages before exploring further.

# [VueJS] Style scoped 的問題與 Hack
- URL: https://blog.hinablue.me/vuejs-style-scoped-de-wen-ti-yu-hack/
- Published: 2016-08-25T05:14:59.000Z
- Updated: 2026-07-06T18:50:42.000Z
- Author: Hina Chen

身為 Vue (X) 眼藥水 (O) 的初學者，偶爾送送 PR 也是很合理的。

---

Vue-loader 提供了樣式、樣版的組合功能，基本上沒什麼好詬病的地方。但是，科技始終來自於惰性（無誤，所以，有些地方還是覺得不太夠用。

## Why `scoped`

通常我們自己撰寫元件時，有的時候不希望樣式放在全域中被使用，只希望在這個元件（或是其子元件內發生，這個時候，就會在樣式加入 `scoped` 來確保樣式只會在子元件被渲染。

好處是樣式維護上比較不會那麼複雜，也不會發生樣式互相蓋版的問題。

壞處是，樣式好像比較不好維護（欸

## Style scoped 問題

通常我們寫一個 `Vue` 會用到一些子元件，例如這樣，

```html
<template>
  <div class="parent-component">
    <h1>我是老爸</h1>
    <child-component></child-component>
  </div>
</template>

<style scoped>
// 我是老爸，我兒子的 h1 要紅色
.parent-component .child-component h1 {
  color: red;
}
</style>

```

子元件例如這樣，

```html
<template>
  <div class="child-component">
    <h1>我是兒子</h1>
  </div>
</template>

<style>
// 我是兒子，我的 h1 是藍色
.child-component h1 {
  color: blue;
}
</style>

```

然後，你會發現，老爸這樣的寫法，無法干涉兒子的 `h1` 的顏色，基於 `vue-loader` 當中 `style-rewrite` 的作法，**老爸** 最終樣式輸出的結果會是，

```css
.parent-component .child-component h1[_v-d5346ea8] {
  color: red;
}

```

而 **兒子** 的樣式輸出結果會是，

```css
.child-component h1 {
  color: blue;
}

```

根據 CSS 選擇器原則，**老爸** 的規則在 **兒子** 的 DOM Tree 當中並不符合規則，所以無論 **老爸** 怎麼改，基本上對於 **兒子** 的樣式是無法改變的。

## Style scoped Hack

所以，我們換個方式想，**只要老爸的樣式規則，符合兒子的 DOM Tree 即可**，所以，理想的狀態下，我們只要這樣輸出，就能干涉 **兒子** 的顯示樣式，

```css
.parent-component[_v-d5346ea8] .child-component h1 {
  color: red;
}

```

所以，只需要把 `scope id` 寫在 **老爸** 的樣式後方，而不是統一加在所有選擇器的最後面，就能解決這樣的問題。

> 所以我送了一個 PR 給 vue-loader
> 
> [https://github.com/vuejs/vue-loader/pull/323](https://github.com/vuejs/vue-loader/pull/323?ref=blog.hinablue.me)

基本上的寫法就是，

```html
<style scoped>
// 我是老爸，我兒子的 h1 要紅色，兒子就要是紅色
.parent-component[scoped] .child-component h1 {
  color: red;
}

div[scoped] .images[scoped] {
  // 只要加上 scoped 就會被替換成正確的 scope id
  max-width: 100%;
}
</style>

```

只要在任何一個選擇器後方，加上 `[scoped]` 這樣的屬性選擇器，就能渲染出符合我們需要的樣式規則，

```css
.parent-component[_v-d5346ea8] .child-component h1 {
  color: red;
}
div[_v-d5346ea8] .images[_v-d5346ea8] {
  max-width: 100%;
}

```

這樣一來，只要 **CSS 權重** 正確，就能夠覆蓋子元件的樣式表，對於使用了第三方元件的人來說，永遠只能使用 Global CSS 來改寫樣式這樣的情況應該可以完全消失。

只要計算 DOM Tree 跟 CSS 權重，就能對第三方元件的樣式進行覆蓋，即便你的元件使用了 `scoped` 屬性，也依然能正常覆蓋。

## 小結

這需求只是自己爽所以改了一下（欸