【Sass】pxからremへ変換する関数の作り方|math.divで非推奨の「/」を回避

レスポンシブデザインやアクセシビリティの観点から、フォントサイズや余白をremで指定する場面が増えています。とはいえデザインデータはpx基準のことが多く、Sassでpxをremに変換する関数を用意しておくと便利です。ただし、昔よく使われた $px / $base * 1rem という書き方は、現在のDart Sassでは非推奨になっています。この記事では、非推奨警告が出ない正しい変換関数を、実行確認済みのコードで解説します。

この記事の結論:px→rem変換は math.div($px, $base) * 1rem で行います。除算に / を使う書き方は非推奨(Dart Sass 2.0で削除予定)のため、@use "sass:math"; を読み込んで math.div() を使います。
スポンサーリンク

基準のフォントサイズを決める

remはルート要素(html)のフォントサイズを基準にする単位です。ブラウザの初期値は 16px なので、これを基準値として変数に定義します。

基準フォントサイズの定義
@use "sass:math";

$base-font-size: 16px; // html のフォントサイズ

px→rem変換関数を作る(math.div)

pxをremに変換する関数を作ります。px同士の割り算は単位が打ち消し合って無単位の数値になるので、それに 1rem を掛けてrem値にします。

正しいpx→rem変換関数
@use "sass:math";

$base-font-size: 16px;

@function px-to-rem($px) {
  @return math.div($px, $base-font-size) * 1rem;
}

.element {
  font-size: px-to-rem(24px);              // => 1.5rem
  padding: px-to-rem(16px) px-to-rem(32px); // => 1rem 2rem
}
除算に / を使う書き方は非推奨です。@return $px / $base-font-size * 1rem; のように / で割ると、Dart Sassで「Using / for division is deprecated and will be removed in Dart Sass 2.0.0」という警告が出ます。割り算は必ず math.div() を使ってください。
関数の定義そのものの書き方は【Sass】関数を定義する方法、pxとvwなど単位が混ざってエラーになる場合は「Incompatible units」エラーの対処法が参考になります。

基準フォントサイズを引数で変えられるようにする

プロジェクトによって基準のフォントサイズが異なる場合は、デフォルト引数で基準値を渡せるようにしておくと再利用しやすくなります。

基準値を引数化した関数
@use "sass:math";

@function px-to-rem($px, $base: 16px) {
  @return math.div($px, $base) * 1rem;
}

.title { font-size: px-to-rem(32px); }        // 基準16px => 2rem
.note  { font-size: px-to-rem(15px, 15px); }  // 基準15px => 1rem

remを使う理由と62.5%テクニック

remはユーザーがブラウザで設定した文字サイズに追従するため、pxよりもアクセシビリティに優れます。固定pxだと、ユーザーが文字を大きくしても変わりません。

計算をラクにする定番テクニックが「62.5%トリック」です。htmlのフォントサイズを 62.5%(=16px×0.625=10px)にすると、1rem=10pxになり、pxとremの換算が「10で割るだけ」になります。

62.5%トリック
html {
  font-size: 62.5%; // 1rem = 10px
}

.box {
  font-size: 1.6rem; // = 16px
  padding: 2.4rem;   // = 24px
}
rem と em の違い:remは常にルート(html)のフォントサイズが基準なのに対し、emはその要素自身(または親)のフォントサイズが基準です。入れ子で値が累積しないぶん、remのほうが管理しやすく、サイズ指定では基本remが扱いやすくなります。

よくある質問(FAQ)

Qなぜ $px / $base * 1rem ではダメなのですか?
ADart Sassでは / による割り算が非推奨になり、将来のバージョン(2.0)で削除される予定だからです。現在のコンパイルでは警告が出ます。math.div($px, $base) * 1rem に書き換えてください。
Qpx-to-rem(24px) と px-to-rem(24) の違いは?
Apxを付けて渡すのが安全です。math.div(24px, 16px) はpx同士で単位が打ち消され無単位の 1.5 になり、* 1rem で正しく 1.5rem になります。単位なしの数値を扱いたい場合は数値から単位を除去する方法も参考にしてください。
Q結果の小数が長くなります。丸めたいです。
Amath.round() やカスタムの丸め関数と組み合わせます。四捨五入の詳しい方法はround()で四捨五入する方法を参照してください。
Qremとpx、どちらで指定すべきですか?
Aフォントサイズや余白はrem推奨です。ユーザーのブラウザ設定(文字サイズ)に追従でき、アクセシビリティが高まります。一方、ボーダーの太さなど「常に同じ見た目にしたい」ものはpxのままで構いません。

まとめ

Sassでのpx→rem変換のポイントを整理します。

  • 変換関数は math.div($px, $base) * 1rem@use "sass:math" が必要)
  • / による割り算は非推奨(Dart Sass 2.0で削除予定)
  • 基準値はデフォルト引数にしておくと再利用しやすい
  • remはユーザーの文字サイズ設定に追従でき、アクセシビリティに有利
  • 62.5%トリックで「1rem=10px」にすると換算がラクになる

関連として、関数を定義する方法数値から単位を除去する方法round()で四捨五入する方法もあわせて読むと、Sassの数値・単位処理に強くなれます。