[Vue3]なんとしても今書いているcssを優先させる

VueでUIライブラリを使っていると今作業しているvueファイルではないところでcssファイルを読み込んでいて、今書いているcssの適用されないことがある。

Cacading Style Sheetsと言う名前に反することにはなるが、そんな時に個人的に使っている方法を何個か挙げてみようと思う。

## 結論
1. `<style scope></style>`の中に書く
2. `!important`をつける
3. Vanilla JSの書き方で当てる

## 環境
UIライブラリは`Element Plus`を使っている。
`vuetify`みたいなもので使いやすい。

https://element-plus.org/en-US/
```json:package.json
{
    "vue": "^3.4.21",
    "sass": "^1.76.0",
    "element-plus": "^2.7.2",
}
```

## cssが適用されない時
![スクリーンショット 2024-05-26 22.32.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754242/39d63a52-e3e7-fb33-1aa2-3acf809f8f26.png)

今回はElement Plusのselectを例にしてみた。
デザインは白黒を中心にしているため、Element Plusのデフォルト色である青が気になる。

上記画面のコード
```vue
<template>
  <div class="update-container">
    <div>
      <el-select v-model="selectedCategory" placeholder="select">
        <el-option 
          v-for="(category, index) in categories"         
          :key="category.id"
          :label="category.name"
          :value="category"
        />
      </el-select>
      <input type="file" @change="uploadPhoto($event)" accept="image/*" />
      <div v-if="uploading">Uploading...</div>
      <div v-if="uploadError">{{ uploadError }}</div>
    </div>
  </div>
</template>
<style lang="scss" scoped>
.update-container {
  margin-top: 80px;
}
</style>
```

デベロッパーツールで見ると下画像のような構造になっている。

![スクリーンショット 2024-05-26 22.38.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754242/16b7834c-1d6d-dca5-8b30-2d8bd5302dc0.png)

今回は`span`を黒にしてみたい。クラス名を当ててcssを書いてみる。

```vue
<style lang="scss" scoped>
.update-container {
  margin-top: 80px;
}
.el-select-dropdown__item {
  span {
    color: black;
  }
}
</style>
```

変化なし。

![スクリーンショット 2024-05-26 22.42.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754242/62e72eef-3e6f-989d-b747-c63f42d47a60.png)

## 方法１scopeに書く
### コード
```vue
<style lang="scss" scoped>
.update-container {
  margin-top: 80px;
}
</style>
<style lang="scss" scope>
.el-select-dropdown__item {
  span {
    color: black;
  }
}
</style>
```
変わった！

![スクリーンショット 2024-05-26 22.45.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754242/01853acb-62fb-c6e4-f18f-fe7b2bf4ebce.png)

### 問題点
普段は他のコンポーネントに影響を与えないため`scoped`を使っている。

https://vue-loader-v14.vuejs.org/ja/features/scoped-css.html

しかし、今回のように他のコンポーネントでも使われる可能性のあるクラス名でコードを書いていくと後でこのファイルに戻って処理する必要が出てくる。

そのため、scssを使っているなら親要素にクラス名を当ててあげると少し安全になる。
同じクラス名の使われる可能性があるため、完全回避はできないが...
```vue
<style lang="scss" scope>
.update-container { // 親要素のクラスを当てる
  .el-select-dropdown__item {
    span {
      color: black;
    }
  }
}
</style>
```

## 方法２ `!important`を使う
今回はscopeの中に書くことで解決できたが、同じファイル内で同じUIコンポーネントを使っていて、どうしても今作業している方を優先したい時がある。

そんな時は`!important`を使うとできる。

```vue
<style lang="scss" scope>
.update-container { // 親要素のクラスを当てる
  .el-select-dropdown__item {
    span {
      color: black !important;
    }
  }
}
</style>
```

## 方法３ Vanilla JSの書き方で当てる
やはり純正が一番効く。

しかし仮想DOMを使っているvueで直接この作業をすることが正しいかはわからない。
特に、`onUpdated`の中じゃないと上手く操作できない時がある（できる時もある）

ここはもっとライフサイクルの勉強が必要そう。

https://vuejs.org/guide/essentials/lifecycle

```vue
<script setup lang="ts">
onUpdated(() => {
    const select = document.getElementById('select');
    select.style.color = 'black';
});
</script>
```