Scss/flocssで自作ユーティリティー width編

 

u-w-fullやu-w-50pなど「u-w」の接頭辞がついた、ユーティリティーを作成します

フォルダ構成やutilityの適用順などはflocssを基準にしています

社内のコーディング共通フォーマットとして少しずつ独自の改良をしてきた設定です

下記もあわせてご覧ください

ゴール

  • media queryのサイズによる階層的な適用が確実にされること
  • オリジナル名称の設定を作成すること
  • 100% / fit-content設定ができること
  • ピクセル単位で設定ができること
  • %で設定ができること

前提

foundation/variable

使用しないbreak pointを入れておくと無駄な設定ができてしまいますので、注意してください

$break-points: (
  all: '',
  lg: 'screen and (max-width: 1024px)',
  md: 'screen and (max-width: 820px)',
) !default;

$widths: (
  sm: (100, 98, 96),
  md: (150, 148, 146),
  lg: (200, 198, 196),
);

foundation/mixin

@use 'sass:map';
@use 'sass:math';

@function Rem($size) {
  @return math.div($size, 10) + rem;
}

@mixin mq($breakpoint: md) {
  @if($breakpoint == 'all') {
    @content;
  } @else {
    @media #{map.get($break_points, $breakpoint)} {
      @content;
    }
  }
}

使用法

オリジナル名称の設定

.u-w-{$widths}

100%設定

.u-w-full
.u-w-{$break-points}-full

fit-content設定

.u-w-fit
.u-w-{$break-points}-fit

ピクセル設定

.u-w-{数値}
.u-w-{$break-points}-{数値}

%設定

.u-w-{%数値}p
.u-w-{$break-points}-{%数値}p

パラメータ

{数値} … 0~1000

{%数値} … 1~99

{$widths}は、上記前提を参照

使用例

<div class="u-w-50p u-w-lg-80p u-w-md-full">
・・・
</div>

上記では、画面幅により下記のようになります

  • 1025px以上:widthが50%
  • 821~1024px:widthが80%
  • 820px以下:widthが100%
<button type="button" class="u-w-sm">
・・・
</div>

上記では、画面幅により下記のようになります

  • 1025px以上:widthが10rem
  • 821~1024px:widthが9.8rem
  • 820px以下:widthが9.6rem
$widths: (
  sm: (100, 98, 96),
  md: (150, 148, 146),
  lg: (200, 198, 196),
);

$widthsの設定は、この名称は自由に作成できるため、例えば、button-submitやbutton-returnなどの設定を作成することで、複数の幅設定も作成できます。

<button type="button" class="u-w-sm u-w-md-full">
・・・
</div>

break pointのmdだけ100%にしたい場合は、試していませんが、上記で書き順的には行けると思います

最終形

上記の前提は、各環境にあわせ別ファイルとして振り分け、下記ファイルで読み込んでください

@use 'sass:map';

@use '../../foundation/variable' as *;
@use '../../foundation/mixin' as *;

.u-w {
  @each $breakpoint, $query in $break-points {

    // $widthsのkey名で設定
    @each $name, $values in $widths {
      $num: index(map.keys($break-points), $breakpoint);
      &-#{$name} {
        width: #{Rem(nth($values, $num))} !important;
      }
    }

    // 100% / fit
    @include mq($breakpoint) {
      @if $breakpoint=='all' {
        &-full {
          width: 100% !important;
        }
        &-fit {
          width: fit-content !important;
        }
      } @else {
        &-#{$breakpoint}-full {
          width: 100% !important;
        }
        &-#{$breakpoint}-fit {
          width: fit-content !important;
        }
      }
    }

    // 0~100rem
    @for $i from 0 through 1000 {
      @if $breakpoint=='all' {
        &-#{$i} {
          width: Rem($i) !important;
        }
      } @else {
        &-#{$breakpoint}-#{$i} {
          width: Rem($i) !important;
        }
      }
    }

    // 1~99%
    @for $i from 1 through 99 {
      @if $breakpoint=='all' {
        &-#{$i+"p"} {
          width: #{$i+"%"} !important;
        }
      } @else {
        &-#{$breakpoint}-#{$i+"p"} {
          width: #{$i+"%"} !important;
        }
      }
    }
  }
}

解説

上記最終系を一つずつ見ていきます。

ループ設定

$break-points: (
  all: '',
  lg: 'screen and (max-width: 1024px)',
  md: 'screen and (max-width: 820px)',
) !default;

上記$break-pointsをループして展開していきます

.u-w {
  @each $breakpoint, $query in $break-points {
・・・
}

展開されるイメージは下記の通りです

.u-w {
 // all
 // lg
 @media 'screen and (max-width: 1024px)' {
 }
 // md
 @media 'screen and (max-width: 820px)' {
 }
}

最初の$breakpointは「all」となりますが、下記mixinでは、allの場合は、特に処理を行っていませんので空になります

@mixin mq($breakpoint: md) {
  @if($breakpoint == 'all') {
    @content;
  } @else {
    @media #{map.get($break_points, $breakpoint)} {
      @content;
    }
  }
}

ここでのポイントは、「$break-points」を大きいサイズから設定していことです

詳細クラスの設定

オリジナル名称の設定

配列「$font-sizes」を展開していきます

$widths: (
  sm: (100, 98, 96),
  md: (150, 148, 146),
  lg: (200, 198, 196),
);

$widthsにある各変数のカッコ内の数字は、$break-pointsの数と同じ数設定しています

したがって、ここは、左から「all」「lg」「md」のpxサイズを数値のみで設定しています

.u-w {
  @each $breakpoint, $query in $break-points {
    @each $name, $values in $widths {
      $num: index(map.keys($break-points), $breakpoint);
      &-#{$name} {
        width: #{Rem(nth($values, $num))} !important;
      }
    }
  }
}

上記ブロックの真ん中の部分を解説していきます

@each $name, $values in $widths {

$widthsをeach文で展開していますが、ここでは、最初は「$name」に「sm」が、「$values」には「(100, 98, 96)」が入ることになります

$num: index(map.keys($break-points), $breakpoint);

map.keysで$break-pointsのkeyだけの配列を作成しています。結果は「all, lg, md」となります

そしてindex関数で、「all, lg, md」の中でall(二つ目のループで最初の$breakpointは「all」)の位置を取得しています。ここでは「1」が$numとして設定されます

&-#{$name} {

「&-#{$name} {」は、$marginsの最初のキーのsmを使用して「&-sm {」となり、結果として「.u-w-sm」が作成されます

width: #{Rem(nth($values, $num))} !important;

「nth($values, $num)」では、nth関数で、$values、つまり「(14, 13, 12)」のうち、$numの値の順番(最初は「1」)にある値を取得し、Rem関数でremの値に変換しています

結果として「width: 20rem !important;」という記述が作成されます

下記が展開イメージとなります

// all
.u-w-sm {
 width: 10rem !important;
}
// lg
@media 'screen and (max-width: 1024px)' {
 .u-w-sm {
  width: 9.8rem !important;
 }
}
// md
@media 'screen and (max-width: 820px)' {
 .u-w-sm {
  width: 9.6rem !important;
 }
}
・・・

100% / fit-content 設定

したがって、ここは、左から「all」「lg」「md」のpxサイズを数値のみで設定しています

.u-w {
  @each $breakpoint, $query in $break-points {
    @include mq($breakpoint) {
      @if $breakpoint=='all' {
        &-full {
          width: 100% !important;
        }
        &-fit {
          width: fit-content !important;
        }
      } @else {
        &-#{$breakpoint}-full {
          width: 100% !important;
        }
        &-#{$breakpoint}-fit {
          width: fit-content !important;
        }
      }
    }
  }
}

下記が展開イメージとなります

// all
.u-w-full {
 width: 100% !important;
}
.u-w-fit {
 width: fit-content !important;
}
// lg
@media 'screen and (max-width: 1024px)' {
 .u-w-lg-full {
  width: 100% !important;
 }
 .u-w-lg-fit {
  width: fit-content !important;
 }
}
// md
@media 'screen and (max-width: 820px)' {
 .u-w-md-full {
  width: 100% !important;
 }
 .u-w-md-fit {
  width: fit-content !important;
 }
}

ピクセルごとの設定

次にピクセル単位の設定を行います

下記のループ部分は、上記と同じです。2番目のブロックについて解説します

.u-w {
  @each $breakpoint, $query in $break-points {
    @for $i from 0 through 1000 {
      @if $breakpoint=='all' {
        &-#{$i} {
          width: Rem($i) !important;
        }
      } @else {
        &-#{$breakpoint}-#{$i} {
          width: Rem($i) !important;
        }
      }
    }
  }
}

今回は、10~1000の数値で設定しています

@for $i from 1 through 1000 {

「@for $i from 1 through 1000」が0~1000までの数値をループし$iに1から順に数字を代入しています

@if $breakpoint=='all' {

上記同様allの場合の振り分けをしています

下記が展開イメージです

// all
.u-w-1 {
 width: 0.1rem !important;
}
// lg
@media 'screen and (max-width: 1024px)' {
 .u-w-lg-1 {
   width: 0.1rem !important;
 }
}
// md
@media 'screen and (max-width: 820px)' {
 .u-fs-md-1 {
   width: 0.1rem !important;
 }
}
・・・

%設定

次にピクセル単位の設定を行います

下記のループ部分は、上記と同じです。2番目のブロックについて解説します

.u-w {
  @each $breakpoint, $query in $break-points {
    @for $i from 1 through 99 {
      @if $breakpoint=='all' {
        &-#{$i+"p"} {
          width: #{$i+"%"} !important;
        }
      } @else {
        &-#{$breakpoint}-#{$i+"p"} {
          width: #{$i+"%"} !important;
        }
      }
    }
  }
}

今回は、1~99の数値で設定しています

@for $i from 1 through 99 {

「@for $i from 1 through 1000」が0~1000までの数値をループし$iに1から順に数字を代入しています

@if $breakpoint=='all' {

上記同様allの場合の振り分けをしています

下記が展開イメージです

// all
.u-w-1p {
 width: 1% !important;
}
// lg
@media 'screen and (max-width: 1024px)' {
 .u-w-lg-1p {
   width: 1% !important;
 }
}
// md
@media 'screen and (max-width: 820px)' {
 .u-fs-md-1p {
   width: 1% !important;
 }
}
・・・

まとめ

以上でwidthのユーティリティーの完成となります

全設定が吐き出されてしまうと膨大な量になってしまいますが、弊社では、vite+@fullhuman/postcss-purgecssなどを使って、余計なclassは入らないようにしていますので、そういった工夫も必要になるかと思います

コーディングの省力化に貢献できれば幸いです

文責:フライング・ハイ・ワークス代表 松田 治人(まつだ はるひと)
会社では、Laravelを中心としたエンジニアとして働いており、これまでに50本以上のLaravelによるWebアプリケーションの構築や東京でホームページ制作をしています。
エンジニアとして弊社で働きたい方、お仕事のご相談など、お待ちしております。

WEBサイト・ホームページの制作をご検討の方

コーポレートサイト

フライング・ハイ・ワークスの紹介

フライング・ハイ・ワークスは、東京のホームページ制作・Web制作会社・システム開発会社です。東京都及びその近郊(首都圏)を中心として、SEO対策を意識したPC及びスマホのサイトをワンソース(レスポンシブ対応)で制作します。

実績

デザイナーチームは、グラフィックデザインやイラストの制作も得意としており、著作権を意識しない素材の提供が可能です。システム・コーディングチームでは、Laravelなどを使用したスクラッチからのオリジナルシステム開発を始め、WordPressのカスタマイズを得意としております。

また、SEOやランディングページ(LP)、広告向けバナーなどを他社様でやっていた作業の引継ぎでも問題ありません。制作実績は多数ございますので、お客様に合わせたご提案が可能です。

500点以上のフライング・ハイ・ワークスの制作実績ページをご覧ください。

東京のWeb制作会社・ホームページ制作のお問い合わせ、お見積り依頼、相談、質問は
お問い合わせフォームよりお願いいたします

ホームページ制作実績

コーポレートサイトへ