左右marginで任意の比率を保つ

CSS

元ネタはながしまさんのツイートから。

固定幅の要素の左右 margin で auto 値っぽい挙動を保ちつつ、その比率を任意のものにしたいとのこと。実現するにはCSS Values and Units Module Level3 の calc()しかない。

とりあえず、適応したい要素を 200*150px の.box として、margin-leftmargin-rightの比2対3になるように書いてみた。

.box {
  margin-left:  calc(100%*2/5 - 200px*2/5);
  margin-right: calc(100%*3/5 - 200px*3/5);

  width: 200px;
  height: 150px;
  background: red;
}

できた。

2対3なら合計分を分母にとった数を 100% - 200px の式にそれぞれ掛けてあげる。

その後、いろいろ検証的なことをして以下でFTWとなった。

.box {
  margin-left:  calc((100% - 200px) * 2 / 5);
  margin-right: calc((100% - 200px) * 3 / 5);

  width: 200px;
  height: 150px;
  background: red;
}

上記のように四則演算で丸括弧を使って計算を優先させる構文が calc()でも使える。

実はながしまさんに最初のリプライを送るときにcalc()の中で()を使うのは試していたんだけど、(100% - 200px)の部分を以下のようにスペースなしで書いていて、それだと動かなかったのでやめていた。

// 加算・減産の時は演算子の前後にスペースがないと動かない
.nope {
  // 動かない
  margin-left:  calc((100%-200px) * 2 / 5);
}

.yep {
  // 動く
  margin-left:  calc((100% - 200px) * 2 / 5);
}

加減式の場合、負の値への対応で前後にスペースが必要なのだとか。言われてみれば確かにそうだ。CSS Variables で変数にハイフンが入った時に区別できないから、という意見ももらった。どちらもなるほどですね。


追記。

margin の左右両方で calc()を指定していたけど、どちらかで calc()していればもう一方は auto 値でよいようだ。

.box {
  margin-left:  calc((100% - 200px) * 4 / 5 );
  margin-right: calc((100% - 200px) / 5 );
}
.box {
  margin-left: auto;
  margin-right:  calc((100% - 200px) / 5 );
}
.box {
  margin-left:  calc((100% - 200px) * 4 / 5 );
  margin-right: auto;
}

上記3パターンは全て同じことになる。

僕にはもう 1,2 歩先までコードを簡略化する発想がどうもできないっぽい。なので CSS おじさんは名乗れない。