undefined

bokuweb.me

モダンCSSフレームワーク『Bulma』のReactコンポーネントセット『ReBulma』を作った


概要

今年に入ってからのんびりTwitterClient(https://github.com/bokuweb/tsukiakari)を作っていて、こいつに使いたいなーと思いコンポーネントセット作った。といっても、まだかなり雑でまだまだやることがありそう。

以下のような記事もあって様々なReactコンポーネントセットがあるんだが、あまり気にいるものがなく作ってみることにした。有名ところはMateri-UIあたりになるんだろうけど、正直自分はMaterialデザインの色とか見た目があまり好きじゃないし、Material-UIの挙動が?(現在は改善されてるかも)だったり、Styleのみを閉じたシンプルなものが欲しいというのも理由のひとつになっている。

qiita.com

Bulma

BulmaFlexboxベースのモダンCSSフレームワークで現在V0.1.0RC。どんな感じなのかは以下の公式を眺めるとよい。先日もGithub Trendに入っていたので注目度は高いっぽい。

bulma.io

紹介記事もいっぱいでてくるし、以前作った(http://bokuweb.github.io/slack-list-ja/)でも試しに使っている。

coliss.com

作ったもの

作ったものは以下。

github.com

コンポーネントは以下から確認できます。サンプルコードは直接編集できるので、適当にいじってみてください。

re-bulma styleguide

一例を載せると以下のような感じ。

f:id:bokuweb:20160729112449p:plain

気をつけた点など

グローバルスコープを汚染しないこと

自分はもともとこういったCSSフレームワークが好きじゃなくて、大きな理由のひとつにグローバルスコープの汚染が上げられと思う。 これはどのCSSフレームワークも大きな差はないと思うけど、例えばBulmaの場合も以下のような記述があって、コンポーネント外にもスタイルは染みだしてしまう。

body {
  color: #69707a;
  font-size: 1rem;
  font-weight: 400;
  line-height: 1.428571428571429;
}

a {
  color: #1fc8db;
  cursor: pointer;
  text-decoration: none;
  -webkit-transition: none 86ms ease-out;
  transition: none 86ms ease-out;
}

a:hover {
  color: #222324;
}

なので、今回はこういったグローバルなスタイルを削除し、コンポーネントに閉じつつ見た目を保っている(つもり。だけど、やはり多少の差異は避けられないような気もしている。例えばfont-size: inheritが設定されたコンポーネントなどは、グローバルにfont-sizeを指定していないのでBulmaの見本とくらべて大きくなっていると思う。)。これで、コンポーネントのスタイルがコンポーネント外のスタイルに影響を与えることはひとまず、無くなっていると思う。

擬似スコープ

csjs

擬似スコープを作成するのには、今回はcsjsを使ってみることにした。こういったことを行うツールで有名所はCSS Modulesなんだろうけど、自分が食わず嫌いの天邪鬼で(CSS Modulesを使った際に外部にコンポーネントとして提供する手順がぱっと見よくわからなかったのもあるが)今回はcsjsを使った。

github.com

csjsはテンプレートストリングを使って以下のように使用する。

const styles = csjs`
  .title {
    font-size: 15px;
  }
`;

class Foo extends Component {
  render() {
    return (
      <h1 className={styles.title}>Bar</h1>
    );
  }
}

すると実際には以下のようにclassNamesuffixが付加され擬似スコープ化されるというもの。あとはcsjsを経由して得られるcssを何らかの方法でinjectする必要がある。(後述するが今回はsubstack/insert-cssで内の放り込んでいる。)

  render() {
    return (
      <h1 className="title_3YGtO7">Bar</h1>
    );
  }
問題点

上記のようにcsjsでランダムなsuffixをつけて、スタイルを上書きしたい場合は上位からclassNameを渡して設定させようとしていたんだけど、これだと詳細度の関係で思うようにスタイルの上書きができなかったり、入れ子になっているコンポーネントまでclassNameが渡せず、細かいカスタマイズができない、という話しがあって結局現在はcsjsを介して固定(___re-bulma_)のPrefixをつけるようにした。擬似スコープを作るという意味ではこのへんでも十分かもしれない。

npm iのみで済ませたい

これは些細な内容なんだけど、自分は最高に怠惰なのでnpm iした後に、別途<head />にcssを仕込むの嫌いで、上でも少し触れたようにsubstack/insert-csshead内に放り込んでいる。それだけのためにinsert-cssに依存してruntimeで挿入するのか?お前のトレードオフは間違っている。と言われたら「ですよねー」という感情しかわかない気もするけど、みんなコンポーネントのcssを別途、<head />にしこむことについてどんな印象を持っているんだろうか。

課題

容量

現在スタイル関係のファイルで百数十KBあって、それにコンポーネント(各数KB)あるのでかなりきつい。そもそもこうやって作ってもたものの本当に使うのコンポーネントって、ほんの一部でほとんどが無駄だと思う(Progressとか出番がイメージできない)。

なので課題としてlodashのようにコンポーネントの単位でインストールできるようにすれば今後使いやすいかもしれないと思ったりもしている。npm i re-bulma.button のようにインストールするイメージ。

そもそも、じゃあこういったUIキットみたいなものをプロダクションで自分が採用するかといったら、使用するケースは少ないと思うが、<Button />、とか<Input />程度の粒度で公開されていれば、使用できるケースも増えるかもしれない。

CSSのリファクタリング

今はcsjsの制約があって、本家のcssからグローバルな定義を解決しつつ機械的に移植したためcssで書いていて、散らかっているんだけど、リファクタリングしながらstylusで書いてもいいかもと思っている。

蛇足

名前は素直にreact-bulmaとかでいいかとおもったけど、こういったものをみんな作ろうと思うのか何なのかわからないけどreact-bulmabulma-reactも抑えられていて、re-bulmaにした。先に名前だけ抑えて何も作らないのは勘弁して欲しい。その過程でyamchaというのも発見した。ロゴはsvg。

github.com

さいごに

スローペースかもしれないけど、ぼちぼち改善していくのでよければ試してみてください。さくっとモックみたいなのを作るケースには役だつかも。

github.com