Open Propsって何？調べてみました！

この記事は [ここのえ Advent Calendar 2023](https://qiita.com/advent-calendar/2023/99no_exit) Day 10の記事です。

# Introduction

[**State of CSS 2023**](https://2023.stateofcss.com/ja-JP/)でも名前の挙がっていた、[**Open Props**](https://open-props.style/)について追ってみました！

CSSは色々なライブラリがありますが、変数をベースとしたライブラリってどういう事？指定する時はどんな感じに書けばいいの？

今回はそんな疑問に答えるべく、Open Propsについて調査してみました！

:::note info
**残念ながら、Open Propsについて調査したものの、よくわかりませんでした……**　とかクソキュレーションサイトみたいなことはないので安心して読み進めてください。
:::

# 特徴

Open Propsの特徴ですが、このコードだけで大体把握できると思います。

```css
button.blue {
  color: var(--blue-6);
  background-color: var(--blue-0);
}
```

公式で ***Superchaged CSS variables.*** と謳われている[^1]ように、CSS変数をベースとしたCSSライブラリとなっています。

CSS変数の名称はある程度規則性があるため、これらを使用することによりプロジェクト全体のCSSスタイルに一貫性を持たせることができます。
またどんなプロパティが当たっているか容易に判別がつくため、素早くコードを理解できるメリットがあります。

ちなみに全体のライブラリに加えて、機能ごとに分離された個別のCSSも用意されていることから、必要な機能だけ導入するといったことも可能です。

# 導入

## ベース機能のみ

npmでパッケージが落ちているので、それを落としてくるだけです。

```bash
yarn add open-props
```

後はCSSで読み込むだけです。
```index.sass
@import "open-props/open-props.min.css"
```

:::note warn
上記のように、CSSはフルパスでインポートしないと読み込みませんでした。
また公式Docにある通り[^2]JSで以下のように読み込むこともできますが、JS上で使うことがないので当然never usedになりESLintが怒ります。CSSから呼んだ方が無難そうです。
```index.ts
import OpenProps from 'open-props'

// Vue:  OpenProps  is declared but its value is never read.
// ESLint: 'OpenProps' is defined but never used.(@typescript-eslint/no-unused-vars)
```
:::

## Custom Media Queries

後述する `@custom-media` の機能を使うためには、[**PostCSS**](https://postcss.org/) と [**PostCSS Custom Media**](https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-custom-media#postcss-custom-media-) プラグインの導入が必要です。

```bash
yarn add -D postcss postcss-custom-media
```

`.postcssrc.json` などのコンフィグファイルで、プラグインを読み込む必要があります。

```.postcssrc.json
{
  "plugins": {
    "postcss-custom-media": {}
  }
}
```

加えて、CSS内で対象のファイルをimportします。

```index.sass
@import "open-props/open-props.min.css"
@import "open-props/media.min.css"
```


# 実装

どんなことができるか簡単に紹介していきます。
詳しくは公式のドキュメントを見ると、サンプルが多くて分かりやすいです。

https://open-props.style/

## 基本

基本的な機能を見るため、ボタンの実装をしてみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3617021/9cdd182c-7273-ad80-efa9-d0f71ef5dee0.png)

```index.html
<button class="button">
  <p>Button Text</p>
</button>
```

```index.sass
.button
  padding: var(--size-1) var(--size-8)
  background-image: var(--gradient-1)
  box-shadow: var(--shadow-3)
  border: var(--border-size-1) solid var(--gray-5)
  border-radius: var(--radius-round)

  p
    color: var(--gray-1)
    line-height: var(--font-lineheight-1)
    font-size: var(--font-size-3)
    font-weight: var(--font-weight-5)
    font-family: var(--font-sans)
```

ライブラリの性質としては本当に素直で、CSSプロパティで当てる値を直で書かず、CSS変数を当てるだけです。それ以上もそれ以下もありません。

こういった仕様から学習コストが非常に低く、どんな変数が用意されているかを覚えていればすぐ使えます。
加えてライブラリについて理解がなかったとしても、ドキュメントを読まずとも直感的に何をしているのか理解しやすいです。独自構文を覚える必要がないのも良いところです。

カラーテーマなどを定義したければ、自分で同じような命名規則で変数を定義しておくだけなので、拡張性も非常に高いです。

## Custom Media Queries

メディアクエリに当てるための変数も用意されています。以下の例では先程実装したボタンを、`landscape`の時のみ背景色を変えるような動作になります。

ただしこの機能は [**Media Queries Level 5**](https://drafts.csswg.org/mediaqueries-5/#at-ruledef-custom-media) のDraftに入っている `@custom-media` を先取りしているため、標準のCSS環境では動作しません。
先述の通り、[**PostCSS**](https://postcss.org/) と [**PostCSS Custom Media**](https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-custom-media#postcss-custom-media-) プラグインの導入が必要です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3617021/ffe15129-7011-c4a8-dc4a-7a25d5ed4e3f.png)


```index.sass
@media (--landscape)
  .button
    background-image: var(--gradient-3)
```

## Animation, Easing

Open Propsには多彩なAnimation, Easingが定義されています。

```index.sass
.animate
  animation: var(--animation-fade-in) forwards

.easing
  animation: fade-in 300ms var(--ease-1)
```

こういったアニメーションを書かなくても変数として定義されているので、UIアニメーションが何も考えずにすぐ使えます。Open Propsで一番魅力的な点に感じます。

一般的によく使いそうなアニメーションはカバーされているので、デザイナーとエンジニア間のやりとりも「Open Propsのコレつかって」で済むので、大分作業が軽減されそうです。

以下の公式ドキュメントに大量のサンプルが乗っているので、実際に触って確かめてみてください。

https://open-props.style/#animations

# まとめ

**いかがでしたか？**　~~(これが書きたかっただけ)~~

ファーストインプレッションとしては、CSS Modulesなどとの相性は良さそうな感じがしますし、ガンガンCSSを書きまくる層にとっては使い心地が良いかもしれません。生のCSSなのでCDNでも使い易そうです。
ただ、自分はTailwindユーザなのでちょっと合いませんでした…

`sass`環境で `$size-1` といった感じで、sass変数が使えるようになったら`var(--)`の分を一気に短縮でき便利じゃないか？という気持ちが少しあります。今のところ対応していないようですが、sassを使ってるのにわざわざ`var(--size-1)` のように書くのは冗長なので……

公式サイトを見た限り `icons.css`や`layouts.css`といったWIPになっている機能もありそうですし、宝石の原石のように光る可能性を感じます。今後の発展が楽しみです。

とりあえず、しばらくはUnoCSSと戯れようかな……

# 参考

https://coliss.com/articles/build-websites/operation/css/open-source-css-variables-open-props.html

https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-custom-media

https://qiita.com/morishitter/items/4a04eb144abf49f41d7d#postcss-custom-media

[^1]:https://open-props.style/
[^2]:https://open-props.style/#getting-started
[^3]:2023年11月15日現在、Marketplaceからは対応しているプラグインを確認できませんでした。