CSSの calc() ファンクションを使って長さを計算しサイズ指定する方法
CSSで長さを計算できるcalc()
ファンクションというのはご存じですか?
ここのところ流行りのレスポンシブデザインもそうですが、コンテンツの幅をフレキシブルに対応させたいという場合に、とても役立つファンクションです。
今回はこのcalc()
ファンクションの使い方や、ブラウザのサポート状況をご紹介したいと思います。
親要素の幅を超えないようにする
calc()
ファンクションにはいろいろな使い方があるんですが、代表的なところで言えば画像などのコンテンツ幅が親要素の幅を超えないようにするという使い方。
通常、コンテンツ幅をフレキシブルに対応させるだけなら、CSSのmax-width
プロパティに対して100%
と値を指定すりゃいいわけです。
しかし、ここにpadding
やborder
といったプロパティを与えた途端に、親要素の幅をサラリと超えてきやがります。子の成長が著しい。
そこで親要素の幅を超えないよう、calc()
ファンクションを使って100%
からpadding
分の数値を差し引いてやります。
img { max-width: calc(100% - 8px*2); padding: 8px; }
これで100%
から一辺あたりにpadding
として指定した8px
を左右二辺分掛けた数値が差し引かれるということになります。
つまり、親要素の幅から画像の左右のpadding
の大きさを計算して引き算し、その解となる数値が画像の最大幅として与えられたというわけ。
calc()
ファンクションのいいところは、%
、em
、vw
などの異なる単位同士でもちゃんと計算して解を出し適用できるという点。
いちいち予め計算して幅を割り出すなど、面倒な手間も軽減されます。
親要素の幅を子要素が超えてしまうという状況を解決する方法として、box-sizing
プロパティを用いるという方法があります。
img { max-width: 100%; padding: 8px; box-sizing: border-box; }
CSSに書くならこんな感じ。
確かにこれでも子要素の幅が親要素を超えることはなくなるんですが、この方法にはちと盲点があります。
というのも、box-sizing
プロパティを与えることでimg
要素のwidth
属性とheight
属性にも影響を与えてしまいます。
どういうことが起きるかというと、マークアップで指定している値と、実際に表示される大きさが異なってしまうんですね。
Retinaディスプレイを考慮して記事中に縦横2倍の画像を入れたときなどに計算が狂ったりとか。
このあたりを未然に防ぐ意味でも、box-sizing
ではなくcalc()
ファンクションをオススメします。
各ブラウザのサポート状況
calc()
ファンクションのブラウザサポート状況は以下のとおり。
- Internet Explorer
IE9からサポート。 - Firefox
Firefox4〜15までベンダープレフィックス付きで先行実装。
Firefox16からサポート。 - Google Chrome
Chrome19〜25までベンダープレフィックス付きで先行実装。
Chrome26からサポート。 - Safari
Safari6.0からベンダープレフィックス付きで先行実装。
Safari6.1及びSafari7.0からサポート。 - iOS
iOS 6.0から6.1までベンダープレフィックス付きで先行実装。
iOS 7からサポート。 - Android
Android 4.4からサポート。
見てもらえればわかるように、ごくごく最近になってようやくほぼサポートされてきたかなーという感じです。
とは言え、ユーザーのブラウザ利用状況を考えれば、まだベンダープレフィックスを付けつつ、非対応のブラウザに対するフォールバックは欠かせないと言えます。とりあえずIEは爆発しろ。
なので、先ほどの例をベンダープレフィックス付き、かつフォールバックしたものにすると以下のようになります。
img { max-width: 90%; max-width: -webkit-calc(100% - 8px*2); max-width: -moz-calc(100% - 8px*2); max-width: calc(100% - 8px*2); padding: 8px; }
レイアウトが破綻しないくらいのざっくりした数値をフォールバックとして指定しておきましょう。
ベンダープレフィックスはプロパティではなくcalc()
ファンクションに付けます。間違わないように注意。
-moz-
はもう別にいらないかもしれませんけど念のためってことで。
こんなプロパティにも calc() は使える!
今回の例では最大幅を指定するためのmax-width
プロパティをベースに説明しましたが、他にも様々なプロパティに対して使うことができます。
width
height
margin
padding
font-size
background-position
text-shadow
transform:rotate()
などなど、長さや周波数、角度、数量、時間、整数値に当てはまる値を用いるプロパティであれば、どこでも使うことができます。
また、calc()
ファンクションの中でさらに別のcalc()
ファンクションを使うといったことも可能。
使い方次第で、これまでちょっと難しかったレイアウトがかなり簡単にできるようになるので、ぜひCSSにうまく導入してみてください。
HTML5/CSS3モダンコーディング フロントエンドエンジニアが教える3つの本格レイアウト スタンダード・グリ…