自定义组件样式全面解析
🎯 引言
学会这篇文章后,你将能够灵活地定制 Element UI 组件的样式,让你的前端界面更符合设计需求和用户体验。文章不仅涵盖重写样式的方法,还会详细介绍如何解决常见的样式穿透和作用域限制问题,并结合 Input、Button、Dialog 等常用组件实例,帮助你快速上手。
🎨 自定义组件样式
✨ 如何重写 Element UI 样式
Element UI 作为一套成熟的 Vue 2.0 UI 框架,提供了丰富的组件和默认样式,但很多时候我们需要根据业务需求,修改组件的样式。这里介绍几种常见的重写样式方法:
1. scoped 限制
Vue 组件中使用 <style scoped> 可以让样式只作用于当前组件的模板,防止样式污染其他组件。但这也会限制我们对 Element UI 组件内部深层元素的样式修改。
举个例子,如果你想修改一个 Element UI 组件内部的样式,直接在 scoped 样式里写选择器是不会生效的,因为样式被限制在当前组件的根元素范围内。
2. deep 深度选择
为了突破 scoped 限制,Vue 2.0 提供了 :deep 深度选择符,它们可以穿透样式作用域,直接修改子组件或第三方库内部的样式。
示例:
<template>
<el-button>按钮</el-button>
</template>
<style scoped>
:deep(.el-button) {
background-color: #409eff;
color: white;
}
</style>
使用 :deep 可以让样式生效到 .el-button 这个 Element UI 组件的内部元素。
3. class 穿透技巧
除了深度选择器,另一个常用的做法是给组件外层添加自定义 class,然后利用更高权重的选择器来覆盖默认样式。
示例:
<template>
<div class="custom-button">
<el-button>按钮</el-button>
</div>
</template>
<style scoped>
.custom-button >>> .el-button {
border-radius: 20px;
}
</style>
这种方式更灵活,尤其是在复杂页面中,可以避免样式冲突。
4. 全局样式
如果需要修改大量或公共的 Element UI 样式,可以直接在项目的全局样式文件(比如 main.css 或 App.vue 的无 scoped 样式里)进行覆盖。这样不会有 scoped 限制,但要注意选择器的优先级。
.el-button {
font-weight: bold;
}
⚠️ 重写样式注意事项
弹窗、抽屉等组件挂载在 body,为何样式改不动?
Element UI 的弹窗(el-dialog)、抽屉(el-drawer)等组件,默认通过 append-to-body 属性将组件挂载到 body 中,而不是当前组件的 DOM 树内。这带来两个影响:
- 组件的 DOM 元素不在父组件作用域内,
scoped样式无法穿透到弹窗内部。 - 使用
>>>:deep等穿透符号也失效,因为样式作用于当前组件的 DOM 树,弹窗 DOM 在 body 外。
解决方案:
- 使用全局样式文件修改弹窗样式。
- 给弹窗组件添加自定义 class,再在全局样式中写对应样式。
示例:
<el-dialog title="示例弹窗" :visible.sync="dialogVisible" custom-class="custom-dialog">
<p>弹窗内容</p>
</el-dialog>
.custom-dialog .el-dialog__header {
background-color: #f56c6c;
color: white;
}
🎯 重写常用组件样式案例
🔍 自定义 Input 样式(高度、边框、颜色)
Element UI 的 <el-input> 默认样式比较基础,我们可以通过深度选择或全局样式来定制高度、边框颜色等。
示例代码:
<template>
<el-input placeholder="请输入内容" v-model="inputValue" />
</template>
<script>
export default {
data() {
return {
inputValue: '',
};
},
};
</script>
<style lang="scss" scoped>
.el-input {
:deep(.el-input__inner) {
padding: 0 20px;
color: red;
border: 1px solid blue;
background-color: transparent;
border-radius: 0;
height: 30px;
line-height: 30px;
}
}
</style>
🎨 自定义 Button 样式
按钮的悬浮和禁用状态是 UI 交互的重要体现,重写这部分样式可以让按钮更具品牌特色。
示例:
<template>
<el-button>点击我</el-button>
</template>
<style lang="scss" scoped>
.el-button {
width: 120px;
height: 40px;
padding: 0;
background: #f0f9ff;
border: 1px solid #c6e2ff;
color: #409eff;
font-size: 12px;
border-radius: 6px;
}
</style>
🖼️ 自定义 Dialog 样式(边距、宽度)
Dialog 弹窗是常用的交互组件,调整宽度和边距能够更好地适配不同页面布局。
示例:
<template>
<el-dialog title="自定义弹窗" :visible.sync="dialogVisible" custom-class="custom-dialog">
<p>弹窗内容示例</p>
</el-dialog>
</template>
<script>
export default {
data() {
return {
dialogVisible: true,
};
},
};
</script>
<style lang="scss">
body {
.custom-dialog {
width: 600px;
.el-dialog__header {
background-color: #f5f7fa;
}
.el-dialog__body {
padding: 20px;
}
}
}
</style>
custom-dialog 避免全局污染。🧾 小结
- Element UI 样式被 scoped 限制时,使用
/deep/选择器可以穿透子组件样式。 - 弹窗类组件因挂载在 body,需要通过全局样式和
custom-class属性来自定义样式。 - 自定义组件样式时,结合 class 穿透和全局样式,灵活调整元素高度、颜色和状态样式。
❓ 知识问答(Q&A)
Q:为什么直接在 scoped 样式里写 Element UI 组件选择器不生效?
A:因为 scoped 样式只作用于当前组件的 DOM 范围内,无法影响子组件的深层元素,需用 /deep/ 穿透或写全局样式。
Q:如何修改 Element UI 弹窗组件的宽度和边距?
A:给弹窗添加 custom-class,在全局样式中使用更高优先级选择器(通常需 !important)来覆盖默认样式。
🧪 小练习
练习 1
自定义 el-select 组件的下拉框样式,改变背景色和字体颜色。
<template>
<el-select v-model="value" placeholder="请选择" class="custom-select">
<el-option label="选项1" value="1" />
<el-option label="选项2" value="2" />
</el-select>
</template>
<script>
export default {
data() {
return {
value: '',
};
},
};
</script>
<style lang="scss" scoped>
/* 在这里写你的样式 */
</style>
练习 2
自定义 el-checkbox 组件的勾选框颜色和大小。
<template>
<el-checkbox v-model="checked" class="custom-checkbox">勾选我</el-checkbox>
</template>
<script>
export default {
data() {
return {
checked: false,
};
},
};
</script>
<style lang="scss" scoped>
/* 在这里写你的样式 */
</style>
🎉 恭喜你已经掌握 Element UI 组件样式重写、样式穿透技巧及自定义常用组件样式的技能啦!
