anti scroll

ブラウザと小説の新しい関係を模索する

10秒でわかるpseudo-classとpseudo-elementの違い

pseudo-class

pseudo-classは、左側のセレクターに続けて「〜が」と読みます。

/* liが最初の子だった場合 */
li:first-child{
  margin-top:0;
}

「〜が」だから、左側がマッチする要素です(上の例ではli)。

pseudo-element

pseudo-elementは、左側のセレクターに続けて「〜の」と読みます。

/* liの先頭文字 */
li::first-letter{
  font-size:3em;
}

「〜の」だから、右側がマッチする要素です(上の例では::first-letter)。

まとめ

どちらもpseudoと付いていますが、全く性質の異なるものです。

しかし古い仕様ではコロンがどちらも1つで記述されていて(例えば:first-letterとか)、紛らわしいという問題がありました。

なので最新の仕様では

  • pseudo-classにつくコロンの数は1つ(:first-childとか:last-childとか)
  • pseudo-elementにつくコロンの数は2つ(::first-letterとか::beforeとか)

というのが、正式な文法となっています。

ただし古いCSSと互換性を保つために、大体のブラウザではコロン1つでも通るようになっています。

余談

ちなみにnehan.jsの場合、コロンの数は厳密に区別します。

つまり::first-letterとすべきところを:first-letterと書いてしまうと、単に「未定義のpseudo-class」と見なされてしまいます。

Nehan.setStyle(".foo:first-letter", {fontSize:"3em"}); // NG(未定義のpseudo-class)
Nehan.setStyle(".foo::first-letter", {fontSize:"3em"}); // OK!

css framework上の全てのセレクタに特定のprefixを付ける

chrome拡張とかでも、普段使っているcssフレームワークが使いたくなることがあります。

しかし大抵のcssフレームワークは、グローバルな名前空間でスタイルを宣言しています。そのまま導入すると、拡張機能CSSが読み込まれてしまった結果、訪問したサイトの本来のスタイルを崩してしまうことでしょう。

もちろん拡張機能を特定のサイトでだけ動くようなポリシーにすれば防げます。しかし、NehanReaderのように、全てのサイトで使えるようにしている拡張機能も、たくさんあると思います。

そういう場合、フレームワークで宣言されている全てのセレクタに、強引に何かのプレフィックスを足してしまえば良いわけですが、手動でやるのは流石にキツイ、というか無理です。

だから「なんか良いツールないかなあ」と探して見つけたのがrework-mutate-selectorsです。

github.com

インストール

今回はgulpを使いたかったので、gulp-reworkも一緒に導入しました。

npm install rework
npm install rework-mutate-selectors
npm install gulp-rework

gulpやgulp-renameがない人は、先にインストールしておいて下さい。

使ってみる

var gulp = require("gulp");
var rework = require("gulp-rework");
var selectors = require("rework-mutate-selectors");
var rename = require("gulp-rename");

gulp.task("default", function(){
  return gulp.src("framework.css")
    .pipe(rework(selectors.prefix(".my-module"))) // prefixに".my-module"を追加
    .pipe(rename("my-module.framework.css"))
    .pipe(gulp.dest("."));
});

こうすると例えば

/* framework.css */
div a{ color:red }

が、

/* my-module.framework.css */
.my-module div a{ color:red }

と出力されます。

結論

一瞬、自分で作ろうかとも考えましたが、諦めずに探して良かったとです。

box-sizing:margin-box

margin-boxとは

margin-boxとは、ボックスのサイズをmarginも含めて計算するボックスのことです。

つまりmarginが50pxで、widthが200pxなら、コンテントサイズは

200(width) - 50(margin-left) - 50(margin-right) = 100

になります。

ちなみにこのmargin-boxという値は、現在のbox-sizingプロパティでは、有効な値ではありません。

でもcss3 shapesという仕様のshape-outsideというプロパティでは有効な値(それどころかデフォルト値)だったりします。

理由はよくわかりません。

nehan.jsにおけるbox-sizing

ところで nehan.js においては、box-sizingmargin-boxが指定できます。

というか、margin-boxがデフォルトです。なぜか。

それは、ページ送りの組版では、外側のサイズが固定されているからです。

通常のウェブサイトなら、外側のサイズは「スクロール」という組版に逃げることで、いくらでも拡張できます。

しかしページ送りの組版においては、外側のサイズは絶対です。

つまり内側のコンテンツは、外側に固定されたサイズを、何があってもはみ出さないように配置する必要があります。

そういう「外に余剰サイズを逃すことができない」状況下で、ボーダーの外側に余白を表現したい場合はどうするのか。

答えは簡単。コンテントサイズを削るしかありません。

だからnehan.jsのbox-sizingは、基本的にmargin-boxなのです。

というか、paged mediaにおいては、そうならざるを得ないような気がします。