ReactとCSS

Reactを少しずつ使い始めていて、コンポーネント指向でコードを書いていけるところが自分の経験だとDelphiのような感じでとても良い。 JavaScriptとHTML(JSX)を1つのスクリプトにまとめることができたのは良いのだけど、そうするとやはりCSSも一緒にまとめたくなってくる。

それでReactとCSSについていくらか調べてみた。ちなみにElectronで動作すれば良いので、Blinkのことしか考えていない。

CSS in JS

そもそもReactでCSSは普通どういう風に書くのか調べてみた。

ひとつのやり方ではあるけども、style属性に一つ一つ指定していく方法。 辛くない?疑似要素は?疑似クラスは?継承してもらいたいプロパティとかもあるんだけどな〜

scoped CSS

せっかくコンポーネントにするのだし、CSSもコンポーネントに閉じたところでのみ適用されて欲しいと思ってscoped CSSについて調べた。

てっきりBlinkにはstyleタグのscoped属性がすでに実装されていると思っていたのだけど、Firefoxしか実装していないみたいだ。 記事にもあるとおり、Blinkで同様のことをするにはShadow DOMを使用する必要がある。

Shadow DOM

Shadow DOMについて深い理解があるわけではなかったので、調べてみた。

templateタグで楽はできそうだけど、JavaScriptでShadow DOMを生成・追加するためのコードを書く必要があるみたいだ。 Reactと組み合わせて使うにはまだ自分のReactの理解力が低すぎて作れない……

ReactStyle

他の解決策〜と思って調べてみたらReactStyleというのを見つけた。

疑似要素〜疑似クラス〜という感じだ。

Radium

こちらはReactStyleと違って(一部の?)疑似クラスとメディアクエリが使える。

Radiumはスタイルのマージが簡単にできて

const CSS = {
  base: {
    height: '100px',
    width: '100px',
  },
  div: {
    backgroundColor: 'blue',
    height: '150px',
  },
};

const Component = React.createClass(Radium.wrap({
  render() {
    return (<div style={[CSS.base, CSS.div]}></div>);
  },
}));

という風に配列を指定するとできる。

ChromeのReact Developer Toolsで見たらタグ名がUnknownになっていてびっくりした。 Radium.wrap()内に書いたJSXだからなのか、displayNameが出力されないみたいなのでdisplayNameを自分で指定する必要がある。

ReactShadow

ReactでShadow DOMは扱えないのか調べてみたらmixinがあった。

正真正銘のShadow DOMでcssDocumentscssSourceのプロパティ名が示すようにscoped CSSの目的で使うみたいだ。

ただ、出力されるHTMLが若干変な感じ。React.createClass()で生成したコンポーネントがShadow DOMとして追加されるのだけど、 それの直後にscriptタグが追加される。scriptタグの中身はコンポーネントと全く同じ。 つまり、Shadow DOMとscriptタグにそれぞれ同じコンポーネントが追加される。

ちゃんとソースコードを読んでいないので勘なのだけど、Reactがscriptタグ内にあるコンポーネントを変更して、 ReactShadowがその変更をShadow DOM内にあるコンポーネントに同期させている感じなのかな。


とりあえずRadiumを使ってみている。ReactShadowもscriptタグが気にならければ良いんじゃないかなと思う。

そういえばscoped CSSとShadow DOMを使ってのスタイル当てというのは若干異なるような気がした。 Shadow DOMって通常だと外側のスタイルが当たらないんじゃなかったっけ。

簡単に扱えるネイティブのscoped CSSが欲しいなあ。一意のidかclassを付加してセレクタの最初にそれを書けばscoped CSSっぽくなるかな。