# 樣式
## [#](https://panjiachen.github.io/vue-element-admin-site/zh/guide/essentials/style.html#css-modules)CSS Modules
在樣式開發過程中,有兩個問題比較突出:
* 全局污染 —— CSS 文件中的選擇器是全局生效的,不同文件中的同名選擇器,根據 build 后生成文件中的先后順序,后面的樣式會將前面的覆蓋;
* 選擇器復雜 —— 為了避免上面的問題,我們在編寫樣式的時候不得不小心翼翼,類名里會帶上限制范圍的標示,變得越來越長,多人開發時還很容易導致命名風格混亂,一個元素上使用的選擇器個數也可能越來越多,最終導致難以維護。
好在 vue 為我們提供了[scoped](https://vue-loader.vuejs.org/guide/scoped-css.html#mixing-local-and-global-styles)可以很方便的解決上述問題。 它顧名思義給 css 加了一個域的概念。
~~~
/* 編譯前 */
.example {
color: red;
}
/* 編譯后 */
.example[_v-f3f3eg9] {
color: red;
}
~~~
只要加上`<style scoped>`這樣 css 就只會作用在當前組件內了。詳細文檔見[vue-loader](https://vue-loader.vuejs.org/guide/scoped-css.html#mixing-local-and-global-styles)
> ## TIP
>
> 使用 scoped 后,父組件的樣式將不會滲透到子組件中。不過一個子組件的根節點會同時受其父組件的 scoped CSS 和子組件的 scoped CSS 的影響。這樣設計是為了讓父組件可以從布局的角度出發,調整其子組件根元素的樣式。
## [#](https://panjiachen.github.io/vue-element-admin-site/zh/guide/essentials/style.html#%E7%9B%AE%E5%BD%95%E7%BB%93%E6%9E%84)目錄結構
vue-element-admin 所有全局樣式都在`@/src/styles`目錄下設置
~~~
├── styles
│ ├── btn.scss # 按鈕樣式
│ ├── element-ui.scss # 全局自定義 element-ui 樣式
│ ├── index.scss # 全局通用樣式
│ ├── mixin.scss # 全局mixin
│ ├── sidebar.scss # sidebar css
│ ├── transition.scss # vue transition 動畫
│ └── variables.scss # 全局變量
~~~
常見的工作流程是,全局樣式都寫在`src/styles`目錄下,每個頁面自己對應的樣式都寫在自己的`.vue`文件之中
~~~
<style>
/* global styles */
</style>
<style scoped>
/* local styles */
</style>
~~~
## [#](https://panjiachen.github.io/vue-element-admin-site/zh/guide/essentials/style.html#%E8%87%AA%E5%AE%9A%E4%B9%89-element-ui-%E6%A0%B7%E5%BC%8F)自定義 element-ui 樣式
現在我們來說說怎么覆蓋 element-ui 樣式。由于 element-ui 的樣式我們是在全局引入的,所以你想在某個頁面里面覆蓋它的樣式就不能加 scoped,但你又想只覆蓋這個頁面的 element 樣式,你就可在它的父級加一個 class,用命名空間來解決問題。
~~~
.article-page {
/* 你的命名空間 */
.el-tag {
/* element-ui 元素*/
margin-right: 0px;
}
}
~~~
**當然也可以使用深度作用選擇器 下文會介紹**
## [#](https://panjiachen.github.io/vue-element-admin-site/zh/guide/essentials/style.html#%E7%88%B6%E7%BB%84%E4%BB%B6%E6%94%B9%E5%8F%98%E5%AD%90%E7%BB%84%E4%BB%B6%E6%A0%B7%E5%BC%8F-%E6%B7%B1%E5%BA%A6%E9%80%89%E6%8B%A9%E5%99%A8)父組件改變子組件樣式 深度選擇器
當你子組件使用了`scoped`但在父組件又想修改子組件的樣式可以 通過`>>>`來實現:
~~~
<style scoped>
.a >>> .b { /* ... */ }
</style>
~~~
將會編譯成
~~~
.a[data-v-f3f3eg9] .b {
/* ... */
}
~~~
如果你使用了一些預處理的東西,如`sass`你可以通過`/deep/`來代替`>>>`實現想要的效果。
所以你想覆蓋某個特定頁面`element`的 button 的樣式,你可以這樣做:
~~~
.xxx-container >>> .el-button{
xxxx
}
~~~
[官方文檔](https://vue-loader.vuejs.org/en/features/scoped-css.html)
## [#](https://panjiachen.github.io/vue-element-admin-site/zh/guide/essentials/style.html#autoprefixer-%E6%96%B0%E7%89%88%E6%9C%AC%E5%B7%B2%E6%97%A0%E8%AF%A5%E9%97%AE%E9%A2%98)Autoprefixer \[新版本已無該問題\]
vue-cli 有一個小坑,它默認 autoprefixer 只會對通過 vue-loader 引入的樣式才會有有作用,換而言之也就是 .vue 文件里面的 css autoprefixer 才會效果。相關問題[issues/544](https://github.com/vuejs-templates/webpack/issues/544),[issues/600](https://github.com/vuejs-templates/webpack/issues/600)。解決方案也很簡單粗暴
~~~
//app.vue
<style lang="scss">
@import './styles/index.scss'; // 全局自定義的css樣式
</style>
~~~
你在 .vue 文件中引入你要的樣式就可以了,或者你可以改變 vue-cli 的文件在 css-loader 前面在加一個 postcss-loader,在前面的 issue 地址中已經給出了解決方案。不過新版本已經默認解決處理了這個問題。
## [#](https://panjiachen.github.io/vue-element-admin-site/zh/guide/essentials/style.html#postcss)Postcss
這里再來說一下 postcss 的配置問題,新版的[vue-cli webpack 模板](https://github.com/vuejs-templates/webpack)init 之后根目錄下默認有一個`postcss.config.js`。vue-loader 的 postcss 會默認讀取這個文件的里的配置項,所以在這里直接改配置文件就可以了。配置和[postcss](https://github.com/postcss/postcss)是一樣的。
~~~
// postcss.config.js
module.exports = {
plugins: {
autoprefixer: {}
}
}
// package.json
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
]
~~~
如上面代碼所述的,autoprefixer 會去讀取 package.json 下 browserslist 的配置參數
* `> 1%`兼容全球使用率大于 1%的瀏覽器
* `last 2 versions`兼容每個瀏覽器的最近兩個版本
* `not ie <= 8`不兼容 ie8 及以下
具體可見[browserslist](https://github.com/ai/browserslist)
`postcss`也還有很多很多其它的功能大家可以[自行去探究](https://www.postcss.parts/)
## [#](https://panjiachen.github.io/vue-element-admin-site/zh/guide/essentials/style.html#mixin)Mixin
本項目沒有設置自動注入 sass 的 mixin 到全局,所以需要在使用的地方手動引入 mixin
~~~
<style rel="stylesheet/scss" lang="scss">
@import "src/styles/mixin.scss";
</style>
~~~
如需要自動將 mixin 注入到全局 ,可以使用[sass-resources-loader](https://github.com/shakacode/sass-resources-loader)