【CSS】俺のFLOCSSディレクトリとファイル構成のベース（個人用）

個人用のメモ。プロジェクトで共通化できる、FLOCSSのディレクトリやファイル設計について。

(参考)[FLOCSSの詳細や強度・考え方](https://qiita.com/yuta-38/items/19bc7d655145a0fcdca9#1-foundation%E3%83%AC%E3%82%A4%E3%83%A4%E3%83%BC)

<br>
##速度改善を目指したFLOCSS構造
FLOCSSの構造は基本に沿うが、ブラウザの読み込み速度改善のため、コンパイルするファイルは全体共通部分とページ毎に必要な部分で分ける。

(通常は、app.scssでまとめて@importして、コンパイルしたapp.cssを読み込む)


***

**`foundation`**　サイト**全体で共通のデフォルト設定**。
├ _normalize.scss　不要なデフォルトスタイルをリセット(reset.cssよりも軽量)
├ _base.scss　全体で共通のリセットスタイル
├ _variable.scss　変数をまとめるファイル
├ _mixin.scss　mixinをまとめるファイル
**`layout`**　全体で共通のページのレイアウト
├ **`grid`**  グリッド関連のCSSを保存（googleのマテリアルデザインを使用）
　├ _grid.scss
　├ _mixin.scss
　├ _variable.scss
├ _container.scss
├ _header.scss
├ _footer.scss
**`object`**　プロジェクト毎や再利用可能など細かいスタイルを保存するディレクトリ
├ **`component`**　いくつかのページで共通する**モジュール**
　├ _button.scss
　├ _link.scss
　├ …
├ **`project`**　ページ毎に固有のモジュール（他のページで使わない）
　├ **`top`**
　　├ _card.scss 
　　├ _profile.scss
　├ **`ページ名`**...
├ **`utility`** 強制的に適用するスタイル（!importantがつくもの）
　├ _display.scss
　├ _margin.scss
　├ _padding.scss
　├ _typography.scss
├ common_inview.scss　全体で共通のファーストビュー用のスタイル。
├ common_overview.scss　全体で共通のファーストビュー以外のスタイル。
├ top_inview.scss トップページ固有のファーストビュー用のスタイル。
├ top_overview.scss トップページ固有のファーストビュー以外のスタイル。
├ (ページ名)_inview.scss
├ (ページ名)_overview.scss

***


コンパイル対でないファイルの先頭には`_`をつけることで、間違ってコンパイルされることを防ぐ。

ポイントはinviewとoverviewを分けることでファストビューで使うスタイルのみ先に読み込み描画速度を上げていること。

詳しくは[クリティカルCSSとは？使い方](https://qiita.com/yuta-38/items/c6f92fdcfb8eaaaae157)を参照。


また、スタイルの読み込みをページ毎に共通のスタイル(common_inveiwとcommon_overview)とページ毎に使うスタイルだけにし、不要な記述を読み込まないようにする。


これをすることで、レンダリングブロックを回避し、各ページに対して必要なスタイルのみが提供されるので、ページの高速化につなげることができる。


##1. **`foundation`** ：サイト**全体で共通のデフォルト設定**

###1-1. _normalize.scss
hタグなどスタイルを初期化する。MIT Licenseのコードを使用。[公式ページ](https://github.com/necolas/normalize.css)からダウンロードできる。


**▽normalize.cssとreset.cssの違い**
normalize.cssはresetと異なり有効なスタイルを残している。


<br>
###1-2. _base.scss
全体で共通となるスタイルを指定。

```scss:_base.scss
html {
  height: 100%;
  font-size: 62.5%;
}

body {
  font-family: 'YuGothic', 'Noto Sans JP', 'Hiragino Kaku Gothic Pro', 'メイリオ', Meiryo, 'Roboto', Roboto, Osaka, sans-serif;
  display: flex;
  flex-flow: column;
  min-height: 100vh;
  color: text-color(base);
}

main { flex: 1; }

a {
  color: text-color(link01);
  text-decoration: none;
  cursor: pointer;
}

button {
  appearance: none;
  padding: 0;
  background-color: transparent;
  border: none;
  outline: none;
  cursor: pointer;
}

html, body,
p, ol, ul, li, dl, dt, dd,
blockquote, figure, fieldset, legend, textarea, pre, iframe,
h1, h2, h3, h4, h5, h6, hr {
  margin: 0;
  padding: 0;
}

ul, ol, li {
  list-style: none;
}
```

・`text-color(変数名)`
変数名で指定。別ファイルのvariable.scssに記述してある。




<br>
###1-3. _variable.scss
変数を記述するファイル。

```scss:_base.scss
// size
$sizes: tb, sp;

// font size
$fontSizes: 10, 12, 14, 16, 18, 20, 22, 24, 26, 28;

// text line
$lines: 2, 3, 4;

// space
$spaces: 0, 8, 16, 24, 32, 40;

// breakpoint
$breakpoints: (
  pc: 1280px
  tb: 960px,
  sp: 560px,
  min: 360px,
) !default;

// key color
$key-colors: (
  pink01: #f47aa9,
  pink02: #cb678d,
  black: #333,
  white: #fff,
);
@function key-color($key) {
  @return map-get($key-colors, $key);
}

// text color
$text-colors: (
  base: #333,
  white: #fff,
  gray: #999,
  link01: #0074ad,
  link02: #666,
  link02-hover: #333,
);
@function text-color($key) {
  @return map-get($text-colors, $key);
}

// btn color
$btn-colors: (
  normal: #fff,
  normal-hover: #333,
  cv: #f47aa9,
  cv-hover: rgba(244,122,169,.8),
);
@function btn-color($key) {
  @return map-get($btn-colors, $key);
}
```

text-colorやkey-colorは関数を定義し名前で色を呼び出せるようにする。

・関数の使い方
map-getメソッドを使うと複数のKey-Valueから指定したキー名をと一致する値を抜き出すことができる。

関数を用意して名前を付け、キー名を引数で渡す。

```scss:
@function 関数名(引数) {
  @return map-get(検索元の変数名, 引数で渡した変数名)
}
```


<br>
###1-4. _mixin.scss
mixin(どこでも呼び出せるコンポーネント）を定義するファイル。メディアクエリを定義するために使用。


```scss:_base.scss
$breakpoint-down: (
  'pc': 'screen and (max-width: #{map-get($breakpoints, 'pc')})',
  'tb': 'screen and (max-width: #{map-get($breakpoints, 'tb')})',
  'sp': 'screen and (max-width: #{map-get($breakpoints, 'sp')})',
  'min': 'screen and (max-width: #{map-get($breakpoints, 'min')})',
) !default;

@mixin mq($breakpoint: tb) {
  @media #{map-get($breakpoint-down, $breakpoint)} {
    @content;
  }
}
```

`$breakpoint-down`という変数の中でメディアクエリのパターンを作成する。

画面幅はvariable.scssに記述するためこのファイルは変更しない。

```scss:variable.scss
// breakpoint
$breakpoints: (
  pc: 1280px
  tb: 960px,
  sp: 560px,
  min: 360px,
) !default;
```

mqという名前のmixinを作成し、pc, tb, sp, minを指定すれば対応するメディアクエリを表示できるようにする。

なお、scssでの呼び出しは`@include mixin名(引数)`とする。

・`#{ }` 変数をそのまま表示する。

・`@content` mixinを呼び出した時に{ }の中に記述した内容を@contentの部分に表示する。



<br>
##2. **`layout`**　:全体で共通のページのレイアウト
グリッドシステムに関するファイルを保存する。グリッドシステムはgoogleのマテリアルデザインをカスタムしたものを使用。

グリッドシステムに関するmixinとvariableもこのフォルダの中にファイルを作成する。

>（参考）[Googleのマテリアルデザインのグリッドシステムを使う手順](https://qiita.com/yuta-38/items/efe68c154ccf3bcd5cee)


###2-1. gridディレクトリ

```scss:_grid.scss
/*
 * layout/grid/grid.scss
 */

@import './variables';
@import './mixins';

:root {
  @each $size in map-keys($grid-columns) {
    --grid-margin-#{$size}: #{map-get($grid-default-margin, $size)};
    --grid-gutter-#{$size}: #{map-get($grid-default-gutter, $size)};
    --grid-column-width-#{$size}: #{map-get($grid-column-width, $size)};
  }
}

// grid
.l-grid {
  max-width: 1024px;
  transition: all 0.25s;
  @each $size in map-keys($grid-columns) {
    @include grid-media-query_($size) {
      $margin: map-get($grid-default-margin, $size);
      $gutter: map-get($grid-default-gutter, $size);

      @include grid($size, $margin, $gutter);
    }
  }
}

.l-grid-cell {
  // default style
  min-height: 25px;

  // select the upper breakpoint
  $upper-breakpoint: nth(map-keys($grid-columns), 1);

  @each $size in map-keys($grid-columns) {
    @include grid-media-query_($size) {
      $gutter: map-get($grid-default-gutter, $size);

      @include grid-cell($size, $grid-default-column-span, $gutter);

      @for $span from 1 through map-get($grid-columns, $upper-breakpoint) {
        // Span classes.
        // stylelint-disable max-nesting-depth
        @at-root .l-grid-cell--span#{$span},
          .l-grid-cell--span#{$span}-#{$size} {
          @include grid-cell-span_($size, $span, $gutter);
        }
      }
    }
  }
}
```



####2-1-2. _variables.scss
girdシステム用の変数をまとめたファイル。ブレイクポイントやカラム数などはプロジェクトに合わせ変更。

```scss:_variables.scss
$grid-breakpoints: (
  desktop: 1140px,
  tablet: 641px,
  phone: 0,
) !default;

$grid-columns: (
  desktop: 12,
  tablet: 6,
  phone: 4,
) !default;

$grid-default-margin: (
  desktop: 24px,
  tablet: 24px,
  phone: 16px,
) !default;

$grid-default-gutter: (
  desktop: 24px,
  tablet: 24px,
  phone: 16px,
) !default;

$grid-column-width: (
  desktop: 72px,
  tablet: 72px,
  phone: 72px,
) !default;

$grid-default-column-span: 4 !default;

$grid-max-width: null !default;
```


####2-1-3. _mixins.scss
girdシステム用のmixinをまとめたファイル。gridシステムで使うmixinをまとめている。

```scss:_mixins.scss
@import './variables';

// returns the lower grid boundary or null if the smallest grid is selected
@function grid-breakpoint-min($size) {
  @if not map-has-key($grid-columns, $size) {
    @error "Invalid style specified! Choose one of #{map-keys($grid-columns)}";
  }
  $min: map-get($grid-breakpoints, $size);

  @return if($min > 0, $min, null);
}

// returns the upper grid boundary or null if the largest grid is selected
@function grid-breakpoint-max($size) {
  @if not map-has-key($grid-columns, $size) {
    @error "Invalid style specified! Choose one of #{map-keys($grid-columns)}";
  }
  $names: map-keys($grid-columns);
  $n: index($names, $size);
  $prev: if($n > 1, nth($names, $n - 1), null);

  @return if($prev, (grid-breakpoint-min($prev) - 1px), null);
}

// Private mixins, meant for internal use.
@mixin grid-media-query_($size) {
  @if not map-has-key($grid-columns, $size) {
    @error "Invalid style specified! Choose one of #{map-keys($grid-columns)}";
  }

  $min: grid-breakpoint-min($size);
  $max: grid-breakpoint-max($size);

  @if $min == null and $max != null {
    // Phone
    @media (max-width: $max) {
      @content;
    }
  } @else if $min != null and $max != null {
    // Tablet
    @media (min-width: $min) and (max-width: $max) {
      @content;
    }
  } @else if $min != null and $max == null {
    // Desktop
    @media (min-width: $min) {
      @content;
    }
  } @else {
    // Fallback - no breakpoints defined
    @content;
  }
}

@mixin grid-cell-span_($size, $span, $gutter) {
  @if not map-has-key($grid-columns, $size) {
    @error "Invalid style specified! Choose one of #{map-keys($grid-columns)}";
  }

  $percent: percentage($span / map-get($grid-columns, $size));

  @if $percent > 100% {
    $percent: 100%;
  }

  width: calc(#{$percent} - #{$gutter});
  width: calc(#{$percent} - var(--grid-gutter-#{$size}, #{$gutter}));

  @supports (display: grid) {
    width: auto;
    grid-column-end: span min($span, map-get($grid-columns, $size));
  }
}

// Public mixins, meant for developer usage.
@mixin grid($size, $margin, $gutter) {
  @if not map-has-key($grid-columns, $size) {
    @error "Invalid style specified! Choose one of #{map-keys($grid-columns)}";
  }

  display: flex;
  flex-flow: row wrap;
  align-items: stretch;
  margin: -$gutter / 2;
  margin: calc(var(--grid-gutter-#{$size}, #{$gutter}) / 2 * -1);

  @supports (display: grid) {
    display: grid;
    margin: 0;
    grid-gap: $gutter;
    grid-gap: var(--grid-gutter-#{$size}, $gutter);
    grid-template-columns: repeat(map-get($grid-columns, $size), minmax(0, 1fr));
  }
}

@mixin grid-cell($size, $default-span, $gutter) {
  @if not map-has-key($grid-columns, $size) {
    @error "Invalid style specified! Choose one of #{map-keys($grid-columns)}";
  }

  @include grid-cell-span_($size, $default-span, $gutter);

  box-sizing: border-box;
  margin: $gutter / 2;
  margin: calc(var(--grid-gutter-#{$size}, #{$gutter}) / 2);

  @supports (display: grid) {
    margin: 0;
  }
}
```


<br>
###2-2. _container.scss
共通のレイアウトとなるスタイルをまとめるファイル。プロジェクト毎に必要に応じて編集。

```scss:_container.scss
.l-container {
  max-width: 960px;
  margin: 0 auto;
  padding: 0 24px;
  @include mq(tb) {
    width: 100%;
  }
}

.l-list {
  max-width: 640px;
  margin: 0 auto;
  padding: 0 0 24px;
  @include mq(sp) {
    padding: 0 16px 16px;
  }
}

.l-error {
  max-width: 640px;
  margin: 0 auto;
  padding: 0 0 24px;
  @include mq(tb) {
    padding: 0 0 16px;
  }
  @include mq(sp) {
    padding: 0 16px 16px;
  }
}

.l-btn-container,
.l-top-btn-container  {
  padding: 48px 0;
}
.l-btn-container {
  @include mq(sp) {
    padding: 24px 0;
  }
}
.l-top-btn-container {
  background-color: #f5f5f5;
  @include mq(tb) {
    padding: 24px 0;
  }
}
```



<br>
###2-3. _header.scss
共通のヘッダーのスタイルをまとめたファイル。プロジェクト毎に必要に応じて編集。

```scss:_header.scss
#l-header {
  width: 100%;
  height: 130px;
  background-color: #1a1a1a;
  @include mq(sp) {
    height: auto;
  }
}
.l-header-logo {
  height: 130px;
  padding-top: 27px;
  border-bottom: 4px solid key-color(pink02);
  @include mq(sp) {
    height: 67px;
    padding: 14px 16px;
    border-bottom: 2px solid key-color(pink02);
  }
  &__image {
    display: block;
    width: 267px;
    margin: 0 auto;
    @include mq(sp) {
      width: 133px;
      margin: 0;
    }
    img {
      vertical-align: bottom;
      width: 100%;
    }
  }
}
.l-top-text {
  padding-bottom: 16px;
  background-color: #f5f5f5;
  @include mq(tb) {
    padding: 0 16px 16px;
  }
  @include mq(sp) {
    padding: 8px 16px;
  }
  p {
    width: 960px;
    margin: 0 auto;
    color: text-color(base);
    font-size: 1.4rem;
    line-height: 1;
    @include mq(tb) {
      width: 100%;
    }
    @include mq(sp) {
      margin: auto;
      font-size: 1.2rem;
      line-height: 1.5;
    }
  }
}
```


<br>
###2-4. _footer.scss
共通のフッターのスタイルをまとめたファイル。プロジェクト毎に必要に応じて編集。

```scss:_footer.scss
#l-footer {
  max-width: 100%;
  background-color: #1a1a1a;
}
.l-footer-conainer {
  max-width: 1000px;
  margin: 0 auto;
  padding: 48px 0 24px;
  @include mq(tb) {
    padding: 48px 16px 24px;
  }
  @include mq(sp) {
    width: 100%;
    padding: 68px 0 24px;
    border-top: 4px solid key-color(pink02);
  }
}
.l-footer-logo {
  display: block;
  width: 160px;
  margin-bottom: 20px;
  @include mq(sp) {
    width: 120px;
    margin: 0 auto;
  }
  img {
    vertical-align: bottom;
    width: 100%;
  }
}
.l-footer-links {
  display: flex;
  flex-wrap: wrap;
  margin-bottom: 20px;
  @include mq(sp) {
    margin: 24px 0;
    // border: 2px solid #fff;
  }
  a, span {
    color: #fff;
    font-size: 13px;
    line-height: 24px;
  }
  a {
    @include mq(sp) {
      width: 50%;
      height: 58px;
      padding: calc(33px / 2) 0;
      border-color: #fff;
      border-style: solid;
      font-size: 1.2rem;
      text-align: center;
      line-height: 24px;
    }
  }
  span {
    padding: 0 4px;
    @include mq(sp) {
      display: none;

    }
  }
}
.l-footer-copyright {
  @include mq(sp) {
    text-align: center;
  }
  a {
    color: #fff;
    font-size: 1.4rem;
    line-height: 1;
    @include mq(sp) {
      font-size: 1.2rem;
    }
  }
}
```


<br>
##3. `object`
プロジェクト毎や再利用可能など細かいスタイルを保存するディレクトリ。配下にcomponent, project, utilityの３つのディレクトリをもつ。


1. component :いくつかのページで共通するモジュール
1. project  :ページやレイアウト毎に固有のモジュールをまとめるファイル
1. utility :強制的に適用するスタイル


##4. `component`
いくつかのページで共通する**モジュール**
button、link、error、breadcrumbなど

cssのセレクタは冒頭に`c-`を付けて記述していく。

###4-1. _btn.scss

```scss:_btn.scss
.c-btn {
  position: relative;
  display: block;
  width: 376px;
  height: 52px;
  margin: 0 auto;
  background-color: #fff;
  border: 2px solid #333;
  border-radius: 26px;
  color: text-color(base);
  font-size: 1.6rem;
  font-weight: bold;
  text-align: center;
  line-height: 48px;
  transition: all .25s;
  &__arrow {
    position: absolute;
    top: 50%;
    right: 18px;
    width: 20px;
    height: 20px;
    margin-top: -10px;
    background-color: key-color(pink01);
    border-radius: 50%;
    @include mq(sp) {
      right: 16px;
    }
    &::before {
      content: '';
      display: block;
      position: absolute;
      top: 0;
      bottom: 0;
      left: 0;
      right: 3px;
      width: 6px;
      height: 6px;
      margin: auto;
      border-top: 1px solid #fff;
      border-right: 1px solid #fff;
      transform: rotate(45deg);
    }
  }
  &:hover {
    background-color: #333;
    color: text-color(white);
  }
  @include mq(sp) {
    width: 264px;
    height: 40px;
    border: 2px solid #333;
    border-radius: 20px;
    font-size: 1.4rem;
    line-height: 36px;
  }
}

.c-btn-to-top {
  position: fixed;
  z-index: 5;
  right: 20px;
  bottom: 50px;
  width: 40px;
  height: 40px;
  background-color: #373737;
  transition: opacity 0.3s cubic-bezier(.13, .78, .38, .98);
  border-radius: 50%;
  cursor: pointer;
  @include mq(sp) {
    right: 16px;
    bottom: 16px;
  }
  &:hover { opacity: .5; }
  &::before {
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    display: block;
    width: 10px;
    height: 10px;
    margin-top: -3px;
    margin-left: -5px;
    border-width: 0;
    border-top: 2px solid #fff;
    border-left: 2px solid #fff;
    transform: rotate(45deg);
  }
}
```


<br>
###4-2. _breadcrumb.scss

```scss:_breadcrumb.scss
.c-breadcrumb {
  padding: 16px 0;
  background-color: #f5f5f5;
  @include mq(tb) {
    padding: 16px;
  }
  @include mq(sp) {
    overflow: scroll;
    white-space: nowrap;
    padding: 8px 16px;
    background-color: #fff;
  }
  &--narrow {
    background-color: #fff;
    .c-breadcrumb-list {
      width: 640px;
      @include mq(sp) {
        width: 100%;
      }
    }
  }
}
.c-breadcrumb-list {
  width: 960px;
  margin: 0 auto;
  @include mq(tb) {
    width: 100%;
  }
  &__item {
    position: relative;
    display: inline-block;
    color: text-color(link02);
    font-size: 1.3rem;
    @include mq(sp) {
      padding-right: 18px;
      font-size: 1.2rem;
    }
    &:not(:last-child) {
      padding-right: 18px;
      &::after {
        content: '';
        display: block;
        position: absolute;
        top: 50%;
        right: 6px;
        width: 8px;
        height: 8px;
        margin-top: -5px;
        border-top: 1px solid #666;
        border-right: 1px solid #666;
        transform: rotate(45deg);
        @include mq(sp) {
          width: 6px;
          height: 6px;
          margin-top: -4px;
        }
      }
    }
    a {
      color: text-color(link02);
      &:hover {
        color: text-color(link02-hover);
        text-decoration: underline;
      }
    }
  }
}
```

<br>
###4-3. _error.scss

```scss:_error.scss
.p-error-header {
  margin: 32px 0 16px;
  font-size: 3rem;
  font-weight: bold;
  line-height: 1;
  @include mq(sp) {
    margin: 8px 0 16px;
    font-size: 1.7rem;
  }
}
.p-error-text {
  font-size: 1.7rem;
  line-height: 2;
  @include mq(sp) {
    font-size: 1.5rem;
  }
}
```


<br>
###4-4. _link.scss

```scss:_link.scss
.c-link01,
.c-link02 {
  &:hover {
    text-decoration: underline;
  }
}

.c-link02 {
  color: link-color(link02);
  &:hover {
    color: link-color(link02-hover);
  }
}
```

<br>
###4-5. _pagenation.scss

```scss:_pagenation.scss
.c-pagination {
  margin: 24px 0 48px;
  @include mq(sp) {
    margin: 8px 0 24px;
  }
}
.c-pagination-list {
  display: flex;
  align-items: center;
  justify-content: center;
}
.c-pagination-item {
  display: inline-block;
  margin: 0 4px;
  background-color: #fff;
  border: 2px solid #333;
  border-radius: 50%;
  transition: .25s all;
  a {
    position: relative;
    display: block;
    width: 32px;
    height: 32px;
    color: text-color(base);
    font-size: 1.4rem;
    font-weight: bold;
    text-align: center;
    line-height: 32px;
    &:disabled {
      cursor: default;
    }
  }
  &:hover {
    background-color: #ddd;
  }
  // prev & next
  &.is-prev,
  &.is-next,
  &.is-ellipsis {
    a { font-size: 0; }
  }
  &.is-prev,
  &.is-next {
    a::before {
      content: '';
      display: block;
      position: absolute;
      top: 0;
      bottom: 0;
      left: 0;
      right: 0;
      width: 8px;
      height: 8px;
      margin: auto;
      border-top: 1px solid #222;
      border-left: 1px solid #222;
    }
  }
  &.is-prev {
    a::before {
      left: 4px;
      transform: rotate(-45deg);
    }
  }
  &.is-next {
    a::before {
      right: 4px;
      transform: rotate(135deg);
    }
  }
  // ellipsis
  &.is-ellipsis {
    .point-icon {
      position: absolute;
      top: 0;
      bottom: 0;
      left: 0;
      right: 0;
      display: flex;
      align-items: center;
      justify-content: space-between;
      width: 13px;
      height: 3px;
      margin: auto;
    }
    .point {
      display: block;
      width: 3px;
      height: 3px;
      background-color: #222;
      border-radius: 50%;
    }
    &:hover {
      background-color: #fff;
    }
  }
  // current
  &.is-current {
    background-color: #333;
    a { color: key-color(pink01) !important; }
  }
  // disabled
  &.is-disabled {
    &.is-prev,
    &.is-next {
      background-color: #fff;
    }
    a { cursor: default; }
  }
}
```



<br>
###4-5. _title.scss

```scss:_title.scss
.c-title {
  margin-bottom: 24px;
  color: text-color(base);
  font-size: 3rem;
  font-weight: bold;
  line-height: 1;
  @include mq(sp) {
    margin-bottom: 16px;
    font-size: 2.2rem;
  }
}
.c-title-new-article {
  position: relative;
  margin-bottom: 24px;
  padding-bottom: 14px;
  color: text-color(base);
  font-size: 2.6rem;
  font-weight: bold;
  line-height: 1;
  @include mq(sp) {
    margin-bottom: 16px;
    padding-bottom: 12px;
    font-size: 2rem;
  }
  &::before,
  &::after {
    content: '';
    display: block;
    position: absolute;
    bottom: 0;
    left: 0;
    height: 6px;
    @include mq(sp) {
      height: 4px;
    }
  }
  &::before {
    width: 150px;
    background-color: key-color(pink01);
    @include mq(sp) {
      width: 100%;
    }
  }
  &::after {
    width: 36px;
    background-color: #222;
    @include mq(sp) {
      width: 66px;
    }
  }
}

```

など。






<br>
##5. `project`
ページやレイアウト毎に固有のモジュールをまとめるファイル。他のページで使わない。

ページやレイアウト毎にディレクトリを作成して編集。cssのセレクタは冒頭に`p-`を付けて記述していく。


##6. `utility`
強制的に適用するスタイル（!importantがつくもの）。メディアクエリ毎のスタイルもまとめる。

1. _space.scss :marginとpaddingに関するスタイル
1. _typography.scss :textに関するスタイル
1. _display.scss  :displayに関するスタイル

cssのセレクタは冒頭に`u-`を付けて記述していく。


###6-1. _space.scss
marginとpaddingに関するスタイル。一定間隔のmarginとpaddingを用意する。間隔は_variable.scssで定義。

例えば`u-mt8` で`margin-top: 8px !important`となるセレクタを作成する。

```scss:_space.scss
.u-mxa {
  margin-left: auto !important;
  margin-right: auto !important;
}
@each $space in $spaces {
  // margin
  .u-m#{ $space } {
    margin: #{ $space }px !important;
  }
  .u-mx#{ $space } {
    margin-left: #{ $space }px !important;
    margin-right: #{ $space }px !important;
  }
  .u-my#{ $space } {
    margin-top: #{ $space }px !important;
    margin-bottom: #{ $space }px !important;
  }
  .u-mt#{ $space } {
    margin-top: #{ $space }px !important;
  }
  .u-mb#{ $space } {
    margin-bottom: #{ $space }px !important;
  }
  .u-ml#{ $space } {
    margin-left: #{ $space }px !important;
  }
  .u-mr#{ $space } {
    margin-right: #{ $space }px !important;
  }
  // padding
  .u-p#{ $space } {
    padding: #{ $space }px !important;
  }
  .u-px#{ $space } {
    padding-left: #{ $space }px !important;
    padding-right: #{ $space }px !important;
  }
  .u-py#{ $space } {
    padding-top: #{ $space }px;
    padding-bottom: #{ $space }px !important;
  }
  .u-pt#{ $space } {
    padding-top: #{ $space }px !important;
  }
  .u-pb#{ $space } {
    padding-bottom: #{ $space }px !important;
  }
  .u-pl#{ $space } {
    padding-left: #{ $space }px !important;
  }
  .u-pr#{ $space } {
    padding-right: #{ $space }px !important;
  }
}

@each $size in $sizes {
  @include mq($size) {
    .u-mxa-#{ $size } {
      margin-left: auto;
      margin-right: auto;
    }
    @each $space in $spaces {
      // margin
      .u-m#{ $space }-#{ $size } {
        margin: #{ $space }px !important;
      }
      .u-mx#{ $space }-#{ $size } {
        margin-left: #{ $space }px !important;
        margin-right: #{ $space }px !important;
      }
      .u-my#{ $space }-#{ $size } {
        margin-top: #{ $space }px !important;
        margin-bottom: #{ $space }px !important;
      }
      .u-mt#{ $space }-#{ $size } {
        margin-top: #{ $space }px !important;
      }
      .u-mb#{ $space }-#{ $size } {
        margin-bottom: #{ $space }px !important;
      }
      .u-ml#{ $space }-#{ $size } {
        margin-left: #{ $space }px !important;
      }
      .u-mr#{ $space }-#{ $size } {
        margin-right: #{ $space }px !important;
      }
      // padding
      .u-p#{ $space }-#{ $size } {
        padding: #{ $space }px !important;
      }
      .u-px#{ $space }-#{ $size } {
        padding-left: #{ $space }px !important;
        padding-right: #{ $space }px !important;
      }
      .u-py#{ $space }-#{ $size } {
        padding-top: #{ $space }px !important;
        padding-bottom: #{ $space }px !important;
      }
      .u-pt#{ $space }-#{ $size } {
        padding-top: #{ $space }px !important;
      }
      .u-pb#{ $space }-#{ $size } {
        padding-bottom: #{ $space }px !important;
      }
      .u-pl#{ $space }-#{ $size } {
        padding-left: #{ $space }px !important;
      }
      .u-pr#{ $space }-#{ $size } {
        padding-right: #{ $space }px !important;
      }
    }
  }
}
```

@eachを使うと指定した変数の要素を一つずつ抜き出す処理になる。間隔は_variable.scssで定義。

```scss:_variable.scss
// space
$spaces: 0, 8, 16, 24, 32, 40;
```

基本的には8の倍数の間隔を使用。


<br>
###6-2. _typography.scss
textに関するスタイル。font-weightやtext-alignなどのスタイルを定義している。

```scss:_typography.scss
// font weight
.u-fwn {
  font-weight: normal !important;
}
.u-fwb {
  font-weight: bold !important;
}

// text align
.u-tac {
  text-align: center !important;
}
.u-tal {
  text-align: left !important;
}
.u-tar {
  text-align: right !important;
}

// text decoration
.u-underline {
  text-decoration: underline !important;
}

// other
.u-text-truncate,
.u-text-clip {
  overflow: hidden !important;
  white-space: nowrap !important;
}
.u-text-truncate {
  text-overflow: ellipsis !important;
}
.u-text-clip {
  text-overflow: clip !important;
}

// line-clamp
.u-clamp1,
.u-clamp2,
.u-clamp3,
.u-clamp4 {
  overflow: hidden !important;
  text-overflow: ellipsis !important;
  display: -webkit-box !important;
  -webkit-box-orient: vertical !important;
}
.u-clamp1 { -webkit-line-clamp: 1 !important; }
.u-clamp2 { -webkit-line-clamp: 2 !important; }
.u-clamp3 { -webkit-line-clamp: 3 !important; }
.u-clamp4 { -webkit-line-clamp: 4 !important; }

// font size
@each $fontSize in $fontSizes {
  .u-fs#{$fontSize} {
    font-size: #{$fontSize / 10}rem !important;
  }
}

@each $size in $sizes {
  @include mq($size) {
    @each $fontSize in $fontSizes {
      .u-fs-#{$size}-#{$fontSize} {
        font-size: #{$fontSize / 10}rem !important;
      }
    }
  }
}
```


フォントサイズやメディアクエリ用のサイズは_variable.scssで定義している。メディアクエリは_mixin@scssで定義。

```scss:_variable.scss
// size
$sizes: tb, sp;

// font size
$fontSizes: 10, 12, 14, 16, 18, 20, 22, 24, 26, 28;
```


<br>
###6-3. _display.scss
displayに関するスタイル。

```scss:_display.scss
.u-dn {
  display: none !important;
}
.u-db {
  display: block !important;
}
.u-dib {
  display: inline-block !important;
}
.u-df {
  display: flex !important;
}

@each $size in $sizes {
  @include mq($size) {
    .u-dn-#{$size} {
      display: none !important;
    }
    .u-db-#{$size} {
      display: block !important;
    }
    .u-dib-#{$size} {
      display: inline-block !important;
    }
    .u-df-#{$size} {
      display: flex !important;
    }
  }
}
```

メディアクエリ用のサイズは_variable.scssで定義している。メディアクエリは_mixin@scssで定義。

```scss:_variable.scss
// size
$sizes: tb, sp;
```

<br>
##7. コンパイル用のファイル
実際にコンパイルするファイルは以下になる。（resources > sass直下においた`_`のないファイルが該当）

├ common_inview.scss　全体で共通のファーストビュー用のスタイル。
├ common_overview.scss　全体で共通のファーストビュー以外のスタイル。
├ top_inview.scss トップページ固有のファーストビュー用のスタイル。
├ top_overview.scss トップページ固有のファーストビュー以外のスタイル。
├ (ページ名)_inview.scss
├ (ページ名)_overview.scss





###7-1. inviewとoverview
共通のスタイルやページ毎のスタイルを`inview`と`overview`の２つに分けている。

クリティカルCSSの考え方で、
・inviewにはファーストビューで必要なスタイルを記述し、headタグの中でstyleタグで埋め込む。


・overviewはファーストビュー以外で必要なスタイルを記述し、body閉じタグの前でlinkタグで読み込む。

これをすることでレンダリングブロックを回避し、ページの描画速度を改善することができる。


>（補足）[クリティカルCSSとは？使い方について](https://qiita.com/yuta-38/items/c6f92fdcfb8eaaaae157)


<br>
###7-2. common_inview.scss
全体で共通となるファーストビューで必要なスタイルをまとめたファイル。

```scss:common_inview.scss
@charset 'utf-8';

// foundation
@import "foundation/variable";
@import "foundation/mixin";

@import "foundation/normalize";
@import "foundation/base";

// layout
@import 'layout/grid/grid';
@import "layout/header";
@import "layout/container";

// object - component
@import "object/component/breadcrumb";
@import "object/component/title";
@import "object/component/btn";
@import "object/component/link";
@import "object/component/pagenation";
@import "object/component/error";

// object - project

// object - utility
@import "object/utility/display";
@import "object/utility/space";
@import "object/utility/typography";
```


<br>
###7-3. common_overview.scss
全体で共通となるファーストビュー以外で必要なスタイルをまとめたファイル。


```scss:common_oveview.scss
@charset 'utf-8';

// foundation
@import "foundation/variable";
@import "foundation/mixin";

// layout
@import "layout/footer";
```

variableとmixinはコンパイル時に必要となるファイル。



<br>
###7-4. 補足
必要に応じて、ページ毎に`ページ名_inview`、`ページ名_overview`を作成する。

レイアウトのパターン数が多い場合は管理が大変になるため、クリティカルCSSではなく、コンパイル用に`application.scss`の１ファイルのみとする場合もある。


<br>
以上。