CSS フレームワーク Master Styles を使ってみた

## はじめに

Master Styles なる CSS フレームワークの存在を教えてもらったので、

早速使ってみました

公式サイト:

https://styles.master.co/

実装例として、公式サイトの一部を再現してみたリポジトリー

https://github.com/RyoWakabayashi/master-styles-samples

## Master Styles とは

ざっくり言うと、 Master Styles は CSS を書かずにクラス名だけでスタイルを定義する仕組みです

以下のコードは公式からの引用です

### 今までの実装

home.html

```html
<h1 class="title"></h1>
```

home.css

```css
.title {
    font-size: 1rem;
}

.title:hover {
    font-size: 1.5rem;
}

@media (min-width: 768px) {
    .title {
        font-size: 1.25rem;
    }
}

@media print {
    .title {
        display: none;
    }
}
```

HTML にはクラス名を指定して、 CSS 側で詳細なスタイルを指定しています

HTML はすっきりしていますが、 CSS は行数が多いです

### Master Styles を使った場合

home.html

```html
<h1 class="font:16 font:24:hover font:20@sm hide@print"></h1>
```

HTML 1行だけで完結しました

### コードの比較

コーディング量は 74% 削減されているとのこと

注目すべきはクラス名だけで擬似クラスやメディアクエリーまで表現していることですね

- `font:24:hover`
- `font:20@sm`

さらに、以下のような形でセレクタまで表現できます

3番目の子要素

```html
<ul class="bg:gray-78>li:nth-child(3)">
```

子孫の u 要素もしくは strong 要素

```html
<article class="bg:pink-52_:where(u,strong)">
    <p>This is an <u>u tag</u> in p tag</p>
    This is an <u>u tag</u>
    <p>This is an <strong>strong tag</strong> in p tag</p>
    This is an <strong>strong tag</strong>
</article>
```

以下のようにすれば `active` クラスがあるときだけ適用する、というような条件も付与できます

```html
<button class="bg:blue-47.active active">
```

つまり、今まで CSS や SCSS で複数行かけて書いていたことをインラインで済ませるわけです

HTML の `style="..."` では擬似クラスや擬似要素、セレクタは使えないと思うので、

クラス名だけでこれができるなら、かなりスッキリ書けますね

## Master Styles のメリット

上記のように、まずコーディング量がかなり削減されます

`display:flex` は `d:flex` 、 `display:block` は `block` だけに省略も可能なので、

慣れれば相当コーディング量が減るはずです

クラス名自体はほぼCSSの記述と同じなので、違和感もありません

その他に以下のようなメリットがあります

### 名付けコストなし

確かに、どういうクラス名にするか考えるのは面倒です

Master Styles ならクラス名 = スタイルなので考える必要がありません

### 移植性

スタイルが全て HTML に書かれているので、
どんな Web フレームワークを使っていたとしてもそのまま移植できます

今回、せっかくなので様々なフレームワークで Master Styles を使ってみました

## 使ってみる

公式の Getting Started

https://docs.master.co/styles/setup

以下の錚々たるフレームワークが並んでいます

- React
- Angular
- Next.js
- Laravel
- Nuxt.js
- Vite
- Remix
- Svelte

仕組み的に、ここにない、どんなフレームワークであろうとも適用できるはずです

今回は Angular と Laravel 以外で実装してみました

ついでに各フレームワークに Storybook も導入しています

改めて、リポジトリーはこちら

https://github.com/RyoWakabayashi/master-styles-samples

### 実装した画面

#### 色見本

![スクリーンショット 2022-04-07 15.55.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/afa2395d-e5cf-fb23-93c9-6d836f219691.png)

#### アニメーション見本

![スクリーンショット 2022-04-07 15.55.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/d0e6a662-1d8c-f629-bef5-2d3a8978744a.png)

### 実装コード例

どのフレームワークでも、ただ単にスタイルをクラス名として指定するだけなので、使い方に差はありません

#### React

```react
import React from 'react'

export interface ColorBlockProps {
  colorName: string
}

export const ColorBlock: React.FC<ColorBlockProps> = (props: ColorBlockProps) => {
  return (
    <div>
      <div className={`h:40 r:3 background-color:${props.colorName}`} />
      <div className='mt:5 d:flex align-items:center'>
        <span className='f:14 f:semibold'>{props.colorName}</span>
      </div>
    </div>
  )
}
```

#### Vue

```vue
<template>
  <div>
    <div class="h:40 r:3" :class="'background-color:' + colorName" />
    <div class="mt:5 d:flex align-items:center">
      <span class="f:14 f:semibold">{{ colorName }}</span>
    </div>
  </div>
</template>

<script>
export default {
  name: 'color-block',
  props: {
    colorName: {
      type: String,
      default: 'black'
    }
  }
}
</script>
```

#### Svelte

こうして見ると、 Svelte が圧倒的にスッキリしていて見やすいなあ

```svelte
<script>
  export let colorName
</script>

<div>
  <div class="h:40 r:3 background-color:{colorName}" />
  <div class='mt:5 d:flex align-items:center'>
    <span class='f:14 f:semibold'>{colorName}</span>
  </div>
</div>
```

### 使ってみた感想

どのフレームワークでも違和感なく使用できました

まだ使いこなせているとは言い難いですが、、、

非常にシンプルなので、今後機会があったら業務でも使ってみたいですね

## おわりに

実のところ、 Getting Started に並んでいるフレームワークのうち、

業務でガッツリ使ったことがあるのは React と Angular だけだったので、

Vue や Svelte を使ってみたのも面白かったです

細かくつまずいたところもあるので、時間があれば個別に記事を書きたいと思います