🍑
ビューポートを基準として文字や余白のサイズを動的に変更するSCSSのmixin
モバイル端末とPC端末のデザインデータしかないけれどタブレットにも微妙に対応したいときに有用なのかなと思います。
CSS-Tricksの記事をベースに、こちらで紹介されていた関数を自分なりに改変させていただいています。ありがとうございます。
mixin
@use 'sass:map';
@use 'sass:math';
$min-width-mobile: 360px;
$min-width-pc: 1280px;
$base-font-size: 16;
@function strip-unit($num) {
@return math.div($num, ($num * 0 + 1));
}
@function divide-root($px) {
@return math.div(strip-unit($px), $base-font-size);
}
@function rem($px) {
@return divide-root($px) * 1rem;
}
/// @see https://css-tricks.com/linearly-scale-font-size-with-css-clamp-based-on-the-viewport/
/// @see https://firstlayout.net/fluidly-font-size-created-with-sass-and-clamp/
@function fluid-size($min-size, $max-size) {
$min-unit: rem($min-size);
$max-unit: rem($max-size);
$min-num: divide-root($min-size);
$max-num: divide-root($max-size);
$min-breakpoint: divide-root($base-width-mobile);
$max-breakpoint: divide-root($min-width-pc);
$slope: math.div(
math.div(math.round(($max-num - $min-num) * 100), 100),
math.div(math.round(($max-breakpoint - $min-breakpoint) * 100), 100)
);
$calc-rem: math.div(
math.round(($min-breakpoint * -1 * $slope + $min-num) * 1rem * 100),
100
);
$calc-vw: math.div(math.round(($slope * 100) * 1vw * 100), 100);
@return clamp($min-unit, $calc-rem + $calc-vw, $max-unit);
}
小数点第2位で丸めたくて熱心に100が登場してます。もっとすっきり書けそうな気がします。
使い方
@use '@styles/functions/fluid-size' as *;
padding-inline: fluid-size(12, 32);
挙動としては下記になります。
- 360pxのビューポートでは左右の余白が12px
- 360px - 1280pxのビューポートでは左右の余白が12px - 32pxの間で動的に変更
- 1280px以上のビューポートでは32pxで固定
素敵なところ
- すべて明示的に指定せずとも動的にサイズを変更してくれる。
- メディアクエリやコンテナクエリを書かずに一撃で済むのでむちゃ楽になる。
微妙なところ
-
1rem = 16px
の大前提に基づくので、ブラウザやOSの設定で文字のサイズを変更しているユーザーでは表示が崩れる可能性がある(ただしremである以上この件に限った話ではない)。 - 1pxや2pxなどの細い線は苦手な傾向がある(細い縦線が複数並んでいる場合、ビューポートによっては1pxのものと2pxのものが並ぶ可能性がある)。
まとめ
今のところはいい感じですが、もう少し運用してみて気付いたことがあったら追記します。
Discussion
round なら css に来てますね。