フォントを1行でレスポンシブ化するclamp()を、SCSSで設定する方法

Clamp()は、最小値(min)・推奨値(preferred)・最大値(max)の3つの値を設定して、
基本は推奨値を取りつつ、
- 推奨値が最小値より小きくなった場合は最小値
- 推奨値が最大値より大きくなった場合は最大値
となる、レスポンシブ対応に便利なCSSの関数です。
font-size: clamp(min, preferred, max);
今回は、ジェネレータや自力で計算する以外に、
SCSSで計算式を用意して、
フォントの最小値と最大値を入れるだけで
clamp()の式を出す仕組みをつくりたいと思います。
Clamp()の計算方法とSCSS
早速ですが、なめらかに移行するclamp()の計算式を、
vw、remの単位で表したscssの式はこちらになります。
$min-width: 375px;
$max-width: 1280px;
// 単位を除去
@function strip-unit($value) {
@return $value / ($value * 0 + 1);
}
//pxからremに換算
@function rem($px) {
@return strip-unit($px) / 16;
}
@function fluid-font($min-px, $max-px) {
$min-rem: rem($min-px);
$max-rem: rem($max-px);
$min-vp: strip-unit($min-width);
$max-vp: strip-unit($max-width);
// 中央値(推奨値)の式
$slope: ($max-rem - $min-rem) / ($max-vp - $min-vp) * 100;
$intercept: $min-rem - ($slope * $min-vp / 100);
@return clamp(
#{$min-rem}rem,
#{$intercept}rem + #{$slope}vw,
#{$max-rem}rem
);
}
使用例としては、例えばcssで
h3 {
font-size: fluid-font(16px, 24px);
}
と入れると、次のように出力されます。
h3 {
font-size: clamp(1rem, 0.75rem + 1.25vw, 1.5rem);
}
SCSSの推奨値の式の解説
先ほどのscssの式について、下記の推奨値の箇所について補足したいと思います。
$slope: ($max-rem - $min-rem) / ($max-vp - $min-vp) * 100;
$intercept: $min-rem - ($slope * $min-vp / 100);
@return clamp(
#{$min-rem}rem,
#{$intercept}rem + #{$slope}vw,
#{$max-rem}rem
);
clamp()の計算式の詳細については、
CSSのclamp()関数と、フォントサイズの設定方法で書きました。
上記の内容から、clamp()の基本式はこのように表すことができます。
clamp(min-size, min-size + ((max-size - min-size) / (max-vp - min-vp)) * (current-vp - min-vp), max-size)
current-width=100vwなので、推奨値(preferred)は
((max-size – min-size) / (max-vp – min-vp)) * (100vw – min-vp) で表現できます。
$slope: ($max-rem – $min-rem) / ($max-vp – $min-vp) * 100;とすると、
preferred = $slope * vw + ($min-rem – $slope * $min-vp / 100)
さらに、
$intercept: $min-rem – ($slope * $min-vp / 100); もつかうと
preferred = $slope * vw + $interceptになります。
SCSSの応用①: 設定済みのBreakpointsからclamp()値を出す
次に、さきほどのscssをベースにして、$min-width と $max-width を直接数値ではなく、
すでに設定済みのBreakpoints から取得できるように SCSS をアレンジしてみます。
$breakpoints: (
sm: 375px,
md: 768px,
lg: 1280px
);
// 単位を除去
@function strip-unit($value) {
@return $value / ($value * 0 + 1);
}
// pxをremに変換
@function rem($px) {
@return strip-unit($px) / 16;
}
// breakpoint 値を取得
@function get-breakpoint($name) {
@if map-has-key($breakpoints, $name) {
@return map-get($breakpoints, $name);
} @else {
@error "ブレークポイント「#{$name}」が未定義です";
}
}
// フルードフォントの関数
@function fluid-font($min-px, $max-px, $min-breakpoint: sm, $max-breakpoint: lg) {
$min-rem: rem($min-px);
$max-rem: rem($max-px);
$min-vp: strip-unit(get-breakpoint($min-breakpoint));
$max-vp: strip-unit(get-breakpoint($max-breakpoint));
// 中央値(推奨値)の式
$slope: ($max-rem - $min-rem) / ($max-vp - $min-vp) * 100;
$intercept: $min-rem - ($slope * $min-vp / 100);
@return clamp(
#{$min-rem}rem,
#{$intercept}rem + #{$slope}vw,
#{$max-rem}rem
);
}
このようにすると、デフォルトではsmとlgの幅を使って計算、また他の幅を指定することも可能なcssを出すことができます。
/*使用例*/
h1 {
font-size: fluid-font(20px, 32px); // sm → lg を基準に計算
}
p {
font-size: fluid-font(14px, 18px, sm, md); // sm → md を基準に計算
}
SCSSの応用②: 3つの文字サイズからclamp()値を出す
今までスマホ〜PCなど、2つの値の間を遷移するclamp()を出す式をご紹介しました。
さらに、タブレット時のフォントサイズも指定し、3つの値を一度に設定して滑らかに遷移するSCSSを考えてみます。
スマホ、PC、タブレットと、3つのフォントサイズを指定したい場合、clamp()単体では処理できないため、メディアクエリもつかって、2段階で書いていきます。
$breakpoints: (
sm: 375px,
md: 768px,
lg: 1280px
);
// 単位を除去
@function strip-unit($value) {
@return $value / ($value * 0 + 1);
}
// px → rem 変換
@function rem($px) {
@return strip-unit($px) / 16;
}
// breakpoint 値を取得
@function get-breakpoint($name) {
@if map-has-key($breakpoints, $name) {
@return map-get($breakpoints, $name);
} @else {
@error "ブレークポイント「#{$name}」が未定義です";
}
}
// フルードフォント計算
@function fluid-font($min-px, $max-px, $min-breakpoint: sm, $max-breakpoint: lg) {
$min-rem: rem($min-px);
$max-rem: rem($max-px);
$min-vp: strip-unit(get-breakpoint($min-breakpoint));
$max-vp: strip-unit(get-breakpoint($max-breakpoint));
$slope: ($max-rem - $min-rem) / ($max-vp - $min-vp) * 100;
$intercept: $min-rem - ($slope * $min-vp / 100);
@return clamp(
#{$min-rem}rem,
#{$intercept}rem + #{$slope}vw,
#{$max-rem}rem
);
}
// 範囲別に適用する mixin
@mixin fluid-font-2step($sm-px, $md-px, $lg-px) {
// sm〜md の範囲
font-size: fluid-font($sm-px, $md-px, sm, md);
// md〜lg の範囲
@media screen and (min-width: #{get-breakpoint(md)}) {
font-size: fluid-font($md-px, $lg-px, md, lg);
}
}
このように設定すると、例えばCSSでよびだした場合
h3 {
@include fluid-font-2step(16px, 20px, 24px);
}
下記のように出力されます。
h3 {
font-size: clamp(1rem, 1.3333vw + 0px, 1.25rem);
}
@media screen and (min-width: 768px) {
h3 {
font-size: clamp(1.25rem, 1.25vw + 0.25rem, 1.5rem);
}
}
その場合、滑らかに下記のような2段階の遷移をするフォントサイズになっています。
- スマホ(375px)〜 タブレット(768px)で
16px → 20px
- タブレット(768px)〜 PC(1280px)で
20px → 24px
clamp()を、SCSSで設定する方法まとめ
以上、画面幅に応じた滑らかなフォントサイズになるclamp()を
SCSSで設定する方法についてご紹介しました。
基本的にはスマホ、PCの2サイズを設定しつつ、
不具合がある場合はタブレット時のサイズも調整する、
ということが多いかな?と思いますが、
2つのフォントサイズの場合、3つのフォントサイズの場合を書いてみました。
clamp()自体、基本的にどの主要ブラウザでも対応しているので、
スッキリさせつつ見やすいフォント設計に
役立つことがあれば幸いです!