



WithCodeMedia-1-pc
WithCodeMedia-2-pc
WithCodeMedia-3-pc
WithCodeMedia-4-pc




WithCodeMedia-1-sp
WithCodeMedia-2-sp
WithCodeMedia-3-sp
WithCodeMedia-4-sp









CSSでレイアウトを組んでいると、「サイドバーが240pxあるから、メインコンテンツは残りの幅にしたい」「ヘッダーが60pxあるから、コンテンツエリアは100vhから60px引いた高さにしたい」という場面が必ず来ます。これを手計算でpxに落とし込もうとすると、画面幅が変わるたびに値が崩れてしまいます。
そこで活躍するのがCSS calc()です。calc()を使えば、異なる単位(%とpx、vwとremなど)を混在させた計算式をCSSのプロパティ値として直接書くことができます。ブラウザがレンダリング時に計算してくれるため、JavaScriptに頼らずレスポンシブなレイアウトを実現できます。
この記事では、calc()の基本構文から四則演算のルール、実践的なレイアウトテクニック、CSS変数(var)との組み合わせ、さらにclamp()・min()・max()との使い分けまでを網羅します。コピペで動くコード例を中心に、初心者から中級者まで実務で使える知識を身につけましょう。
calc()はCSS Values and Units Module Level 4で定義されているCSS計算関数です。プロパティの値として数式を記述でき、ブラウザが実際の描画時に計算結果を適用します。対応しているプロパティはwidth・height・margin・padding・top・left・font-size・line-height・grid-template-columnsなど、長さや数値を受け取るほぼすべてのプロパティです。
2026年現在、すべての主要ブラウザ(Chrome・Firefox・Safari・Edge)で完全サポートされており、ベンダープレフィックスは不要です。IE11のサポートも終了しているため、実務で安心して使えます。
calc()が普及する前は、異なる単位を混ぜた計算はJavaScriptで行うか、親要素を入れ子にして相対値を重ねるなどの工夫が必要でした。たとえば「100%の幅から32pxを引く」という表現はCSSだけでは不可能で、box-sizingで解決できない場面では複雑なDOM構造を強いられていました。calc()はその問題をシンプルに解決します。
calc()の構文はシンプルです。括弧の中に計算式を書くだけです。
/* 基本構文 */
property: calc(式);
/* 例 */
width: calc(100% - 240px);
height: calc(100vh - 60px);
font-size: calc(1rem + 0.5vw);
padding: calc(8px * 2);
calc()は四則演算(加算・減算・乗算・除算)をサポートしており、CSSで有効な数値・長さ・角度・時間・パーセンテージ・解像度などの値を組み合わせられます。
calc()で最もよくある間違いが、+(加算)と-(減算)の前後にスペースを入れ忘れることです。これはCSSの仕様上の必須ルールで、スペースがないと正しく解析されず、プロパティ全体が無効になります。
/* NG: + と - の前後にスペースがない */
width: calc(100%-240px); /* 無効 */
width: calc(100% -240px); /* 無効(右側のスペースだけでも不可) */
width: calc(100%- 240px); /* 無効(左側のスペースだけでも不可) */
/* OK: + と - の前後に必ずスペースを入れる */
width: calc(100% - 240px); /* 有効 */
height: calc(100vh + 10px); /* 有効 */
一方で*(乗算)と/(除算)は前後のスペースが任意です。ただし可読性のためにスペースを入れる習慣をつけると、+ と – と書き方が統一されてミスが減ります。
/* * と / はスペースなしでも動作するが、統一のためスペース推奨 */
width: calc(100% / 3);
padding: calc(8px * 2);
calc()の中では単位の種類ごとに演算の制約があります。
/* OK: 異なる長さ単位の加減算 */
width: calc(50% + 20px);
font-size: calc(1rem + 0.5vw);
/* OK: 乗算は片方が数値 */
padding: calc(1rem * 1.5);
/* OK: 除算は右辺が数値 */
width: calc(100% / 4);
/* NG: 両方に単位がある乗算 */
width: calc(10px * 10px); /* 無効 */
/* NG: 右辺に単位がある除算 */
width: calc(100% / 10px); /* 無効 */
加算と減算はレイアウトの「引き算」「積み上げ」に使います。もっとも使用頻度が高い演算です。
.main-content {
/* サイドバー240px + ガター20px を差し引いたメイン幅 */
width: calc(100% - 260px);
}
.hero {
/* ヘッダー高60pxを引いたファーストビュー高さ */
min-height: calc(100vh - 60px);
}
.card {
/* 上下パディング合計32pxに加えてボーダー2px×2を足した高さ */
height: calc(200px + 32px + 4px);
}
乗算は倍率計算やベースユニットからの比率計算に使います。
.section {
/* 基準値8pxの3倍 = 24px */
padding: calc(8px * 3);
}
.text-large {
/* 基本フォントサイズの1.5倍 */
font-size: calc(1rem * 1.5);
}
.overlay {
/* 画面幅の0.8倍(80%と同じ効果だが計算上の意図を明示) */
width: calc(100vw * 0.8);
}
除算は均等分割やレイアウトグリッドの計算でよく使います。
.grid-item {
/* 3等分 */
width: calc(100% / 3);
}
.column {
/* 4等分から左右マージン計算を引く */
width: calc(100% / 4 - 16px);
}
calc()内での演算の優先順位は通常の算数と同じです。* と / は + と – より先に評価されます。優先順位を明示したい場合は括弧でグルーピングできます(ただしネストのcalc()とは別物)。
/* * が先に計算される: (2 * 20px) = 40px を 100% から引く */
width: calc(100% - 2 * 20px);
/* 括弧で明示的にグルーピング */
width: calc((100% - 40px) / 3);
calc()最大の利点は異なる単位の混在です。純粋なCSSでは「親要素の50%からさらに20px引いた幅」を1つのプロパティ値で表現できませんでしたが、calc()なら一行で書けます。
.sidebar-layout {
display: flex;
}
.sidebar {
width: 240px;
flex-shrink: 0;
}
.main {
/* 親幅から固定サイドバーと余白を引く */
width: calc(100% - 240px - 32px);
}
vw(ビューポート幅の1%)とremを組み合わせることで、画面幅に連動しながらも最小サイズを確保したフォントサイズを実現できます。これはレスポンシブタイポグラフィの基本テクニックです。
.responsive-heading {
/* 基本1remに画面幅の1%を加算。画面が広いほど大きくなる */
font-size: calc(1rem + 1vw);
}
.fluid-body {
/* 最小14px相当 + 画面幅依存の追加量 */
font-size: calc(0.875rem + 0.25vw);
}
固定ヘッダーの下にコンテンツエリアをぴったりフィットさせるケースは実務で頻出です。
:root {
--header-height: 60px;
}
header {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: var(--header-height);
background: #fff;
z-index: 100;
}
.page-content {
/* ヘッダー高を引いてスクロールなしで画面内に収める */
min-height: calc(100vh - var(--header-height));
margin-top: var(--header-height);
overflow-y: auto;
}
2カラムレイアウトで片側が固定幅、もう片側が残りの幅を取るパターンです。Flexboxと組み合わせると堅牢なレイアウトになります。
<div class="layout">
<aside class="sidebar">サイドバー</aside>
<main class="main">メインコンテンツ</main>
</div>
.layout {
display: flex;
gap: 32px;
max-width: 1200px;
margin: 0 auto;
padding: 0 24px;
}
.sidebar {
width: 260px;
flex-shrink: 0;
}
.main {
/* 親幅 - サイドバー幅 - gap分 - 左右パディング分 */
width: calc(100% - 260px - 32px);
min-width: 0; /* Flexboxのオーバーフロー対策 */
}
@media (max-width: 768px) {
.layout {
flex-direction: column;
}
.sidebar,
.main {
width: 100%;
}
}
CSS Gridを使わずにflexで均等3カラムを作る際、gapの分だけ幅を引く必要があります。
.card-grid {
display: flex;
flex-wrap: wrap;
gap: 24px;
}
.card {
/*
3列: 100% / 3 = 33.333...%
gapは列間に2つ(3列なら2gap分) → 2 * 24px / 3列 = 16px
*/
width: calc(100% / 3 - 24px * 2 / 3);
/* または等価な計算: calc((100% - 24px * 2) / 3) */
}
@media (max-width: 640px) {
.card {
width: 100%;
}
}
CSS Gridのgapプロパティとgrid-template-columnsを使う場合は自動でgapを考慮してくれますが、Flexboxではcalc()による手動計算が必要です。
モーダルやサイドパネル、チャットUI等でスクロール可能なコンテナの高さを設定する典型パターンです。
:root {
--header-h: 60px;
--footer-h: 80px;
}
.scrollable-area {
height: calc(100vh - var(--header-h) - var(--footer-h));
overflow-y: auto;
-webkit-overflow-scrolling: touch; /* iOS対応 */
}
/* チャットUI: 入力欄が下固定の場合 */
.chat-container {
display: flex;
flex-direction: column;
height: calc(100vh - var(--header-h));
}
.chat-messages {
flex: 1;
overflow-y: auto;
}
.chat-input {
height: 64px;
flex-shrink: 0;
}
コンテナにパディングがある中で、内包要素を左右端まで伸ばしたい(いわゆる「はみ出し」)ケースに使います。
.container {
padding: 0 24px;
max-width: 960px;
margin: 0 auto;
}
/* コンテナのパディングを打ち消して全幅に伸ばす */
.full-bleed {
width: calc(100% + 48px); /* 左右24px×2 = 48px 追加 */
margin-left: -24px;
margin-right: -24px;
}
要素を中央配置する際のtransformを使わないアプローチにもcalc()が使えます。
.modal {
position: fixed;
width: 480px;
/* 画面中央に配置: 50% - 要素幅の半分 */
left: calc(50% - 240px);
top: calc(50% - 200px);
}
/* 右端から固定オフセットで配置 */
.fab {
position: fixed;
bottom: calc(24px + env(safe-area-inset-bottom)); /* iPhone対応 */
right: 24px;
}
CSS変数(カスタムプロパティ)とcalc()を組み合わせると、デザイントークンベースの計算が実現できます。基準値を変数に持たせておけば、その変数を変更するだけで関連するすべての計算結果が連動して変わります。
:root {
--base-space: 8px; /* スペーシングの基準 */
--header-height: 60px;
--sidebar-width: 260px;
--content-padding: 24px;
}
/* 変数を計算に使う */
.section {
padding: calc(var(--base-space) * 4) calc(var(--base-space) * 3);
/* = padding: 32px 24px; */
}
.page-body {
height: calc(100vh - var(--header-height));
padding: 0 var(--content-padding);
}
.main-area {
width: calc(100% - var(--sidebar-width) - var(--content-padding) * 2);
}
メディアクエリと組み合わせて変数の値だけを変えることで、calc()の式はそのまま使い回せます。
:root {
--header-height: 60px;
--sidebar-width: 260px;
}
@media (max-width: 768px) {
:root {
--header-height: 48px;
--sidebar-width: 0px; /* スマホではサイドバー非表示 */
}
}
.content {
/* 計算式はそのままで、変数の値だけ切り替わる */
height: calc(100vh - var(--header-height));
width: calc(100% - var(--sidebar-width));
}
JavaScriptからCSS変数を更新することで、スクロール位置やユーザー操作に応じてcalc()の計算結果をリアルタイムに変えられます。
:root {
--scroll-y: 0;
}
.parallax-element {
transform: translateY(calc(var(--scroll-y) * 0.3px));
}
<script>
window.addEventListener('scroll', () => {
document.documentElement.style.setProperty('--scroll-y', window.scrollY);
});
</script>
calc()と同じくCSS計算関数ファミリーに属するclamp()・min()・max()は、calc()だけでは表現しづらい「範囲制限」を実現します。2026年現在、これら4つの関数を使い分けることがモダンCSSの基本スキルになっています。
/* min(): 画面幅とpxのうち小さい方を採用 → 最大幅の制限 */
.container {
width: min(100%, 1200px);
/* width: 100%; max-width: 1200px; と同等 */
}
/* max(): 値のうち大きい方を採用 → 最小サイズの保証 */
.touch-target {
/* タッチターゲットは最低44px確保 */
height: max(44px, 2.75rem);
}
/* calc()を内部で使う組み合わせ */
.fluid-width {
width: min(calc(100% - 48px), 960px);
}
clamp()は「最小値, 推奨値, 最大値」の形式で書きます。推奨値には可変単位(vwなど)を使うことで、画面幅に連動しながら上下限を持つ値を1行で表現できます。
.fluid-heading {
/*
最小: 1.5rem(24px)
推奨: 2vw + 1rem(画面幅に連動)
最大: 3rem(48px)
*/
font-size: clamp(1.5rem, 2vw + 1rem, 3rem);
}
.fluid-padding {
padding: clamp(16px, 4vw, 64px);
}
/* calc() + clamp() の組み合わせ */
.section {
/* コンテナ幅から左右パディングを引いた値を、clampで上下限付きで使う */
width: clamp(320px, calc(100% - 48px), 960px);
}
判断基準は「範囲制限が必要かどうか」です。単に計算結果が欲しいだけならcalc()、「この値より小さくも大きくもしたくない」という制約があるならclamp()・min()・max()を選んでください。clamp()の推奨値引数にcalc()の式を書くことも可能で、両者を組み合わせると表現力が格段に上がります。
CSS Values Level 4仕様でcalc()のネストが正式に許可されています。calc()の中にcalc()を書くことができますが、内側のcalc()は省略して括弧だけにすることも可能です。
/* 内側にcalc()を書く形 */
width: calc(calc(100% - 240px) / 2);
/* 内側のcalc()は省略できる(括弧だけでOK) */
width: calc((100% - 240px) / 2);
/* 変数との組み合わせでネストが深くなる場合 */
.complex {
margin: calc(var(--base-space) * 2 + (100vw - 1200px) / 2);
}
min()・max()・clamp()の引数の中でcalc()の式を使う場合、内側のcalc()は省略できます。これはCSS仕様で「数学関数の引数内では計算コンテキストが継続する」ため、括弧だけで計算式を分離できるからです。
/* clamp()内のcalc()は省略可能 */
font-size: clamp(1rem, 1rem + 2vw, 2rem);
/* これは以下と同等 */
font-size: clamp(1rem, calc(1rem + 2vw), 2rem);
/* min()内でcalc()式を使う */
width: min(100% - 32px, 1200px);
/* これは以下と同等 */
width: min(calc(100% - 32px), 1200px);
前述の通り、+と-の前後にスペースが必要です。プロパティが効いていない場合はまずここを疑ってください。ブラウザのDevToolsでCSSプロパティが取り消し線付きで表示されていたら構文エラーのサインです。
/* NG */
width: calc(100%-240px);
/* OK */
width: calc(100% - 240px);
calc()の中でも通常のCSSと同様、0には単位をつけなくてよいですが、0pxと書いても動作します。ただし除算の右辺にゼロを置くとゼロ除算になり無効です。
/* OK: 0に単位なし */
margin: calc(0 + 16px);
/* NG: ゼロ除算 */
width: calc(100% / 0); /* 無効 */
長さ(px・%・vh等)と数値(単位なし)を加減算しようとするとエラーになります。
/* NG: 長さと数値の加算 */
width: calc(100% + 2); /* 無効: 2は数値で長さではない */
opacity: calc(0.5 + 10%); /* 無効: opacityは数値だが10%は長さ型 */
/* OK: 同じ型同士 */
width: calc(100% + 2px);
opacity: calc(0.5 + 0.1);
CSS変数に数値だけを入れてcalc()内で単位を後付けするテクニックは仕様上グレーゾーンでしたが、現在は「数値を変数に入れてcalc()で単位をつける」書き方が多くのブラウザで動作します。ただし確実性を求めるなら単位ごと変数に入れる方が安全です。
:root {
--size: 240; /* 単位なし数値 */
--size-px: 240px; /* 単位付き(推奨) */
}
/* 単位なし変数 + calc()で単位付加(動作するが非推奨) */
width: calc(var(--size) * 1px); /* 動く場合もあるが避けたほうが安全 */
/* 単位付き変数を直接使う(推奨) */
width: var(--size-px);
SassでCSS変数とcalc()を組み合わせる場合、Sassが計算を先に評価しようとしてエラーになることがあります。Sass変数をcalc()内で使う場合は#{$variable}で補間するか、Sassの計算とCSS calc()を区別して書く必要があります。
/* Sass内の例 */
/* NG: Sassが計算しようとしてエラー */
/* width: calc($sidebar-width - 20px); */
/* OK: Sass補間を使う */
/* width: calc(#{$sidebar-width} - 20px); */
/* 純粋なCSSカスタムプロパティなら問題なし */
/* width: calc(var(--sidebar-width) - 20px); */
ChromeやEdgeのDevToolsでは、calc()の式がどの値に計算されているかをComputedパネルで確認できます。Stylesパネルではcalc()の式そのままが表示され、Computedパネルでは計算後の実際のpx値が表示されます。レイアウトが崩れた場合はComputedパネルで期待値と実際値を比較するのが最短の診断方法です。
数値・長さ・パーセンテージ・角度・時間などを値として受け取るプロパティであればcalc()を使えます。width・height・margin・padding・top・left・bottom・right・font-size・line-height・transform(の引数)・grid-template-columns・animation-durationなど広範囲で利用可能です。一方でdisplayやpositionなどキーワード値のみのプロパティには使えません。
通常の使い方では問題ありません。ブラウザはcalc()をスタイルの解決フェーズで評価し、その後はキャッシュされた計算値を使います。アニメーションのtransformプロパティ内でcalc()を使う場合も、GPU合成レイヤーで処理されるため実質的なオーバーヘッドはほぼゼロです。ただし、JavaScriptからCSS変数を頻繁に更新するパターン(スクロールごとなど)では再計算コストが生じるため、will-changeやrequestAnimationFrameと組み合わせて最適化することを推奨します。
目的によって使い分けます。「AとBを計算して1つの値を出す」ならcalc()、「計算結果を一定範囲内に収めたい」ならclamp()・min()・max()です。フォントサイズやコンテナ幅のレスポンシブ対応にはclamp()が直感的で便利です。ただしclamp()の推奨値引数にcalc()の式を書くケースは多く、「clamp()にcalc()を入れる」組み合わせが実務では最もよく登場します。
小規模なスタイルシートや1箇所だけの計算であれば直書きでも問題ありません。ただし複数箇所で同じ基準値(ヘッダー高・サイドバー幅・スペーシング基準など)を使うなら、CSS変数に切り出してcalc()内でvar()を使う構成を強く推奨します。値が変わったときに1箇所の変更だけで済み、保守性が大幅に上がります。特に:rootに変数を集約し、メディアクエリで変数値だけを更新するパターンはレスポンシブ設計のベストプラクティスです。
IE11のサポートは2022年6月に終了しており、2026年時点では実質的に考慮不要です。ただしあえてフォールバックを用意する場合は、calc()の前に固定値を書くカスケードを使います。
.element {
/* フォールバック: 古いブラウザはこちらを使う */
width: 75%;
/* モダンブラウザはcalc()で上書き */
width: calc(100% - 260px);
}
CSS calc()はレスポンシブWebデザインの根幹を支える計算関数です。「異なる単位を混在させた計算」「ブラウザに計算を任せて常に正確なレイアウト」というこの2点が、calc()を使う最大の理由です。基本をおさえたうえで、CSS変数やclamp()・min()・max()と組み合わせることで、メンテナンス性の高いモダンなCSSが書けるようになります。

副業・フリーランスが主流になっている今こそ、自らのスキルで稼げる人材を目指してみませんか?
未経験でも心配することはありません。初級コースを受講される方の大多数はプログラミング未経験です。まずは無料カウンセリングで、悩みや不安をお聞かせください!
WithCodeでWeb制作を習得後、フリーランスエンジニアとして活動。HTML/CSS・JavaScript・WordPress案件を中心に年間20件以上の制作実績を持つ。「難しい技術をわかりやすく」をモットーに、初心者〜中級者向けの技術記事を執筆。副業・フリーランス独立を目指す方に向けた情報発信に注力している。
公式サイト より
今すぐ
無料カウンセリング
を予約!