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

Advertisements

Clamp()は、最小値(min)・推奨値(preferred)・最大値(max)の3つの値を設定して、
基本は推奨値を取りつつ、

  1. 推奨値が最小値より小きくなった場合は最小値
  2. 推奨値が最大値より大きくなった場合は最大値

となる、レスポンシブ対応に便利な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);
}
Advertisements

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 を基準に計算
}
Advertisements

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段階の遷移をするフォントサイズになっています。

  1. スマホ(375px)〜 タブレット(768px)で 16px → 20px
  2. タブレット(768px)〜 PC(1280px)で 20px → 24px

clamp()を、SCSSで設定する方法まとめ

以上、画面幅に応じた滑らかなフォントサイズになるclamp()を
SCSSで設定する方法についてご紹介しました。

基本的にはスマホ、PCの2サイズを設定しつつ、
不具合がある場合はタブレット時のサイズも調整する、
ということが多いかな?と思いますが、
2つのフォントサイズの場合、3つのフォントサイズの場合を書いてみました。

clamp()自体、基本的にどの主要ブラウザでも対応しているので、
スッキリさせつつ見やすいフォント設計に
役立つことがあれば幸いです!

Advertisements