Angular Material : Theming your custom components

Theming your Angular Material app


What is theme?

Theme는 Angular Material Component에 적용될 color set이다. theming에 대한 라이브러리의 접근방법에 대해서는 Material Design Spec의 가이드를 기반으로 한다.

Angular Material에서는 여러 팔레트를 조합하여 하나의 테마를 만든다. 특히 Theme는 다음과 같이 구성된다.

  • 기본 팔레트(A primary palette): 모든 화면과 Component에서 가장 널리 사용되는 색상
  • 액센트 팔레트: 플로팅 액션 및 버튼, 그리고 인터랙티브 요소에 사용되는 색상.
  • 경고 팔레트: 오류 상태를 전달하는 데 사용되는 색상
  • 전경 팔레트: 텍스트 및 아이콘 색상
  • 배경 팔레트: 요소 배경에 사용되는 색상

Angular Material에서는 모든 테마 스타일이 빌드 타임에 정적으로 생성되므로 앱이 시작할 때 테마 스타일을 생성하는 사이클을 소비하지 않아도 된다.

빌드된(pre-built)테마 사용하기

Angular Material에는 사전 제작된 테마 CSS 파일이 준비되어있다. 이 테마 파일에는 core용 style(모든 component에 대한 공통 스타일)도 포함되므로 application에 Angular Material에대한 단일 CSS만 포함하면 된다.

@angular/material/prebuilt-themes에서 테마 파일을 애플리케이션에 직접 포함시킬 수 있다.

사용가능한 pre-built themes 목록

  • deeppurple-amber.css
  • indigo-pink.css
  • pink-bluegrey.css
  • purple-green.css

Angular CLI를 사용하는 경우 style.css 파일에 한 줄을 포함하면 된다.

@import '~@angular/material/prebuilt-themes/deeppurple-amber.css';

위 방법외에 index.html에 직접 파일을 참조하는 방식으로 적용할 수 있다.


<link href="node_modules/@angular/material/prebuilt-themes/indigo-pink.css" rel="stylesheet">

이 pre-built theme 파일과 application의 css를 결합 할 수도 있다.

마지막으로, 앱의 콘텐츠가 mat-sidenav-container요소 안에 있지않다면 wrapper요소(예를들면 <body>요소)에 mat-app-background 클래스를 추가해야한다. 이렇게 하면 테마의 배경이 페이지에 적용 될 것이다.

커스텀 테마 정의하기

사전 빌드된 테마 제공보다 더 많은 커스텀 스타일이 필요한 경우, 커스텀 테마를 정의해서 사용할 수 있다.

커스텀 테마 파일은 다음 두 가지 작업을 수행해야한다.

  1. import mat-core() sass mixin.
  • 여기에는 여러 Component가 사용하는 공통 스타일이 포함된다.
  • 이것은 application에 한번만 포함되어야 한다.
  • 이 mixin이 여러번 사용되게되면, application 곳곳에 동일한 스타일코드의 복사본으로 뒤덮일 것이다.
  1. theme 데이터 구조를 여러 팔레트의 구성으로 정의한다.
  • 이 객체는 mat-light-theme함수 또는 mat-dark-theme함수로 만들 수 있다.
  • 이 함수의 출력은 angle-material-theme mixin으로 전달되며, 이 minxin은 테마에 해당하는 모든 스타일을 출력한다.

일반적인 테마 파일은 다음과 같다.

@import '~@angular/material/theming';
// Plus imports for other components in your app.

// Include the common styles for Angular Material. We include this here so that you only
// have to load a single css file for Angular Material in your app.
// Be sure that you only ever include this mixin once!
@include mat-core();

// Define the palettes for your theme using the Material Design palettes available in palette.scss
// (imported above). For each palette, you can optionally specify a default, lighter, and darker
// hue.
$candy-app-primary: mat-palette($mat-indigo);
$candy-app-accent:  mat-palette($mat-pink, A200, A100, A400);

// The warn palette is optional (defaults to red).
$candy-app-warn:    mat-palette($mat-red);

// Create the theme object (a Sass map containing all of the palettes).
$candy-app-theme: mat-light-theme($candy-app-primary, $candy-app-accent, $candy-app-warn);

// Include theme styles for core and each component used in your app.
// Alternatively, you can import and @include the theme mixins for each component
// that you are using.
@include angular-material-theme($candy-app-theme);

이 단일 Sass 파일만 필요하다. Sass를 활용하여 나머지 앱의 스타일을 지정할 필요가 없다.

AngularCLI를 사용하는 경우

  • AngularCLI에는 Sass to css 를 컴파일하는 기능이 내장되어있다.
  • 테마파일(예: unicorn-app-theme.scss)을 가리키는 angular-cli.json의 styles 목록에 새로운 항목을 추가해주기만하면 된다.

AngularCLI를 사용하지 않는 경우

  • 기존의 Sass 툴링을 사용하여 파일을 빌드할 수 있다(예: gulp-sass or grunt-sass).
  • 가장 간단한 방법은 node-sassCLI를 사용하는 것이다.
node-sass src/unicorn-app-theme.scss dist/unicorn-app-theme.css

테마 파일을 다른 SCSS 파일로 가져올 수 없다.

  • 이렇게 하면 중복 된 스타일이 CSS에 기록된다.
  • 다른 scss 파일에서 테마 정의 객체(예: $candy-app-theme)를 사용하려면 테마 객체의 정의가 mat-coreangular-material-thememixin과 분리되어있어야한다.

테마 파일은 application의 나머지 CSS와 연결하여 축소할 수 있다.

생성된 테마 파일을 Angular Component의 styleUrls에 포함하면 해당 Component안에서 view encapsulation화된다.

Multiple themes

여러 Angular Material을 포함하여 Application에대한 여러가지 테마를 만들 수 있다. 여기서도 잊지 말아야 할 것은 @mat-coremixin은 한 번만 import해야한다는 점이다.

다음은 여러 테마를 동시에 정의해서 사용하는 예다.

@import '~@angular/material/theming';
// Plus imports for other components in your app.

// Include the common styles for Angular Material. We include this here so that you only
// have to load a single css file for Angular Material in your app.
// **Be sure that you only ever include this mixin once!**
@include mat-core();

// Define the default theme (same as the example above).
$candy-app-primary: mat-palette($mat-indigo);
$candy-app-accent:  mat-palette($mat-pink, A200, A100, A400);
$candy-app-theme:   mat-light-theme($candy-app-primary, $candy-app-accent);

// Include the default theme styles.
@include angular-material-theme($candy-app-theme);


// Define an alternate dark theme.
$dark-primary: mat-palette($mat-blue-grey);
$dark-accent:  mat-palette($mat-amber, A200, A100, A400);
$dark-warn:    mat-palette($mat-deep-orange);
$dark-theme:   mat-dark-theme($dark-primary, $dark-accent, $dark-warn);

// Include the alternative theme styles inside of a block with a CSS class. You can make this
// CSS class whatever you want. In this example, any component inside of an element with
// `.unicorn-dark-theme` will be affected by this alternate dark theme instead of the default theme.
.unicorn-dark-theme {
  @include angular-material-theme($dark-theme);
}

위의 예에서 unicorn-dark-theme 클래스가 있는 부모의 Component는 어두운 테마를 사용하지만 다른 Component에서는 기본 $candy-app-theme를 사용하게된다.

이런식으로 원하는 만큼 theme를 포함할 수 있다. 또한 Angular Material theme를 별도의 파일에 포함시킨다음 최종 사용자 상호작용(application에 따라 lazyloading하는 방법은 다르다)에 기반하여 lazyloading 할 수 도 있다.

여기서도 잊지 말아야 할 것은 @mat-coremixin은 한 번만 import해야한다는 점이다.

Multiple themes and overlay-based components

특정 Component(예: menu, select, dialog, etc)가 전역 오버레이 컨테이너 안에 있기 때문에 위의 예에서 테마의 CSS 클래스 선택기 (.unicorn-dark-theme)의 영향을 받는 Componentㅔㅇ 대한 추가 단계가 필요하다.

이렇게 하려면 전역 오버레이 컨테이너에 적절한 클래스를 추가하면 된다. 위 예제의 경우 다음과 같다.

import {OverlayContainer} from '@angular/cdk/overlay';

@NgModule({
  // ...
})
export class UnicornCandyAppModule {
  constructor(overlayContainer: OverlayContainer) {
    overlayContainer.getContainerElement().classList.add('unicorn-dark-theme');
  }
}

특정 Component에서만 사용하려할때 (Theming only certain components)

angular-material-theme mixin은 라이브러리의 모든 Component에 대한 스타일을 export하게된다. Component의 하위집합에서만 사용하는 경우(또는 특정 Component 테마만 변경하는 경우) Component별 테마 mixin을 include 해줄 수 있다.

이러한 경우에도 mat-core-theme mixin를 포함시켜야한다. 여기에는 일반적인 동작(예: 잔물결(ripples))에 대한 테마별 스타일이 포함되어있기때문이다.

@import '~@angular/material/theming';
// Plus imports for other components in your app.

// Include the common styles for Angular Material. We include this here so that you only
// have to load a single css file for Angular Material in your app.
// **Be sure that you only ever include this mixin once!**
@include mat-core();

// Define the theme.
$candy-app-primary: mat-palette($mat-indigo);
$candy-app-accent:  mat-palette($mat-pink, A200, A100, A400);
$candy-app-theme:   mat-light-theme($candy-app-primary, $candy-app-accent);

// Include the theme styles for only specified components.
@include mat-core-theme($candy-app-theme);
@include mat-button-theme($candy-app-theme);
@include mat-checkbox-theme($candy-app-theme);

Theming your own components

자신의 Component를 theming하는 더 자세한 내용은 theming-your-components.md에서 확인 할 수 있다.

Future work

  • 하나의 CSS variables로 모든 브라우저를 지원 할 수 있다면, 더 쉽게 테마를 제작하는 방법을 모색할 것이다
  • 개발이 계속 진행중이기때문에, 앞으로 더 많은 사전제작 테마가 추가될 것이다.
H2
H3
H4
3 columns
2 columns
1 column
Join the conversation now
Logo
Center