余白を割合で分割

余白を特定の比率で分割したいなとちょっと考えていた。つまりmargin-leftmargin-rightプロパティーの計算済みの値が3:2とかの比率で自動調節されるように、ということ。そのようなことをTwitterでちょっと書いたら、@o_tiがcalc()を使う方法を考えてくれた。

Demo: Split margins 1 to 3

最初のデモの幅は320px、二つ目のデモの幅は480pxになっている。margin-leftプロパティーでcalc()を使い、100%から要素の幅を引いた残りを4で割っている。margin-rightプロパティーはautoで自動調節すれば良い。

.test {
  margin-right: auto;
  margin-left: calc((100% -320px) / 4);
  width: 320px;
}
320pxの要素では260pxと780px、480pxの要素では220pxと660px、と1:3で余白が分割されている。
Inspect margin-left: calc((100% - width) / 3)

開発者ツールを使って検証すると、それぞれの要素でちゃんと1:3になっていることが確認できる。残念ながらcalc()でその要素の幅を参照するような仕組みはない(CSS Variables待ちだろうか)ので、それぞれでcalc()を書かないとならないけど、やりたいことはこれで出来た。


どうも僕はcalc()を使うという発想に欠けている気がする。欲しがっていた割になかなか安心して使えるようにならなかったため、使わないで済むようにCSSを書くという教育されてきたからなのかも。現在calc()はデスクトップのブラウザーならほぼ自由に使えると言っていい状況。主に複雑なレイアウトの時に使うため、モバイル・ブラウザーでは必要性が少ないであろうと考えられるので、積極的に使うように意識改革してももう大丈夫なんじゃないかと思う。


calc()の中でcalc()みたいなことしたいとかできなかったっけとかできないな……とか混乱した。落ち着いて考えた感じ、calc()内にcalc()は書けないけど、calc()内の(...)は事実上calc()と同等なので、calc()内でcalc()出来ると言って良さそう。

<calc()> = calc( <calc-sum> )
<calc-sum> = <calc-product> [ [ '+' | '-' ] <calc-product> ]*
<calc-product> = <calc-value> [ '*' <calc-value> | '/' <number> ]*
<calc-value> = <number> | <dimension> | <percentage> | ( <calc-sum> )

2014/06/22付けの開発版のCSS Values and Units Modules Level 3仕様ではこのようにcalc()の計算が()でネストできることが、その文法の解説で明示されている。