• CSSのcalc()は割合から固定幅を引く計算に使う

CSSのcalc()は割合から固定幅を引く計算に使う

公開日: 執筆:佐藤

CSSのcalc()は、100%から20pxを引くように、単位の違う値を一つの式で組み合わせるために使います。親要素に合わせて幅を変えながら、余白や固定幅の部品だけを差し引きたい場合に便利です。

ただし、計算式を入れればレイアウト全体の寸法が自動で合うわけではありません。百分率の基準、paddingとborder、兄弟要素の余白を分けて確認します。

100%から固定の余白を引く

親要素の幅いっぱいから左右20pxずつを引く例です。

.panel {
  width: calc(100% - 40px);
}

100%は、このwidthの百分率が参照する幅です。そこから固定長の40pxを引きます。画面や親要素の幅が変われば百分率の部分は変わり、引く40pxは変わりません。

同じことを固定幅だけで書くと、親要素の幅が変わるたびに値を直す必要があります。百分率だけで書くと、固定して残したい余白を式へ含められません。calc()は、可変部分と固定部分の関係をCSSに残します。

割合とpxやemを同じ式で扱える

calc()の仕様は、長さ、割合、角度、時間、数値などを計算式で表せるようにしています。使う場所で認められる型になることが条件です。

たとえば、固定幅のサイドバーと可変幅の本文を横に並べる場合は、本文の幅を次のように表せます。

.sidebar {
  float: left;
  width: 240px;
}

.main {
  float: right;
  width: calc(100% - 260px);
}

差し引く260pxは、サイドバー240pxと、その間に残す20pxを合わせた値です。この20pxがどの要素のmarginなのかを決めずに式だけ合わせると、後から余白を変更したときに計算が崩れます。

固定部分はpxに限りません。文字の大きさに合わせたい余白なら、calc(100% - 2em)のように書けます。単位を混ぜられることが目的であり、すべてを一つの長い式へ詰める必要はありません。

足し算と引き算の記号の前後には空白を置く

+と-の前後には空白が必要です。

/* 有効 */
width: calc(100% - 40px);

/* 式として正しく解釈されない */
width: calc(100%-40px);

値と演算子を見分けるための空白です。見た目の好みで詰めず、100% - 40pxのように書きます。

丸括弧を使って計算順序を示すこともできますが、式が長くなるほど、どの寸法を差し引いているか分かりにくくなります。計算の内訳を部品名と対応させられない場合は、HTMLとCSSの分け方を先に見直します。

widthだけでなくpaddingとborderを含めて確認する

初期状態のbox-sizing: content-boxでは、widthが示すのは内容領域の幅です。左右のpaddingとborderは、その外側に加わります。

.panel {
  width: calc(100% - 40px);
  padding: 0 20px;
  border: 1px solid #ccc;
}

この例では、計算した幅に左右のpadding40pxとborder2pxが加わります。親要素へ収める意図なら、差し引く寸法へ含めるか、box-sizing: border-boxを使って境界までを指定幅へ含めます。

.panel {
  box-sizing: border-box;
  width: calc(100% - 40px);
  padding: 0 20px;
  border: 1px solid #ccc;
}

calc()が間違っているように見えても、原因がボックスの幅計算にある場合があります。式、padding、border、marginを一行ずつ分けて確認します。

対応しない環境には先に単純な値を置く

対象とするブラウザーでcalc()を利用できるか確認できない場合は、先に単純な値を書き、その後へ計算式を置きます。

.main {
  width: 70%;
  width: calc(100% - 260px);
}

calc()を解釈できる環境では後の指定を使い、解釈できない環境では前の指定が残ります。ただし、70%と計算結果が常に同じになるわけではありません。代替指定は、完全に同じ見た目を再現する値ではなく、内容を読める配置を残すために決めます。

実装可否を仕様書の存在だけで判断せず、対象ブラウザーで表示幅を変えて確認します。狭い幅、広い幅、文字を拡大した状態で、横スクロール、重なり、極端に狭い本文が生じないかを見ます。

計算式には寸法の理由を残す

calc(100% - 260px)だけを見ても、260pxの内訳は分かりません。サイドバー240pxと間隔20pxを表すなら、近くにコメントを残します。

/* 240px sidebar + 20px gap */
.main {
  width: calc(100% - 260px);
}

数値を変更するときは、式だけでなく、対応するサイドバーと余白も同じ確認単位にします。CSSの計算を増やすことより、可変部分と固定部分を誰が見ても追えることを優先します。

まず、幅が合わない一つの部品について、親要素の幅、固定して残す部品、padding、border、marginを書き出してください。百分率から固定部分を引く関係で表せるならcalc()を使い、狭い幅と広い幅の両方で計算結果を確認します。

戻る