SCSSでつくる「気持ちいいfluidデザイン」

1. なぜ今さら「fluid」なのか? clamp時代のSCSSユーティリティの価値

最近のfluid設計は、ほぼ clamp() 一強です。

font-size: clamp(16px, 4vw, 24px);

みたいな書き方は、Smashing Magazine や moderncss.dev をはじめ

いろんな媒体で紹介されています。

ですが、実務でやろうとすると、こうなりがちです。

  • デザイナーから「PCでは32px、SPでは20pxくらい」と言われる
  • ビューポート幅は… 375〜1440pxくらい?
  • じゃあ clamp() の真ん中の式どう計算するの…
  • しかも案件ごとに何度も同じ計算を書くのはダルい

ここで生きてくるのが SCSS の

  • 変数
  • 関数
  • ミックスイン
  • マップ

を使った fluidユーティリティ群 です。

utils/scss/fluid のようなディレクトリは、おそらく

「数式とロジックを全部カプセル化して、

実装者は @include fluid-font(16px, 24px); みたいに書くだけ」

という世界を目指しているはずです。


2. 

utils/scss/fluid

 が担っていそうな役割を分解する

パス名から逆算すると、このディレクトリは

  • utils …… どこからでも使える汎用ユーティリティ
  • scss …… SCSS専用
  • fluid …… fluid(流体)なスケールを扱う一式

という位置付けになっているはずです。

中身として典型的にありそうなのは、例えば以下のような構成です。

  • _variables.scss
    • fluid設計で使うデフォルト値(最小/最大vwなど)
  • _functions.scss
    • fluid() みたいな、値を返す関数
  • _mixins.scss
    • fluid-font(), fluid-space() など、プロパティをまとめて吐くミックスイン
  • _index.scss or _fluid.scss
    • 上記をまとめて @forward / @use するための入口

実際のファイル名は違う可能性がありますが、

「fluidディレクトリとして切り出している」という時点で、

ある程度しっかり設計されたユーティリティ群 である可能性が高いです。


3. 一般的なfluidユーティリティの構成イメージ

では、ここからは

「もし自分が utils/scss/fluid を書くならどう構成するか」

という観点で、かなり現実的な実装像を組み立てていきます。

3-1. まずは前提となる設定値

よくあるのが「プロジェクトのデフォルト」として

  • ビューポートの最小幅
  • ビューポートの最大幅
  • 最小フォントサイズ / 最大フォントサイズの基準値

などを変数として定義するパターンです。

// fluid/_variables.scss

$fluid-min-vw: 375;  // SPベース
$fluid-max-vw: 1440; // PCの想定幅

// clampの汎用fallback等に使うベースサイズ
$fluid-base-font-size: 16px;

こうしておくと、

  • 案件A:375〜1440px
  • 案件B:360〜1280px

のように条件が違っても、

変数だけ差し替えれば同じ関数・ミックスインが再利用できます。


3-2. 中心となる 

fluid()

 関数のイメージ

fluid系ユーティリティの核になるのは、

fluid($min, $max, $min-vw: $fluid-min-vw, $max-vw: $fluid-max-vw)

のような関数です。

この関数が返すのは、だいたい次のどちらかです。

  1. clamp() を返す
  2. calc() と vw を組み合わせた文字列を返す

最近は1の clamp() ベースが主流です。

擬似コード的には、こんな感じのイメージです。

@function fluid($min, $max, $min-vw: $fluid-min-vw, $max-vw: $fluid-max-vw) {
  // 単位チェックやエラー処理を挟んだ上で…

  $slope: ($max - $min) / ($max-vw - $min-vw); // 傾き
  $intercept: $min - $slope * $min-vw;          // 切片

  // clamp(
  //   最小値,
  //   (vwに対する傾き * 100vw) + 切片,
  //   最大値
  // )
  @return clamp(
    $min,
    #{$slope * 100}vw + #{$intercept}px,
    $max
  );
}

実際は単位を px に固定せず、rem ベースで扱ったり、

ひと手間かけて unitless 変換したりしますが、考え方はだいたいこんな感じです。


3-3. 関数を包むミックスインたち

関数ができたら、あとは用途ごとに薄くラップしてあげると使いやすくなります。

たとえば:

  • fluid-font($min, $max, …) → font-size 用
  • fluid-space($property, $min, $max, …) → margin, padding, gap など任意プロパティに使える
  • fluid-width($min, $max, …) → width / max-width / min-width 用

例:

// fluid/_mixins.scss

@use "variables" as *;
@use "functions" as *;

// font-size専用
@mixin fluid-font($min, $max, $min-vw: $fluid-min-vw, $max-vw: $fluid-max-vw) {
  font-size: $min;
  font-size: fluid($min, $max, $min-vw, $max-vw);
}

// 任意プロパティ用
@mixin fluid-space(
  $property,
  $min,
  $max,
  $min-vw: $fluid-min-vw,
  $max-vw: $fluid-max-vw
) {
  #{$property}: $min;
  #{$property}: fluid($min, $max, $min-vw, $max-vw);
}


こうしておくと、コンポーネント側では

.title {
  @include fluid-font(18px, 28px);
}

.section {
  @include fluid-space(padding-inline, 16px, 40px);
}

のように、かなり読みやすい形で使えます。


4. 一番よく使うのはこれ:

fluid()

 関数と 

fluid-size()

 ミックスイン

ここからは、実務でよく使うであろう

「基本の使い方」をサンプルコードつきで整理していきます。

4-1. タイポグラフィ用 

fluid-font()

見出しまわりでの典型的な使い方はこんな感じです。

// _typography.scss

@use "../utils/scss/fluid" as fluid;

:root {
  // fallbackとして全体の基準を定義
  font-size: 16px;
}

h1 {
  @include fluid.fluid-font(28px, 40px);
  line-height: 1.3;
}

h2 {
  @include fluid.fluid-font(24px, 32px);
  line-height: 1.4;
}

h3 {
  @include fluid.fluid-font(20px, 28px);
  line-height: 1.5;
}


コンパイル後のイメージは:

h1 {
  font-size: 28px;
  font-size: clamp(28px, 3.5vw + 10px, 40px);
  line-height: 1.3;
}

のような形になります(式はあくまで例)。

  • 小さなSPでは 28px からスタート
  • ビューポートが広がるに従って自然に大きくなり
  • PCで 40px に到達したらそれ以上は大きくならない

という挙動です。


4-2. 余白用 

fluid-space()

余白もfluid化しておくと、

SPでもPCでも「ちょうどいい余白感」を保ちやすくなります。

.section {
  @include fluid-space(padding-block, 40px, 80px);
  @include fluid-space(padding-inline, 16px, 64px);
}

このようなユーティリティを持っておくと、

  • section間の余白
  • カードのインナー余白
  • カラム間の gap

などを統一感のある設計で動かせるようになります。


4-3. コンポーネント幅用 

fluid-width()

ヒーローエリアのタイトルの行幅なども fluid にしておくと

PCだけやたら長くなってしまう問題を避けられます。

.hero-title {
  @include fluid-width(260px, 720px);
}
  • SPではそこまで幅を取らず
  • PCでは適度に広がる

という挙動を、メディアクエリを書かずに実現できます。


5. 実務での使い方サンプル

ここからは、もう少し実務寄りのコード例をまとめておきます。

5-1. WordPress + ブロックエディタ用のタイポグラフィ

WordPress案件の場合、

「ブロックエディタの見出しとフロント側の見出しを合わせたい」

というニーズがよく出てきます。

SCSS側でfluidを使いつつ、エディタ用CSSにも同じミックスインを使えば

かなり楽に運用できます。

// theme/scss/_editor.scss

@use "../utils/scss/fluid" as fluid;

.editor-styles-wrapper {
  h1 {
    @include fluid.fluid-font(26px, 38px);
  }
  h2 {
    @include fluid.fluid-font(22px, 32px);
  }
}

フロント用の style.css 側でも 全く同じミックスインを呼べば、

エディタとフロントでズレない設計になります。


5-2. 工数削減用のマップ設計

さらに踏み込んで、「タイポスケール全部をマップ化」しておき、

ループで吐き出すパターンもよくあります。

$fluid-type-scale: (
  "h1": (min: 28px, max: 40px),
  "h2": (min: 24px, max: 32px),
  "h3": (min: 20px, max: 28px),
  "body": (min: 14px, max: 16px)
);

@each $name, $sizes in $fluid-type-scale {
  .u-fluid-#{$name} {
    @include fluid.fluid-font(map-get($sizes, min), map-get($sizes, max));
  }
}


これで、HTML側では

<h2 class="u-fluid-h2">見出し</h2>
<p class="u-fluid-body">本文テキスト...</p>

のように、ユーティリティクラスとしても使えるようになります。


5-3. ACF+カスタムブロックとの組み合わせ

ACFブロックやカスタムブロックで

「タイトル・リード・ボタン付きのカード」をよく作る場合も、

fluidユーティリティはかなり役立ちます。

.block-hero-card {
  .block-hero-card__title {
    @include fluid.fluid-font(24px, 34px);
  }

  .block-hero-card__lead {
    @include fluid.fluid-font(16px, 20px);
  }

  .block-hero-card__btn {
    @include fluid.fluid-font(14px, 16px);
    @include fluid.fluid-space(padding-inline, 16px, 24px);
  }
}

ブロックが増えても、「数字を変えるだけ」で済むのが地味に効きます。


6. clampベースのfluid設計をSCSSで包むメリット

「いや、素のCSSで clamp() 直書きすればよくない?」

という気持ちも分かります。

が、実務では SCSSラップのメリットがかなり大きいです。

6-1. 数字遊びを関数に押し込める

clamp() を毎回手で組み立てると、

どうしてもこういう地味なストレスが溜まります。

  • 4つの数字を渡す → min font、max font、min vw、max vw
  • 傾きと切片の計算が地味に面倒
  • 単位の整合性も気にする必要がある

この「計算どこかに閉じ込めたい欲」を

きれいに満たしてくれるのが fluid() 関数です。


6-2. プロジェクト内のバラつきを抑えられる

チーム開発でありがちなのが、

  • 人によって clamp() の書き方や考え方がバラバラ
  • ある箇所は375〜1440、別の箇所は320〜1024で計算されている
  • remにする人、pxのままの人

という「何となく揃ってない」状態です。

SCSSユーティリティとして

  • デフォルトのmin/max幅
  • 単位の扱い
  • 計算方法

を固定化してしまえば、

「この案件のfluidは、基本全部この関数で出す」

とルール化しやすくなります。


6-3. 古いブラウザへのフォールバックも一括管理

IEを完全に切り捨てられる案件は増えましたが、

業種によっては「古いタブレットが現役」というケースもあります。

fluid() 関数の内部で

  • clamp() を返す
  • ついでに先に font-size: $min; を出力しておく

といった工夫をしておけば、

@mixin fluid-font(...) {
  font-size: $min; // ここが古いブラウザ用のフォールバック
  font-size: fluid(...); // clampを返す
}

のように「古いブラウザは固定サイズ」という安全な挙動にできます。


7. よくあるハマりポイントとガードの入れ方

fluidユーティリティを書く時に

やっておくと幸せになれる防御テクをいくつか。

7-1. 単位の混在チェック

よくあるミス:

@include fluid-font(16px, 2rem); // minとmaxの単位が違う

これを防ぐには、関数内で unit() を使ってチェックし

違っていたら @error を投げるのが王道です。

@function fluid($min, $max, $min-vw: $fluid-min-vw, $max-vw: $fluid-max-vw) {
  @if unit($min) != unit($max) {
    @error "fluid(): $min と $max の単位は揃えてください。";
  }

  // 以降、計算処理...
}

ビルド時にエラーが出るので、

本番で「なんか変だけど原因が分からない」という事態を避けられます。


7-2. min > max の逆転

これもありがちです。

@include fluid-font(32px, 18px); // 逆

これも @if $min > $max { @error … } で潰せます。


7-3. 極端なmin/max幅

ビューポート幅に対して

  • 極端に狭い
  • 極端に広い

数値を設定してしまうと、

想定どおりの挙動にならないことがあります。

$fluid-min-vw / $fluid-max-vw を変数化しておき、

プロジェクトの最初にチームで決めておくと事故りにくいです。


8. WordPress案件への導入パターン

実務フロントエンド目線でいうと、

utils/scss/fluid は以下のように組み込むのが定番です。

8-1. SCSS構成に組み込む

例:

scss/
  utils/
    _variables.scss
    _mixins.scss
    _functions.scss
    fluid/
      _variables.scss
      _functions.scss
      _mixins.scss
      _index.scss
  base/
    _reset.scss
    _typography.scss
  components/
    _buttons.scss
    _cards.scss
  pages/
    _front-page.scss
    _single.scss
  style.scss
@use "utils/fluid" as fluid;

しておき、あとは各所で fluid.fluid-font() を呼ぶイメージです。


8-2. ブロックテーマ(FSE)との併用

FSEの場合、

  • theme.json 側で基本のtypographyを定義
  • SCSS側で「特定ブロックだけfluidにする」

というハイブリッド運用もよくあります。

theme.json の値を基準にして

SCSS内のfluidのmin/maxを決める、といった設計も可能です。


8-3. メンテ時のメリット

あとから

  • 「全体的にPCの文字ちょっと大きくして」
  • 「SP時の余白を気持ち減らしたい」

などの要望が来たとき、

$fluid-min-vw / $fluid-max-vw や

$fluid-type-scale のマップを書き換えるだけで

一括調整できるのはかなり強力です。


9. 一緒に押さえておくと強い関連トピックと学習リソース

最後に、この fluid ユーティリティを理解した上で

一緒に押さえておくと強いトピックと、参考になる外部記事をいくつか挙げておきます。

9-1. clampの数式をちゃんと理解する

  • clamp(最小値, 好ましい値, 最大値) の「好ましい値」に vw と rem をどう組み合わせるか
  • 任意のビューポート幅に対して 「この時にこのフォントサイズ」となるように式を立てる方法

は、Smashing Magazine の記事が非常に丁寧です。


9-2. Sassでのタイプスケール生成

moderncss.dev の記事では、

Sassでタイプスケールやfluid typographyを生成する方法が

かなり具体的に紹介されています。

utils/scss/fluid のようなユーティリティを書くときも、

ここで紹介されている「マップ+ループ」の考え方がそのまま応用できます。


9-3. container queries × fluidのこれから

今後は @container と

コンテナクエリ系の単位(cqw など)と組み合わせることで、

「ビューポート幅ではなく、

親コンテナの幅に応じてfluidに動く」

設計も主流になっていきます。

今書いているfluidユーティリティも、

  • まずはビューポートベース
  • 将来的にコンテナベースに移行可能な抽象度

で作っておくと長生きしやすいです。


まとめ:

utils/scss/fluid

 は「デザインと実装の橋渡し」をしてくれる

今回、GitHub上の実ファイルはツールの制約で中身を直接読めませんでしたが、

  • ディレクトリ名
  • 一般的なfluidユーティリティの設計
  • clampを使った現代的なfluid実装のトレンド

から逆算すると、utils/scss/fluid はおそらく

「デザイナーがくれたpx指定を、

自然なfluid挙動に変換してくれるSCSSの小さな頭脳」

のような役割を担っているはずです。

もしあなたの案件でも

  • 画面幅ごとのフォントサイズ指定が多い
  • 余白やコンテナ幅の調整が毎回手作業
  • clampを書きたくない

という状況があるなら、

ここで紹介したような構成をベースに

自分専用の utils/scss/fluid を作ってみる価値はかなり高いと思います。

(Visited 1 times, 1 visits today)