Skip to content

Instantly share code, notes, and snippets.

@xl1

xl1/gist:8006594

Last active Dec 31, 2015
Embed
What would you like to do?
CSS Regions と ::region() 疑似要素

CSS Regions と ::region() 疑似要素

これは CSS Property Advent Calendar 2013 17 日目の記事です。

検証環境

Google Chrome  33.0.1736.2 (Official Build 240253) dev-m
OS  Windows 
Blink 537.36 (@163749)
JavaScript  V8 3.23.18

CSS Regions

14 日目の thleap さんの記事でも触れられていましたが、コンテンツとレイアウトを分離することができる CSS Regions という仕様が提案されています。 コンテンツの要素のスタイルに flow-into プロパティを設定して、flow-from を指定した「領域」となる要素に、流しこむことができます。

現在は Chrome (「試験運用版のウェブ プラットフォームの機能を有効にする」 flag を有効にする必要あり)では実装が進んでいます。Safari 7 (iOS 版も)でも実装されているようですが、確認していません。 また、JavaScript による polyfill 実装も作られています。

::region() 関数的疑似要素

仕様によると、::region() 疑似要素 を使って、「領域」要素に流し込んだ先でのスタイルを指定できるようになります。 http://www.w3.org/TR/css3-regions/#region-styling の例がわかりやすいと思います。 ここでは、

#region1::region(p) { ... }

と指定することで、**「#region1 に流し込まれている p 要素」**に対してスタイルをあてています。

::region() で使えるプロパティ

::region() 疑似要素の中では、::first-line 疑似要素などのように、使用できるプロパティが制限されています。

  • font
  • color
  • opacity
  • background
  • word-spacing
  • letter-spacing
  • text-decoration
  • text-transform
  • line-height
  • text-aligntext-justify
  • border
  • border-radius
  • margin
  • padding
  • text-shadow
  • box-shadow
  • box-decoration-break
  • width

Bug 15190 – List of region style properties によると、この制限は実装の都合によるもののようです。 たとえば、font-size やスペーシングのプロパティを変える場合、スタイルを当てることによって配置がずれ、::region() 疑似要素の範囲が変わってしまうということがありえます。

フォントサイズの変更によって ::region() の範囲が変わってしまう例 フォントサイズの変更によって ::region() の範囲が変わってしまう例。

  • (a): スタイルを適用しない状態。
  • (b): (a) で最初の要素に入っている部分に ::region() でスタイルを適用しようとした場合。font-size が大きくなるため、はみ出してしまう。
  • (c): 正しい描画。

このため、実装されてもあまり使われないだろうプロパティも含めて、すべてを許可するのは難しいと思います。 個人的には animationtransform などが使えると楽しそうですが。

現在の Chrome の実装では、古い仕様に基づいているため、::region() 疑似要素ではなく、@region ルールを使うようになっています。

@-webkit-region #region1 {
  p { ... }
}

さらに、サポートされているプロパティも、リフローが生じることがありえない、colorbackground-color のみになっています。 こちらのデモ で試すことができます。

Polyfill

そういう状態ですから、主要ブラウザが ::region() に対応するまでにはまだまだかかりそうですが、とりあえず JavaScript ポリフィルを作ってみました。

CSS パーサは入っていないので、手作業で

Region('#region1').addRegionRule('p', {
  color: 'black',
  marginRight: '100px'
});

などとする必要があります。 CSS Regions に対応していないブラウザでは、上述の Adobe の CSS Regions polyfill を前提にして動きます。 まだ動作が怪しい部分もあるので、あとで整理します……。

明日は

@nakajmg さんです。よろしくお願いします。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment