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

 

displayでは、u-d-blockやu-d-md-noneなど、「u-d」の接頭辞で、また、flex / gridで使用するgapは、u-gap-48やu-gap-r-60など「u-gap」の接頭辞で、各ユーティリティーを作成します

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

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

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

ゴール

  • media queryのサイズによる階層的な適用が確実にされること
  • display
    • grid系で均等分割の設定が行えること
  • gap
    • オリジナル名称の設定を作成すること
    • ピクセルごとの設定を作成すること

前提

foundation/variable

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

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

$gaps: (
  sm: (48, 46, 44),
  md: (60, 58, 56),
  lg: (80, 78, 76),
);

foundation/mixin

@use 'sass:map';

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

使用法

display

基本

.u-d-{display値}
.u-d-{$break-points}-{display値}

grid / inline-grid

.u-d-{display値}-{均等分割数}
.u-d-{$break-points}-{display値}-{均等分割数}

パラメータ

{display値} … 'none', 'block', 'inline', 'flex', 'inline-flex', 'grid', 'inline-grid'

{均等分割数} … grid / inline-gridの場合のみ有効 で、1及び3~10まで。指定ない場合は均等2分割

gap

オリジナル名称の設定

.u-gap-{$gaps}

ピクセルごとの設定

.u-gap-{サイズ}
.u-gap-{$break-points}-{サイズ}
.u-gap-{タイプ}-{サイズ}
.u-gap-{タイプ}-{$break-points}-{サイズ}

パラメータ

{display値} … 'none', 'block', 'inline', 'flex', 'inline-flex', 'grid', 'inline-grid'

{タイプ} … c: column-gap、r: row-gap

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

使用例

display

<div class="u-d-grid-4 u-d-grid-lg-3 u-d-grid-md-1">
・・・
</div>

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

  • 1025px以上:「u-d-grid-4」で4分割
  • 821~1024px:「u-d-grid-lg-3」で3分割
  • 820px以下:「u-d-grid-md-1」で1分割
<br class="u-d-none u-d-block u-d-none" />

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

  • 1025px以上:改行なし
  • 821~1024px:改行あり
  • 820px以下:改行なし

gap

<div class="u-d-grid-3 u-gap-r-36 u-gap-c-24">
・・・
</div>

上記では、gridの3分割の状態になり、下記のようになります

  • 縦方向のgap:row-gapが3.6rem
  • 横方向のgap:column-gapが2.4rem
<div class="u-d-grid-3 u-gap-sm">
・・・
</div>

上記では、gridの3分割の状態になり、画面幅により下記のようになります

  • 1025px以上:gapが縦横4.8rem
  • 821~1024px:gapが縦横4.6rem
  • 820px以下:gapが縦横4.4rem

$gapsの設定は、現在下記となっていますが、この自由に設定を追加できます。また、後からそれぞれの設定を変更すれば、一気に更新することもできます。

$gaps: (
  sm: (48, 46, 44),
  md: (60, 58, 56),
  lg: (80, 78, 76),
);

最終形

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

display

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

// -----------------------------------------------------------------
// Display
// -----------------------------------------------------------------
$array: ('none', 'block', 'inline', 'flex', 'inline-flex', 'grid', 'inline-grid');
.u-d {
  @each $breakpoint, $query in $break-points {
    @include mq($breakpoint) {
      @each $key in $array {
        @if $breakpoint=='all' {
          &-#{$key} {
            display: #{$key} !important;
            @if $key == 'grid' or $key=='inline-grid' {
              @for $i from 2 through 10 {
                @if $i==2 {
                  grid-template-columns: repeat($i, 1fr) !important;
                } @else {
                  &-#{$i} {
                    display: #{$key};
                    grid-template-columns: repeat($i, 1fr) !important;
                  }
                }
              }
            }
          }
        } @else {
          &-#{$breakpoint}-#{$key} {
            display: #{$key} !important;
            @if $key == 'grid' or $key=='inline-grid' {
              @for $i from 2 through 10 {
                @if $i==2 {
                  grid-template-columns: repeat($i, 1fr) !important;
                } @else {
                  &-#{$i} {
                    display: #{$key};
                    grid-template-columns: repeat($i, 1fr) !important;
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

gap

@use 'sass:map';

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

// -----------------------------------------------------------------
// Gap
// -----------------------------------------------------------------
$array: (
  c: 'column',
  r: 'row'
);
.u-gap {
  @each $breakpoint, $query in $break-points {
    @include mq($breakpoint) {

      // オリジナル名称の設定
      @each $name, $values in $gaps {
        $num: index(map.keys($break-points), $breakpoint);
        &-#{$name} {
          #{gap}: #{Rem(nth($values, $num))} !important;
        }
        @each $key, $type in $array {
          &-#{$key}-#{$name} {
            #{$type}-gap: #{Rem(nth($values, $num))} !important;
          }
        }
      }

      // ピクセルごとの設定
      @for $i from 1 through 100 {
        @if $breakpoint == 'all' {
          &-#{$i} {
            gap: Rem($i) !important;
          }
          @each $key, $type in $array {
            &-#{$key}-#{$i} {
              #{$type}-gap: Rem($i) !important;
            }
          }
        } @else {
          &-#{$breakpoint}-#{$i} {
            gap: Rem($i) !important;
          }
          @each $key, $type in $array {
            &-#{$key}-#{$breakpoint}-#{$i} {
              #{$type}-gap: Rem($i) !important;
            }
          }
        }
      }
    }
  }
}

解説

上記最終系を一つずつ見ていきます。下記はdisplay及びgapで同じです

ループ設定

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

上記$break-pointsをループして展開していきます(gapの場合は、u-dの部分はu-gapとなります。以下同様)

.u-d {
  @each $breakpoint, $query in $break-points {
    @include mq($breakpoint) {
・・・
  }
}

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

.u-d {
 // 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」を大きいサイズから設定していことです

これにより、画面幅が小さくなるにつれ、後述の設定が生きてくることになります。

詳細クラスの設定

display

$array: ('none', 'block', 'inline', 'flex', 'inline-flex', 'grid', 'inline-grid');

上記$arrayを展開し、各classを作成していきます

.u-d {
  @each $breakpoint, $query in $break-points {
    @include mq($breakpoint) {
      @each $key in $array {
        @if $breakpoint=='all' {
          &-#{$key} {
            display: #{$key} !important;
            @if $key == 'grid' or $key=='inline-grid' {
              @for $i from 1 through 10 {
                @if $i==2 {
                  grid-template-columns: repeat($i, 1fr) !important;
                } @else {
                  &-#{$i} {
                    display: #{$key};
                    grid-template-columns: repeat($i, 1fr) !important;
                  }
                }
              }
            }
          }
        } @else {
          &-#{$breakpoint}-#{$key} {
            display: #{$key} !important;
            @if $key == 'grid' or $key=='inline-grid' {
              @for $i from 1 through 10 {
                @if $i==2 {
                  grid-template-columns: repeat($i, 1fr) !important;
                } @else {
                  &-#{$i} {
                    display: #{$key};
                    grid-template-columns: repeat($i, 1fr) !important;
                  }
                }
              }
            }
          }
        }
    }
  }
}

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

@each $key in $array {

displayプロパティの値の一覧です。よく使う値があれば、追加してください

@if $breakpoint=='all' {
・・・
} @else {
・・・
}

$break-points配列のキーがallの場合とそれ以外に振り分けています

allは、media queryに左右されない値を設定するために、独自に設定したものです

@if $breakpoint=='all' {
  &-#{$key} {
    display: #{$key} !important;
 ・・・
  }
} @else {
  &-#{$breakpoint}-#{$key} {
    display: #{$key} !important;
  }
 ・・・
}

上記で、をつかった「文字列補間(String Interpolation)」の「&-#{$key}」は、「#{$key}」の$keyに$arrayの値が一つずつ設定されます。

また、「display: #{$key} !important;」も同様に$keyに$arrayの値が一つずつ設定されます。

下記のように展開されるイメージです

// all
.u-d-none {
 display: none !important;
}
// lg
@media 'screen and (max-width: 1024px)' {
 .u-d-none {
  display: none !important;
 }
}
// md
@media 'screen and (max-width: 820px)' {
 .u-d-none {
   display: none !important;
 }
}
・・・
// all
.u-d-inline-grid
 display: inline-grid !important;
}
// lg
@media 'screen and (max-width: 1024px)' {
 .u-d-inline-grid
   display: inline-grid !important;
 }
}
// md
@media 'screen and (max-width: 820px)' {
 .u-d-inline-grid
   display: inline-grid !important;
 }
}

さらに「grid」と「inline-grid」の場合のみ分割数を設定できるようにしています

@for $i from 1 through 10 {
 @if $i==2 {
  grid-template-columns: repeat($i, 1fr) !important;
 } @else {
  &-#{$i} {
   display: #{$key};
   grid-template-columns: repeat($i, 1fr) !important;
  }
 }
}

上記のループは1~10としています。1は狭いサイズの場合に使用することを想定しています

また、「2」をデフォルトとして設定し、1及び3~10が「-3」のように設定できるようにしています

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

・・・
// all
.u-d-grid-1 {
 display: grid !important;
 grid-template-columns: repeat(1, 1fr) !important;
}
.u-d-grid {
 display: grid !important;
 grid-template-columns: repeat(2, 1fr) !important;
}
.u-d-grid-3 {
 display: grid !important;
 grid-template-columns: repeat(3, 1fr) !important;
}
.u-d-grid-4 {
 display: grid !important;
 grid-template-columns: repeat(4, 1fr) !important;
}
・・・
// lg
@media 'screen and (max-width: 1024px)' {
 .u-d-lg-grid-1 {
  display: grid !important;
  grid-template-columns: repeat(1, 1fr) !important;
 }
 .u-d-lg-grid {
  display: grid !important;
  grid-template-columns: repeat(2, 1fr) !important;
 }
 .u-d-lg-grid-3 {
  display: grid !important;
  grid-template-columns: repeat(3, 1fr) !important;
 }
 .u-d-lg-grid-4 {
  display: grid !important;
  grid-template-columns: repeat(4, 1fr) !important;
 }
・・・
}
// md
@media 'screen and (max-width: 820px)' {
 .u-d-md-grid-1 {
  display: grid !important;
  grid-template-columns: repeat(1, 1fr) !important;
 }
 .u-d-md-grid {
  display: grid !important;
  grid-template-columns: repeat(2, 1fr) !important;
 }
 .u-d-md-grid-3 {
  display: grid !important;
  grid-template-columns: repeat(3, 1fr) !important;
 }
 .u-d-md-grid-4 {
  display: grid !important;
  grid-template-columns: repeat(4, 1fr) !important;
 }
}
・・・

gap

オリジナル名称の設定

配列「$gaps」を展開していきます

$gaps: (
  sm: (48, 46, 44),
  md: (60, 58, 56),
  lg: (80, 78, 76),
);

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

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

.u-gap {
  @each $breakpoint, $query in $break-points {
    @include mq($breakpoint) {
      @each $name, $values in $gaps {
        $num: index(map.keys($break-points), $breakpoint);
        &-#{$name} {
          gap: #{Rem(nth($values, $num))} !important;
        }
        @each $key, $type in $array {
          &-#{$key}-#{$name} {
            #{$type}-gap: #{Rem(nth($values, $num))} !important;
          }
        }
      }
    }
  }
}

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

@each $name, $values in $gaps {

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

$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} {」は、$gapsの最初のキーのsmを使用して「&-sm {」となり、結果として「.u-gap-sm」が作成されます

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

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

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

次にcolumとrowの設定を追加しています

$array: (c: 'column', r: 'row');
@each $key, $type in $array {
 &-#{$key}-#{$name} {
  #{$type}-gap: #{Rem(nth($values, $num))} !important;
 }
}

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

// all
.u-gap-sm {
 gap: 4.8rem !important;
}
.u-gap-c-sm {
 gap: 4.8rem !important;
}
.u-gap-r-sm {
 gap: 4.8rem !important;
}
// lg
@media 'screen and (max-width: 1024px)' {
 .u-gap-sm {
  gap: 4.6rem !important;
 }
 .u-gap-c-sm {
  gap: 4.6rem !important;
 }
 .u-gap-r-sm {
  gap: 4.6rem !important;
 }
}
// md
@media 'screen and (max-width: 820px)' {
 .u-gap-sm {
  gap: 4.4rem !important;
 }
 .u-gap-c-sm {
  gap: 4.4rem !important;
 }
 .u-gap-r-sm {
  gap: 4.4rem !important;
 }
}
・・・

ピクセルごとの設定

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

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

.u-gap {
  @each $breakpoint, $query in $break-points {
    @include mq($breakpoint) {
      @for $i from 1 through 100 {
        @if $breakpoint == 'all' {
          &-#{$i} {
            gap: Rem($i) !important;
          }
          @each $key, $type in $array {
            &-#{$key}-#{$i} {
              #{$type}-gap: Rem($i) !important;
            }
          }
        } @else {
          &-#{$breakpoint}-#{$i} {
            gap: Rem($i) !important;
          }
          @each $key, $type in $array {
            &-#{$key}-#{$breakpoint}-#{$i} {
              #{$type}-gap: Rem($i) !important;
            }
          }
        }
      }
    }
  }
}

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

@for $i from 1 through 100 {

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

@if $breakpoint=='all' {

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

下記が展開イメージです

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

まとめ

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

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

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

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

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

コーポレートサイト

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

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

実績

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

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

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

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

ホームページ制作実績

コーポレートサイトへ