「画面いっぱいの幅から、固定したサイドバーの分だけ引いた残りを本文にしたい」「ヘッダーの高さを引いた高さでコンテンツを表示したい」。こうした異なる単位を混ぜた計算を CSS だけで行えるのが calc() 関数です。% と px のように、本来そのままでは足し引きできない単位どうしを組み合わせて値を求められます。この記事では、calc() の基本構文から四則演算のルール、実務でよく使う具体例、CSS 変数との組み合わせ、つまずきやすい点までを、コーディング初心者〜中級者の方に向けて解説します。
目次
calc()とは何か・なぜ便利か
calc() は、CSS のプロパティの値を「計算式」で指定できる関数です。たとえば width: calc(100% - 240px); と書くと、「親要素の幅 100% から 240px を引いた値」がそのプロパティに適用されます。ポイントは、%(相対的な単位)と px(絶対的な単位)のように、性質の異なる単位を1つの式の中で混ぜられることです。
これまでこうしたレイアウトは、JavaScript で要素の幅を測って計算するか、固定値を決め打ちするしかありませんでした。calc() を使えば、画面サイズが変わっても親要素の幅に追従しながら、固定したい部分(サイドバーやヘッダーなど)の分だけを正確に差し引けます。レスポンシブなレイアウトを CSS だけで素直に表現できるのが、最大の利点です。
基本の構文
使い方はとてもシンプルで、値を書く場所に calc( 計算式 ) と書くだけです。width や height はもちろん、margin、padding、font-size、top など、長さ(length)を取るプロパティのほとんどで使えます。
.box {
/* 親要素の幅から左右 20px ずつ(合計 40px)を引く */
width: calc(100% - 40px);
/* 50px を基準に、ビューポート幅に応じて少し増やす */
font-size: calc(50px + 1vw);
}
このように、計算式の中には %・px・vw・em など複数の単位を混在させられます。単位を持たない数値(たとえば 2)も、後述の掛け算・割り算でのみ使えます。式の結果が最終的にそのプロパティの正しい型(長さなど)になっていれば問題ありません。
四則演算と演算子のスペースのルール
calc() の中では、足し算 +、引き算 -、掛け算 *、割り算 / の4つが使えます。計算の優先順位は算数と同じで、* と / が先に評価され、丸括弧 () でグループ化して優先順位を変えることもできます。
ここで初心者がもっとも引っかかるのが演算子の前後のスペースです。+ と - は、前後に必ず半角スペースが必要です。これは - がマイナス符号と引き算のどちらなのかを区別するための仕様で、スペースがないと式全体が無効になります。一方 * と / はスペースが任意ですが、読みやすさのために前後へ入れるのがおすすめです。それぞれの演算子の扱いを整理すると次のようになります。
| 演算子 | 意味 | 前後のスペース |
|---|---|---|
+ | 足し算 | 必須(無いと式が無効) |
- | 引き算 | 必須(無いと符号と区別できない) |
* | 掛け算 | 任意(推奨は入れる) |
/ | 割り算 | 任意(推奨は入れる) |
/* OK: + と - の前後にスペースがある */
width: calc(100% - 40px);
/* NG: - の前後にスペースが無く、式が無効になる */
width: calc(100%-40px);
/* * と / はスペース無しでも動くが、入れた方が読みやすい */
width: calc(100% / 3);
width: calc(100%/3);
サイドバー分を引いて本文の幅を決める
もっとも代表的な使い方が、固定幅のサイドバーがあるレイアウトです。サイドバーの幅を 240px に固定し、本文は calc(100% - 240px) として「残り全部」に広げます。画面幅が変わっても、サイドバーは常に 240px を保ったまま、本文だけが伸び縮みします。下のデモで、本文側に calc() が効いている様子を確認できます。
<div class="layout">
<aside class="sidebar">サイドバー<br>240px 固定</aside>
<main class="content">
<p>本文エリア</p>
<p>幅は <code>calc(100% - 240px)</code></p>
<p>サイドバーの分を引いた残り全部に広がります。</p>
</main>
</div>
.layout {
display: flex;
gap: 16px;
font-family: sans-serif;
}
.sidebar {
/* サイドバーは 240px で固定 */
width: 240px;
flex: none;
padding: 16px;
background: #e3f2fd;
border-radius: 8px;
text-align: center;
}
.content {
/* 全体(100%)からサイドバー分(240px)を引いた残りが本文の幅 */
width: calc(100% - 240px);
padding: 16px;
background: #f1f3f5;
border-radius: 8px;
}
.content code {
background: #fff;
padding: 2px 6px;
border-radius: 4px;
}
同じ考え方は縦方向にも応用できます。たとえば画面の高さいっぱいから固定ヘッダーの高さを引きたいときは、height: calc(100vh - 60px); のように書きます。100vh はビューポートの高さの 100% を表す単位なので、ヘッダーが 60px なら、残りの高さがちょうどメインコンテンツの領域になります。
CSS変数と組み合わせて一括管理する
calc() の真価が出るのは、CSS 変数(カスタムプロパティ)と組み合わせたときです。--gap: 12px; のように基準値を1か所で定義し、calc(var(--gap) * 2) のように式の中で参照すれば、余白やサイズの比率を保ったまま全体をまとめて調整できます。基準値を1行変えるだけでデザイン全体のバランスが連動するため、保守がぐっと楽になります。
<div class="card">
<h2>カードのタイトル</h2>
<p>このカードの余白とフォントサイズは CSS 変数と calc() を組み合わせて計算しています。</p>
<p class="note">--gap を変えると余白がまとめて変わります。</p>
</div>
.card {
/* 基準となる余白を変数で1か所に定義 */
--gap: 12px;
/* 変数を calc() の中で使い、上下と左右で量を変える */
padding: calc(var(--gap) * 2) calc(var(--gap) * 1.5);
max-width: 360px;
background: #fff;
border: 1px solid #ddd;
border-radius: 8px;
font-family: sans-serif;
}
.card h2 {
margin: 0 0 var(--gap);
/* 基本サイズ 16px に変数分を足してタイトルを少し大きく */
font-size: calc(16px + var(--gap));
}
.card .note {
margin-top: calc(var(--gap) * 2);
color: #007bff;
font-size: 14px;
}
変数を calc() の中で使うと、単純な代入では難しい「変数の2倍」「変数+固定値」といった派生値を作れます。フレックスやグリッドの gap を変数で持っておき、要素の margin をその gap から計算する、といった設計とも相性が良いです。
入れ子とmin()・max()との関係
calc() は入れ子にもできます。calc(100% - calc(40px + 1em)) のように書けますが、内側の calc は省略しても同じ意味になり、calc(100% - (40px + 1em)) のように単なる丸括弧でグループ化するのが一般的です。
近い仲間として min()・max()・clamp() という関数もあります。これらは「複数の候補のうち最小・最大を選ぶ」「下限・上限の範囲に収める」ための関数で、内部で calc() と同じ計算式を直接書けます。たとえば width: min(100% - 40px, 800px); は「親幅から 40px 引いた値」と「800px」の小さい方を選び、大きな画面でも最大 800px に抑えつつ、狭い画面では左右に余白を残せます。引き算で残りを確保したいときは calc()、上限・下限を設けたいときは min()・max()・clamp()、と使い分けると整理しやすくなります。
calc()が効かないときに見直す点
+と-のスペースが抜けている
もっとも多い原因が、+ と - の前後のスペース漏れです。calc(100%-40px) のようにスペースがないと、ブラウザは式を解釈できず、その宣言ごと無視します。値がまったく反映されないときは、まず演算子の前後に半角スペースが入っているかを確認してください。* と / はスペースが任意ですが、+ と - は省略できない、という点を覚えておくと安心です。
0での割り算や単位の不整合
/ の右側に 0 を書いた割り算(calc(100% / 0))は無効で、その宣言は適用されません。変数で割る数を渡す設計のときは、0 が入り込まないよう注意します。また、掛け算と割り算には「片方は必ず単位なしの数値」というルールがあります。calc(100px * 2) は正しいですが、calc(100px * 2px) のように両辺へ単位を付けると無効です。長さ×長さは面積になってしまい、CSS の長さとして成立しないためです。
単位の付け方を取り違えている
足し引きする値どうしは、それぞれが有効な単位を持っている必要があります。calc(100% - 40) のように片方の単位を付け忘れると、100%(パーセント)と 40(数値)を足し引きすることになり、型が合わず無効になります。引きたいのが 40px なら、必ず calc(100% - 40px) と単位まで書きましょう。式が効かないときは、各項に正しい単位が付いているかを1つずつ見直すと原因にたどり着きやすくなります。
まとめ
calc() は、% と px のように異なる単位を混ぜて値を計算できる関数で、width: calc(100% - 240px) のように「全体から固定分を引いた残り」を CSS だけで表現できます。四則演算が使え、+ と - は前後のスペースが必須、* と / はスペース任意で片側は単位なしの数値にする、というルールを押さえておけば大半のつまずきは防げます。CSS 変数と組み合わせれば基準値を一括管理でき、上限・下限を設けたい場面では min()・max()・clamp() と使い分けると、レスポンシブなレイアウトを柔軟に組み立てられます。