
CSSのcalcプロパティを使った様々な計算式と注意点
CSSのcalcは計算式を入れる事ができる利便性の高いプロパティです。
固定した数値を設定するのではなく、環境に応じた値を出すのでケースごとに結果が違います。
calcはカスタムプロパティなどとも連携できるので、利用用途は非常に豊富です。
CSSのcalcプロパティについて
本記事ではCSSのcalcプロパティについて解説していきます。
まずcalcとは何か、どのように使う事ができるのか、或いは使えないケースも含めて事例を紹介します。
calcの最大の利点は、関数として計算式を使って出力される値を変えられる事です。
各要素に対しpxで数値を固定しなくとも、その環境に応じて最適な状態にする事ができる訳ですね。
早速ご紹介していきましょう。
calcとは
calcとはプロパティの値に計算式を使う事ができる関数です。
ですので記述は同じでも、そのCSSが適用される個所や環境によってHTML上で表現される状態が変わってきます。
PCやスマホなどデバイス幅が大きく変わる事が主流の今のWEBサイトにとって必須の機能と言えるでしょう。
常に画面の幅は流動的であり、これらを全てpx単位で計算。設定する事はできません。
しかしcalc関数を使えば、これらをスマートに管理できるようになる大きなメリットがあります。
流動幅への対応
まずはcalc最大の利点となる、可変幅への自動対応機能です。
各デバイスごとの横幅を設定するのではなく、内要素の持つ余白を適宜計算する考え方です。
これにより、可変幅における要素の幅が自動で算出されます。
横幅に対してどれくらいの幅を持つか
HTML
<div class="calc">実行結果テキスト</div>
CSS
.calc { margin: 0 auto; width: calc(100% - 20px); border: solid 1px #999; }
実行サンプル
解説
上記コードはwidthを100%とし、そこから20pxを引いた状態を計算しています。
実質の幅がどれだけあっても(無くても)、最大幅から20px差し引いた幅になるという訳です。
これならデバイスがどんな幅であっても、常に20pxの余白を設ける事ができますね。
幅の数値を各々設定しなくとも常に適切な状態を算出する事ができる、これがcalc最大の特徴でしょう。
要素の「幅」を設定する事=外枠との「余白」を設定する事になります。
文字の大きさの変更
レスポンシブデザインでは画面の幅が随時変わる訳ですから、幅が変わると同時に文字の大きさも変更する必要があります。
スマホとPCで同じフォントを表示するのは、違和感が出やすいのです。
calcを使った実践的なフォント計算については割愛しますが、計算によりサイズを変更する事ができる例を紹介します。
ビューポート幅に対しての分割サイズ
HTML
<div class="calc">実行結果テキスト</div>
CSS
.calc { margin: 0 auto; width: calc(100% - 20px); font-size: calc(50vw / 20); border: solid 1px #999; }
実行サンプル
解説
上記のCSSでは、MAX100vwの半分の50vwビューポート幅に対し、20で割った大きさをフォントサイズにしています。
各デバイスの幅をpxに変換すると、常に算出されるpx数値は変わります。
50vw幅を常に20で割ったpxフォントが表示される例です。
ブラウザのウィンドウ幅を変更すると、徐々にフォントサイズが可変するのがわかります。
フロート要素間に一定間隔を設置
2つの列(左の列幅は30%、右の列幅は70%)を並べて表示するとします。
この時両者間には、常に1emの間隔を付けています。
様々なデバイス幅が存在する今のWEB環境でこれらの間隔を維持していくためには、通常は親要素(gridなど)が必要になります。
各デバイス間で常に一定の間隔を開ける
まずは左の列幅を30%、間隔となる右側のmarginを1emに設定します。
その上で右の列幅を70%としつつ、calcでその間隔分の1emを引いたものに設定する訳です。
HTML
<div class="area30">左フロート</div> <div class="area70">右フロート</div>
CSS
.area30 { padding: 30px; width: 30%; float: left; margin-right: 1em; background: #1E88E5; } .area70 { padding: 30px; width: calc(70% - 1em); float: right; background: #cc0000; }
実行サンプル
これで親要素を使用しなくても、常に2つの列の間隔(余白)を維持できます。
厳密に本サンプルでは、1emの間隔があいている分70%の幅は維持できていません。
calc関数の特徴
プロパティの一部に使える
上の例はwidthへの設定でしたが、他にもmarginやpaddingの様に上下左右等の複数設定が必要なものがありますよね。
この中で上や下などのプロパティの一部にも、calcは利用できます。
CSS
.calc { margin: 10px calc(2vw + 5px); padding: calc(1vw + 10px) 20px; border: solid 1px #999; border-radius: 0px calc(35px / 3) 0px calc(35px / 3); }
実行サンプル
上記例のmarginやpaddingはそれぞれ、左右だけ・上下だけ、にcalcを使っています。
さらにborderの角の曲線は、右上と左下にのみ付けています。
別の関数の一部に使う
上記以外にも別の関数の中にcalc関数を使う事も可能です。
CSS
.calc { padding: 10px; background: #1E88E5 linear-gradient( to right, #005bac, #1f86e3 calc(50% - 40px), #1f86e3 calc(50% + 40px), #005bac ); }
実行サンプル
上記は左から始まる背景グラデーションの演出内に、calc関数を使った例です。
半分の50%から前後40pxの区間が、色が薄くなるグラデーションになっていますね。
calc計算のPOINT
・使われるのは数値のみであり、文字列などを入れる事はできない
・単位なしの数値も使用可
・計算ができない状態でも問題はなし
calc計算のルール
ではcalc関数を使った計算をする際のルールについてまとめておきます。
空白が重要
calc関数の書き方の基本となりますが、演算子の前後には「空白」が必要です。
特に2番目にマイナス数値などを入れる場合、きちんと余白を入れておく必要があります。
CSS
.calc { font-size: calc(3vw + 2px); /* この様に書けます */ font-size: calc(3vw+-2px); /* この様に書けません */ font-size: calc(3vw * 2px); /* この様に書けます */ font-size: calc(3vw/2px); /* この様に書けますがスペースを入れるべき */ }
厳密に言うと掛け算や割り算では、演算子の前後に空白は必要ありません。
CSSコードを見るのは自分だけではない訳ですから、足し算引き算と同様に空白を入れるべきです。
この方が統一性を図れますし、見やすくなります。
足し算・引き算の場合「長さ」の単位を付ける事
calc関数内で足し算「+」や引き算「-」をする場合、中に入る数値は「長さの単位」が必ず必要になります。
CSS
.cals { margin: calc(10px + 10px); /* この様に書けます */ margin: calc(10px + 5); /* この様には書けません */ }
px以外にvwやvh、%を使う事はできますが、単位無しの数値のみで「+」「-」計算をする事はできない訳ですね。
割り算の場合、2番目の数値は「単位無し」である事
割り算の計算の場合は、2つ目の割る数字の部分に単位を付けてはいけません。
付けてしまうと計算自体がされない事になります。
CSS
.calc { margin: calc(30px / 3); /* この様に書けます */ margin: calc(30px / 10px); /* この様に書けません */ margin: calc(30px / 0); /* この様に書けません */ }
一番下の例の様に0で割っても0にしかならないので、calcが機能しません。
掛け算では、数値の1つが単位なしである事
掛け算の際には、2つの数値の内どちらかが単位無しである必要があります。
CSS
.calc { margin: calc(10px * 3); /* この様に書けます */ margin: calc(3 * 10px); /* この様に書けます */ margin: calc(30px * 3px); /* この様に書けません */ }
前と後ろどちらかが単位無しであれば大丈夫です。
calcの入れ子計算
これはcalc計算の中で入れ子を使い、さらにcalcで計算式を用いる事ができます。
基本的には以下の様に、括弧を入れ子にしていく事になります。
CSSによる演算ルール
.calc { width: calc((100% / 3) - (1rem * 2)); }
正直に書けば、2つの計算をするなら上記の様になります。
ただここは一般的な数学の世界と同じで、以下の様に括弧を省いて短縮する事ができます。
CSS(括弧を省略したケース)
.calc { width: calc(100% / 3 - 1rem * 2); }
これは足し算引き算よりも掛け算割り算の方が優先計算されるというルールに則っています。
ですので、入れ子になった部分の括弧は外す事ができる訳です。
足し算と掛け算が混ざる式の場合には、計算順序を間違わない様に先に計算が必要な箇所を括弧でくくる必要があります。
CSS(足し算優先の為括弧を追加)
.calc { width: calc(100% + 2rem / 2); ↓ width: calc((100% + 2rem) / 2); }
メディアクエリで使う事はできない
各サイズに応じて様々な値を演出するcalc関数ですが、残念ながらメディアクエリの中に入れる事はできません。
@media (min-width: calc(40rem + 1px)) { /* こういった書き方はできません。*/ }
ただこれがもし実装されるようになれば、かなり高度なメディアクエリを実行できる事になるでしょう。
CSSカスタムプロパティとの連携
calc関数の素晴らしいメリットの一つが流動幅に対応できる点だとするなら、もう一つはカスタムプロパティが利用できる点でしょう。
カスタムプロパティとは、値を代入する事ができるプロパティです。
値の代入による管理
値の代入は、CGIやPHPなどプログラム言語でよく使われますよね。
CSS
html { --space: 10px; } .calc { padding: calc(var(--space) * 2); }
上記のhtml属性内で、「--space」プロパティに10pxが代入されています。
その代入されたプロパティがcalcの中で使われている例ですね。
定義数値が変わった場合の管理がしやすい
仮にcalcの1番目の数値に、直接「10px」を入れて計算をしているとしましょう。
後からこのベースとなる数値が15pxや20pxに変わった場合、同じルールで構成しているcalcの1番目を全て書き変える必要がありますよね。
それに対して上記のカスタムプロパティを利用していれば、--spaceの値を1箇所変えるだけで済みます。
calcの計算部分は触る必要なく、全ての計算式が変わってくれるという訳です。
計算式自体を代入する事ができる
さらに「計算式自体」を代入する事もできます。これもカスタムプロパティの特徴の一つですね。
代入する時点ではcalc関数は使わず、計算式だけが代入されています。
実際に使う場合に式自体を引っ張ってきて、calcで計算をしている事になります。
CSS
html { --space: 10px; --space2: var(--space) * 2; --space3: var(--space) * 3; } .calc { padding: calc(var(--space3)); }
カスタムプロパティはHTML上からも参照できる
カスタムプロパティはCSS上で値を代入するだけではありません。
HTMLソース上に設定されたカスタムプロパティの値を、CSSで利用する事もできます。
微妙な変更が必要になる部分をHTMLソース上に記述できるので、視覚的に確認がしやすいメリットがあります。
HTML上のカスタムプロパティ値の設定
HTML
<div class="calc" style="--mar: 20px;">幅20px</div> <div class="calc" style="--mar: 40px;">幅40px</div> <div class="calc" style="--mar: 60px;">幅60px</div>
上記の様にstyleクラスでカスタムプロパティ名と値を記述します。
CSS
.calc { margin: 0 auto; width: calc(100% - var(--mar)); }
実行サンプル
HTMLソースに代入された値(20px、40px、60px)がぞれぞれCSS側で計算されます。
幅100%に対し、20pxを引いた幅、40pxを引いた幅、60pxを引いた幅がそれぞれ中央寄せされていますね。
それぞれHTML上の数値に基づいて幅が変動しているのがわかります。
calcとattrを組み合わせることはできない
CSSのattrは関数も同様に、HTMLからデータを引き出して使用できるものですね。
before:やafter:の疑似要素中で、content文字列として表示するために使います。
しかしattrのベースとなるdata-属性で記述できるのは「文字」だけです。数値(pxや%などの単位)を用いる事ができません。
HTML
<a href="#" data-○○="文字列"></a>
CSS
a hover:before{ content: attr(data-○○); }
calc計算の場合は単位が重要になってきますので、その意味でattrとは併用できないと思って下さい。