Quantcast
Channel: Angular Advent Calendarの記事 - Qiita
Viewing all articles
Browse latest Browse all 25

Angular+sass(scss)によるカラーテーマ切り替えベストプラクティス

$
0
0

Angular+sass(scss)によるカラーテーマ切り替えベストプラクティス

https___angular-changetheme.stackblitz.io-Google-Chrome-2018_12_09-19_27_33.gif

この記事は,Angular Advent Calendar 2018,10日目の記事です.

TL;DR

目指したかったもの

  • WEBで,各要素の色を,瞬時に切り替えたい
  • 全部css(sass,もといscss)で管理したい
  • 色は,scssの変数で1か所で管理したい
  • このご時世にaddClassとか,removeClassとかしたくない…….
  • 各要素ごとに,テーマごとのcssを全部定義するのも,メンテできなくなるのでしたくない.
  • 結論,テーマごとに定義した色変数を用いて,それをスマートに切り替えてくれるもの

執筆動機

  • 上記要件を満たした実装が,検索してもでてこなかった
  • よくあるのは,要素ごとに色を定義して,上位クラス(wrapperとか)のクラスをremoveClass,addClassで付け替えることによる切り替え例.
  • もっとスマートにできるはず,かつ色も変数化できるはず,と頭を悩ませて,一応落としどころを見つけたので共有したい.

考えた構成

  • 1,Wrapperクラスを,テーマ分生成する.ただし,色の定義は1回のみとする.
    image.png

  • 2,Wrapperクラスを,Angularのバインドによって切り替える.
    image.png

コード解説

  • 1,Wrapperクラスを,テーマ分生成する.ただし,色の定義は1回のみとする.
// 適当な値で変数を初期化しておく
$back: #000000;
$font: #000000;
$bttn: #000000;
$btnf: #000000;

// テーマの数だけループする
@for $i from 1 through 2 {

  .wrapper#{$i} {
    @if $i == 1 {
        // テーマごとに色を定義する,1回で良い.
        $back : #F4F3EE;
        $font : #463F3A;
        $bttn : #E0AFA0;
        $btnf : #FFFFFF;
    } @else {
        $back : #000000;
        $font : #FFFFFF;
        $bttn : #32FFFB;
        $btnf : #38005B;
    }

    // スタイリングは,テーマごとに切り替えなくてよい.
    background-color: $back;
    color: $font;
    width: 100%;
    height: 100%;
    padding: 0;
    margin: 0;

    .block{
      padding: 20px;
      h1 {
        font-size: 24px;
        padding: 0;
        margin: 0;
      }
      button {
        background-color: $bttn;
        color: $btnf;
      }
    }
  }
}

  • 2,Wrapperクラスを,Angularのバインドによって切り替える.

.html

<!-- クラス名をバインドしている -->
<div [(class)]="colorTheme">
  <div class="block">
    <h1>Change Color Theme with .scss and .ts</h1>
    <p>
      toggle and change theme :)
    </p>
  </div>
  <div class="block">
    <button mat-button>This is the Button</button>
  </div>
  <div class="block">
    <mat-slide-toggle (change)="changeColor($event)">
        On Dark
    </mat-slide-toggle>    
  </div>
</div>

.ts

import { Component } from '@angular/core';
import { MatSlideToggle } from '@angular/material';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.scss' ]
})
export class AppComponent  {
  name = 'Angular';

  // バインドするテーマ
  public colorTheme = 'wrapper1';

  constructor(){
    this.colorTheme = 'wrapper1';
  }

  // toggle event
  // トグルされるたびに,バインドするクラス名を変更する
  public changeColor(e){
    if(e.checked) {
      // to dark
      this.colorTheme = 'wrapper2';
    } else {
      // to light
      this.colorTheme = 'wrapper1';
    }
  }
}

終わりに

  • この仕組みの優れたポイントは,色の定義を1極集中管理しながら,色の切り替えが行えるところである.
  • とはいえラッパーの切り替えや,scssのループなどは決して可読性は高くないので,もう少し改良ができればしたい.

明日は@kimamulaさんの記事です.
よろしくお願いいたします.


Viewing all articles
Browse latest Browse all 25

Trending Articles