커스텀 테마
커스텀 테마 (Custom theme)
출처: 문서
본문
Element Plus는 BEM 스타일의 CSS를 사용해서 스타일을 쉽게 오버라이드할 수 있어요. 하지만 테마 색상을 파란색에서 오렌지나 초록으로 바꾸는 것처럼 스타일을 대규모로 교체해야 한다면, 하나씩 오버라이드하는 건 좋은 방법이 아니겠죠. 스타일 변수를 바꾸는 방법 네 가지를 제공해요.
테마 색상 바꾸기
커스텀 테마에 대한 예시들이에요.
- 전체 import: element-plus-vite-starter
- 온디맨드: unplugin-element-plus/examples/vite
SCSS 변수로
theme-chalk는 SCSS로 작성되어 있어요. SCSS 변수는 packages/theme-chalk/src/common/var.scss에서 찾을 수 있습니다.
WARNING sass 모듈(
sass:map...)과@use를 사용해 모든 SCSS 변수를 리팩터링했어요. 모든 SCSS 변수에@use를 쓰면@import에서 생기던 중복 출력 문제가 해결돼요. 자세한 내용은 Sass Modules 글을 참고하세요.
예를 들어 $colors는 서로 다른 타입의 색상을 보관하는 map으로 사용돼요. $notification은 notification 컴포넌트의 모든 변수를 담은 map이죠. 앞으로 각 컴포넌트에서 커스터마이즈할 수 있는 변수에 대한 문서도 작성할 예정이에요. 지금은 소스 var.scss를 직접 확인해도 됩니다.
$colors: () !default;
$colors: map.deep-merge(
(
'white': #ffffff,
'black': #000000,
'primary': (
'base': #409eff,
),
'success': (
'base': #67c23a,
),
'warning': (
'base': #e6a23c,
),
'danger': (
'base': #f56c6c,
),
'error': (
'base': #f56c6c,
),
'info': (
'base': #909399,
),
),
$colors
);
어떻게 오버라이드할까요?
프로젝트도 SCSS를 사용한다면 Element Plus 스타일 변수를 직접 바꿀 수 있어요. 새 스타일 파일(예: styles/element/index.scss)을 만듭니다.
WARNING
@import 'xxx.scss';대신@use 'xxx.scss' as *;를 사용해야 해요. sass 팀이 결국@import를 제거할 예정이기 때문이에요. 관련 글: Sass: @use vs Sass: @import
styles/element/index.scss
/* just override what you need */
@forward 'element-plus/theme-chalk/src/common/var.scss' with (
$colors: (
'primary': (
'base': green,
),
)
);
// If you just import on demand, you can ignore the following content.
// if you want to import all styles:
// @use "element-plus/theme-chalk/src/index.scss" as *;
그다음 프로젝트의 엔트리 파일에서 Element의 내장 CSS 대신 이 스타일 파일을 import 해요.
TIP 내 커스텀 변수로 light-x를 생성해야 하므로, sass 변수 혼합 문제를 피하려면
element/index.scss를 element-plus의 scss보다 먼저 import 하세요.
element/index.scss를 만들어 내 변수와 element-plus의 변수를 결합해요. (ts에서 import 하면 결합되지 않아요.)
TIP 또 하나, 내 scss와 element 변수 scss를 분리해야 해요. 섞여 있으면 element-plus의 핫 리로드마다 수많은 scss 파일을 컴파일해야 해서 느려지거든요.
main.ts
import { createApp } from 'vue'
import './styles/element/index.scss'
import ElementPlus from 'element-plus'
import App from './App.vue'
const app = createApp(App)
app.use(ElementPlus)
vite를 쓰면서 온디맨드 import 시 커스텀 테마를 적용하고 싶다면, scss.additionalData를 사용해 매 컴포넌트의 scss와 함께 변수를 컴파일하면 돼요.
vite.config.ts
import path from 'path'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// You can also use unplugin-vue-components
// import Components from 'unplugin-vue-components/vite'
// import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
// or use unplugin-element-plus
import ElementPlus from 'unplugin-element-plus/vite'
export default defineConfig({
resolve: {
alias: {
'~/': `${path.resolve(__dirname, 'src')}/`,
},
},
css: {
preprocessorOptions: {
scss: {
additionalData: `@use "~/styles/element/index.scss" as *;`,
},
},
},
plugins: [
vue(),
// use unplugin-vue-components
// Components({
// resolvers: [
// ElementPlusResolver({
// importStyle: "sass",
// // directives: true,
// // version: "2.1.5",
// }),
// ],
// }),
// or use unplugin-element-plus
ElementPlus({
useSource: true,
}),
],
})
webpack을 쓰면서 온디맨드 import 시 커스텀 테마를 적용하고 싶다면 이렇게 하세요.
webpack.config.js
// use unplugin-element-plus
import ElementPlus from 'unplugin-element-plus/webpack'
export default defineConfig({
css: {
loaderOptions: {
scss: {
additionalData: `@use "~/styles/element/index.scss" as *;`,
},
},
},
plugins: [
ElementPlus({
useSource: true,
}),
],
})
CSS 변수로 (By CSS Variable)
CSS Variables는 아주 유용한 기능으로, 거의 모든 브라우저에서 지원돼요. 거의 모든 컴포넌트의 스타일 시스템을 css 변수로 재구성했답니다.
TIP SCSS 변수 시스템과 호환돼요. SCSS의 기능으로 css 변수를 자동 생성해서 쓰기 때문이에요.
이 말은 scss를 수정하고 다시 컴파일하지 않아도 컴포넌트 내부의 개별 변수를 동적으로 변경해 더 잘 커스터마이즈할 수 있다는 뜻이에요. 앞으로 각 컴포넌트의 css 변수 이름과 역할 문서도 각 컴포넌트에 작성할 예정이에요. 이렇게 씁니다:
:root {
--el-color-primary: green;
}
특정 컴포넌트만 커스터마이즈하고 싶다면 해당 컴포넌트에 인라인 스타일을 추가하면 돼요.
<el-tag style="--el-tag-bg-color: red">Tag</el-tag>
성능 때문에 전역 :root보다는 클래스 아래에서 css 변수를 커스터마이즈하는 걸 더 권장해요.
.custom-class {
--el-tag-bg-color: red;
}
스크립트로 css 변수를 제어하고 싶다면 이렇게 해 보세요.
// document.documentElement is global
const el = document.documentElement
// const el = document.getElementById('xxx')
// get css var
getComputedStyle(el).getPropertyValue(`--el-color-primary`)
// set css var
el.style['--el-color-primary'] = 'red'
더 우아한 방법을 원한다면 VueUse의 useCssVar를 확인해 보세요.