なんかタイトルがややこしくなってしまいましたが、例えばこのようなBootstrapを利用した画面デザインツールで実現しているプレビュー画面と、デザイン画面を実現する方法を紹介します。右側が設定パネル、中央に表示されている箇所がプレビュー画面です。
デザイン画面とプレビュー画面を同一のページに組み込もうと思うとデザイン画面のCSSがプレビューにも影響してしまい、
かなり気をつけて作らないと思った通りのプレビュー画面になりません。
この機能を実現する方法は3つあります。
- iframeを使用する
- Shadow DOMを利用する
- CSS modulesを利用する
iframeを利用する
iframeを利用する方法は比較的昔から取られている方法です。間違いなく親フレームのCSSの影響を排除することができます。
しかし、親フレームからiframeのエレメントを操作しなければいけないので、操作が煩雑になることが難点です。
上記のデメリットを克服するために、React.jsのreact-frame-componentを使えば下記のように親ページにレンダリングしているかのように使用できます。React.jsを使ってアプリを作っているのであればおすすめのライブラリです。
var Header = React.createClass({
render: function() {
return (
<Frame>
<h1>{this.props.children}</h1>
</Frame>
);
}
});
React.render(<Header>Hello</Header>, document.body);
このライブラリで楽は出来るようになるものの、D&Dをしたくなった場合なども考えると、辛い選択肢ではあります。
Shadow DOMを利用する
Shadow DOMを利用すればiframeを用いなくても良くなります。本当であればこれを使いたい。
しかし、Can I useを見れば分かる通り壊滅的な状況です。これが使えるようになるのはまだまだ先のよう。ブラウザを限定できるならありかもしれません。
CSS modulesを利用する
先程紹介したBootstrapを利用した画面デザインツールを作成したことにはなかった選択肢です。
CSS modulesを利用するとグローバルに定義されるCSSのクラス名をいい感じにかぶらないようにしてくれます。
ただし、かぶらないようにしてくれるのはクラス名だけなので、タグに対してスタイルが設定されていると影響を受けてしまいます。つまりかなり気をつけてスタイルを設定した画面でのみ、実現可能な方式です。
例えばBootstrapのCSSを読んでいた場合には、それだけでBootstrapの影響を受けてしまいます。
また、デザイナーさんと協業する場合にCSS modulesが受け入れられるかも気になります。
結論
運用フローなどの問題はあるものの、
特定のページでのみプレビューを表示したいのであればCSS Modules、
様々なページでプレビューを表示したいのであればiframeといったところが結論でしょうか。
はやくShadow DOMがすべてのブラウザでサポートされるようになって欲しいです。