【CSS・SASS】FLOCSS(フロックス)とは何か?命名規則やディレクトリ構造を実例で解説(初心者向け、わかりやすく解説)

sass-scss-prograshi(プロぐらし)-kv CSS・SCSS
記事内に広告が含まれていることがあります。

FLOCSS(フロックス)とは何か?

CSSを使ってスタイル処理を書いていると、いつのまにやら同じ処理を重複して記載していたり、使いたかった処理が既に使用されていて、スタイルの適用を強制する「!import」を大量に使わなければいけないといったファイルやコードのカオスが発生することがあります。

そのようなCSSファイルをメンテナンスするのは地獄です。

そのようなCSSで陥りがちなカオスを避ける方法にFLOCSSがあります。

FLOCSSとは、WEBサイト(プロジェクト)の中でCSSスタイルをどのように適用させていくかをまとめた作り方のルールです。

なお、細かく見ると、「Foundation Layout Object CSS」の略で、従来からあったCSSの作り方のルールであるOOCSSやSMACSS、BEM、SuitCSSなどのコンセプトを取り入れたものです。


>(参考)Github FLOCSS公式ページ


FLOCSSの考え方

FLOCSSを使う上で重要な概念は以下の3つです。

FLOCSSの考え方
  1. カスケーディング
  2. レイヤー
  3. 命名規則

カスケーディングとはスタイルを適用する際の優先度(強度)のことです。この優先度に合わせてレイヤーを作成し、その中に命名規則にそってセレクタ名をつけて処理を記述していきます。

以下でそれぞれの詳細について解説していきます。


カスケーディングとは何か?

カスケーディングとは何か?

CSSにおけるカスケーディングとは、ある要素に対して、複数のスタイル処理を指定した場合に、どの処理を優先して適用するかの順序です。

英語ではCascadingと書き、Cascade(カスケード)の進行形になっています。

Cascade(カスケード)とは滝が幾段にも重なった状態を表しています。

CSSでは、滝のように段々とスタイルを適用させていくイメージになぞらえています。

point

カスケーディングとはスタイルを適用する優先順位のこと。


スタイル適用の優先順位

CSSのカスケーディング、すなわちスタイル適用の優先順位は大きく次の2つに分類することができます。

スタイル適用の優先順位
  1. ファイルの中のスタイル適用の優先順位。
  2. セレクタの種類によるスタイル適用の優先順位。


ファイルの中のスタイル適用の優先順位

CSSファイルの中では、下側に記述されている処理ほど、スタイル適用の優先順位が上がります

このため、SASSの@import機能で他のCSSファイルを読み込むときに、上側で読み込んだファイルで指定しているプロパティと、後から読み込んだファイルで指定しているプロパティに同じ記述があった場合、後から読み込んでいるスタイルが優先されます


実例:CSSファイル内の場合

例えば、以下のようにクラス名「red-color」と「blue-color」がついたdivタグがあるとします。

<p class="red-color blue-color">ダミーテキスト</p>

これに対して、それぞれのクラスを指定してCSSを記述したとします。

.red-color{
  color: red;
  background-color: yellow;  
}

.blue-color{
  color: blue;
}

ブラウザの表示は以下のようになります。

指定したpタグに適用されるのは、下側に記述した「blue-color」の処理が優先的になり、上側の「red-color」のプロパティの値は上書きされます。

なお、「background-color」のように、他に処理が出てこない場合は上書きは発生しません。


実例:他のファイルを読み込む場合

例えば、@importを使って、以下のように「fundation/_base.scss」と「layout/_footer.scss」ファイルの2つを「app.scss」というファイルの中で読み込んだとします。

@import "foundation/_base";
@import "layout/_footer";

すると、app.scssの中にはファイルを読み込んだ順番に、そのファイルの内容が入ります。

このため、後から読み込んでいる「layout/_footer.scss」の中に、「fundation/_base.scss」と重複する指定があると、後から読み込んだファイルの内容で上書きが発生してしまいます。

point

ファイルを読み込む順番が大切。スタイル適用の優先度が低いファイルから読み込んでいく。


セレクタの種類によるスタイル適用の優先順位

CSSではスタイル適用の処理を各順番以外にも、どのセレクタや書き方を使うかで適用の優先順位が変わります。

例えば、aタグに直接スタイルを指定したものよりも、a:linkのように疑似クラスを使った処理の方が優先されます。

このため、a:linkの中に重複するプロパティがあれば、その値で処理を上書きします。

さらに、タグの種類よりも、クラスで指定したり、id名で指定する方が優先度は強くなります。

セレクタとは異なりますが、更に上の優先度になるのが、HTML上に直接スタイルを記述するインラインスタイルです。

そして最強なのがプロパティの後ろに「!important」を宣言する書き方です。

このため、CSS/SASSファイルの読み込み順序や書き方がカオスになっていると、スタイルの強制適用を表す「!important」の記述が乱用されることになります。(非常にメンテ性が低い状態です)

なお、FLOCSSではLayoutレイヤーのみid名を使ったidセレクタ(#セレクタ名)の使用が許可されています。その他のレイヤーではクラス名を使ったクラスセレクタを使用します。

各セレクタや記述の優先度をまとめると以下のようになります。

適用の優先度セレクタや適用の種類処理の例
6!important宣言color: red !important;
5インライン(style属性)style=”color: red;”
4IDセレクタ#hoge
3クラスセレクタ.hoge
3属性セレクタa[href=”https://example.org”]{color: red;}
3擬似クラスbutton:hover {color: red;}
2疑似要素p::first-line {color: red;}
2要素セレクタp {color: red;}
1ユニバーサルセレクタ* {color: red;}
  • 優先度は最弱を1として+1ずつで表示しています。
  • !importantはセレクタではありませんが、すべてのルールを無視して適用されるため最上位の優先度として記載しています。

>(参考)htmq.com セレクタの種類一覧


合わせて読みたい

「:」や「::」がついた疑似要素や疑似クラスの詳細については下記をご参考ください。

【CSS】疑似要素と疑似クラスとは何か?セレクタのコロン2つ::と1つ:の違いを実例で解説


レイヤー(ディレクトリ構造)

レイヤーとは何か?

FLOCSSでは上記のカスケーディングを考慮しスタイルの優先度を反映した形で、かつ機能毎に分けてディレクトリ構造が定義されています。

そして、このディレクトリのことをレイヤーと呼びます。

主体となる3つのレイヤーがあり、その中に更に3つのレイヤーがあります。合計すると6つのレイヤーで構成されます。

さらに、そこに各SASSファイルを取りまとめる用の「app.scss」というファイルを設置します。


主な3つのレイヤー

  1. Foundation: スタイルのリセットや、ページの下地となる背景のスタイルなどを指定するファイルを置く。
  2. Layout: ヘッダー、フッター、メインコンテンツエリアなど全体で共通となる主要なエリアのスタイルを指定するファイルを置く。
  3. Object: WEBサイト内の複数のヵ所で再利用する可能性のある要素のスタイルを指定するファイルを置く。この中に更に3つのレイヤーがある(component, project, utility)


objectの中の3つのレイヤー

  1. Component: ボタンなどの繰り返し再利用する要素(モジュール)のスタイルを指定するファイルを置く。
  2. Project: プロジェクトに固有のページなどのスタイルを指定するファイルを置く。(ページ単位でスタイルを用意する)
  3. Utility: わずかなスタイルの調整をするためのファイル。例えばmargin-topを8pxずつ0~40pxまで用意するなど。(処理の中で!important宣言が使われることが多い)


統合用ファイル

各レイヤーの中に設置したファイルを読み込むために、app.scssというとりまとめようのファイルを作成します。

その中に@importで各ファイルを読み込んでいきます。


ファイルの冒頭に「_(アンダースコア)」をつける

各レイヤーの配下に配置するファイル名の冒頭に「_(アンダースコア)」をつけます

ファイル名の冒頭に「_」をつけることで、SASSをCSSにコンパイルしないようにする指示となります。

コンパイルするファイルは統合用のapp.scssファイルのみです。


レイヤー構造の例

FLOCSSのレイヤー構造は以下のようになります。

中に設置してあるファイルは例です。

sass
│
├── foundation
│   ├── _base.scss
│   └── _reset.scss
|
├── layout
│   ├── _footer.scss
│   ├── _header.scss
│   ├── _main.scss
│   └── _sidebar.scss
|
└── object
│    ├── component
│    │   ├── _button.scss
│    │   ├── _dialog.scss
│    │   ├── _grid.scss
│    │   └── _media.scss
│    │ 
│    ├── project
│    │   ├── _articles.scss
│    │   ├── _comments.scss
│    │   ├── _gallery.scss
│    │   └── _profile.scss
│    │ 
│    └── utility
│        ├── _align.scss
│        ├── _clearfix.scss
│        ├── _margin.scss
│        ├── _position.scss
│        ├── _size.scss
│        └── _text.scss
│
└── app.scss     


各レイヤーのスタイル適用の優先度

なお6つのレイヤーは上が最もスタイルの適用優先度が低く、下に行くほど優先度が高くなっていきます

弱い
F: Fundation
L: Layout
C: ObjectのComponent
P: ObjectのProject
U: ObjectのUtility
強い


統合用ファイルapp.scssの記述例

統合用(コンパイル用)のapp.scssファイルでは、CSSを適用する順番を守るため、レイヤーの順番に従ってファイルを読み込んでいきます。


実例

上記のレイヤー構造の例に従ってapp.scssの中で各ファイルを読み込むと以下のようになります。

// ==========================================================================
// Foundation
// ==========================================================================

@import "foundation/_reset";
@import "foundation/_base";

// ==========================================================================
// Layout
// ==========================================================================

@import "layout/_footer";
@import "layout/_header";
@import "layout/_main";
@import "layout/_sidebar";

// ==========================================================================
// Object
// ==========================================================================

// -----------------------------------------------------------------
// Component
// -----------------------------------------------------------------

@import "object/component/_button";
@import "object/component/_dialog";
@import "object/component/_grid";
@import "object/component/_media";

// -----------------------------------------------------------------
// Project
// -----------------------------------------------------------------

@import "object/project/_articles";
@import "object/project/_comments";
@import "object/project/_gallery";
@import "object/project/_profile";

// -----------------------------------------------------------------
// Utility
// -----------------------------------------------------------------

@import "object/utility/_align";
@import "object/utility/_clearfix";
@import "object/utility/_margin";
@import "object/utility/_position";
@import "object/utility/_size";
@import "object/utility/_text";


@importとは何か?

@importとはSASSの記述方法で、以下のようにすることでSASS(.scss, .sass)やCSS(.css)ファイルを読み込むことができます。

@import "ファイルパス"
@import使用時のポイントと注意点
  • ディレクトリ単位で読み込むことはできない(ファイル名を指定する
  • .scssは省略可能(.cssは必要)
  • _がついたファイル名は、_なしで記述する。


実例

例えば以下のパスにある「_align.scss」を読み込むとします。

sass > object > utility > _align.scss

この場合、app.scssでの記述は以下のようになります。

@import(object/utility/align)

「_align.scss」の「_」と「.scss」を省略しています。



命名規則

FLOCSSを使う時はHTMLタグに適用するクラス名に命名規則があります。

考えるべき命名規則は大きく次の2つに分かれます。

FLOCSSの命名規則
  1. レイヤー毎の命名規則。
  2. BEMによる命名規則。

BEMとは既に提唱されているCSSの命名規則です。(詳しくは後述hします)

FLOCSSでは、レイヤー名をクラス名のプレフィックス(接頭語)で指定し、モジュールや適用するスタイルの内容をBEMの命名規則に則ってサフィックス(接尾語)で指定します。


レイヤー毎の命名規則

レイヤー毎の命名規則では、WEBページや各要素が分類されるレイヤーに従って、クラス名の冒頭に各レイヤーの冒頭位置文字を記載します。

fundationレイヤーでは、bodyやタグなどの基本設定を記述するため、クラス名を指定することはありません。

layoutレイヤーのみid名を使うことも許容されています。

なお、選択中などの状態を表すものは「.is-」をつかって記述します。

レイヤー接頭語セレクタ(クラス名)の例
fundationなしbody { margin: 0 }
layout.l または #l.l-footer
component.c.c-label
project.p.p-profile
utility.u.u-black
状態.is.is-selected


BEMによる命名規則

BEMとは何か?

BEMとは「Block Element Modifier」の略で、CSSを適用するためのクラス名(セレクタ名)の付け方を定義したものです。

名前が指すとおり「Block(ブロック)」「Element(エレメント)」「Modifier(モデファイヤ)」の3つの機能に分けて命名していくルールです。

Yandex(ヤンデックス)というロシアの検索エンジンを開発する人たちによって使われたのが最初と言われています。

(参考)Wikipedia Block, Element, Modifier


Block, Element, Modifierとは何か?

BEMの「Block(ブロック)」「Element(エレメント)」「Modifier(モデファイヤ)」はそれぞれ、以下のように定義されています。


Block(ブロック)とは何か?

Block(ブロック)は大きな一つの塊・機能です。例えば、レビューなどの複数のタグで構成される一番外側のタグ(ラッパー)に付けるのがBlock名です。

なお、FLOCSSではBlockの命名ルールはレイヤーの命名ルールになります

また、ブロック名がユーザー詳細(user detail)といったように複数の単語になる場合は、ハイフンでつないで「user-detail」とします。

合わせて読みたい

ブロック名をハイフンでつないでいくと、ブロック名だけでかなり長い名称になってしまうことがあります。その場合の対処法については下記をご参考ください。

【CSS】BEMの命名ルールのポイント。あまりにも長くなる場合は、新しい名前を付ける


Element(エレメント)とは何か?

Element(エレメント)はBlockの構成要素です。例えば、レビューの中に、ユーザーアイコン、プロフィール、レーティング、コメントなどの要素があります。それぞれが一つ一つのElementとなります。

アンダーバー2つを使って「 __エレメント名 」として記述します。


Modifier(モディファイヤ)とは何か?

Modifier(モディファイヤ)は色やサイズを変えるといった微調整をするときに指定する命名規則です。例えば、レビューの中のアイコンに赤色を適用するといった場合にModefierを使います。

ハイフン2つを使って「 –モデファイヤ名 」として記述します。


BEMの命名規則一覧と実例(FLOCSSの場合)

BEMの命名規則をまとめると以下のようになります。

項目内容命名規則クラス名の例
Block独立して再利用できる要素FLOCSSの規則に沿うc-review
ElementBlockの中にのみ存在できる要素__ (アンダーバー2つ)c-review__icon
ModifierBlockやElementを修飾する— (ハイフン2つ)c-review__icon–red


FLOCSSにおけるBEMの仕様

SASS(.scss)でFLOCSSを使ってBEMの命名規則を適用すると以下のような記述になります。

.c-key-visual {
  background-repeat:  no-repeat;
  background-position: center;
  background-size: cover;
  height: 340px;
  &__title{
    font-size: 36px;
    font-weight: bold;
  }
  &__lead{
    font-size: 24px;
  }
  &__title--black,
  &__lead--black {
    color: #333;
  }
}
  • Block(ブロック): c-key-visual
  • Element(エレメント): __title, __lead
  • Modifier(モデファイヤ): --black

なお、HTMLタグの例は以下のようになります。

<div class="c-key-visual">
  <img src="../images/kv.jpg">
  <p class="c-key-visual__title c-key-visual__title--black">タイトル</p>
  <p class="c-key-visual__lead">リード文</p>
</div>


合わせて読みたい

SASSの記述の中で使用している「&」については下記をご参考ください。

【SCSS】セレクタの&(アンド・アンパサンド)とは何か?意味や使い方、注意点、メリットを実例で解説


modifierかutilityどちらを使うべきか?

FLOCSSを使っていると、既存のモジュールに追加でちょっとした修正を加えたいときに、「modifier」か「utility」のどちらを使うべきかで悩むことがあるかもしれません。

例えば、あるページの見出しに「margin-top: 8px」を設定するといった場合です。

そういったときは、他のページや要素でも使う頻度が高い場合は、utilityとしてそのプロパティを登録します。

特定のページやブロック、エレメント内などのみで使い、あまり頻出しない場合はmodefierとして「–モデファイヤ名」で新たなクラスを作成します。

例えば、marginの場合は、他の要素でも指定することが多いためutilityに登録しておきます。その際「_margin.scss」というファイル名で、複数のマージン設定を用意しておくのが一般的です。

utilityの例

utility
  ├── _align.scss
  ├── _clearfix.scss
  ├── _margin.scss
  ├── _padding.scss
  ├── _position.scss
  ├── _size.scss
  └── _text.scss


FLOCSS使用時の注意点

FLOCSSを使うときの注意点は以下のようになります。

FLOCSS使用時の注意点
  1. SASSに同じブロックを複数記載しない。
  2. モジュール内で完結しない@extendを使用しない。
  3. ファイル名の冒頭に「_(アンダースコア)」をつける。
  4. 統括用のファイルapp.scssの中ではレイヤーの順番に読み込む(並び順を変えない)


SASSに同じブロック名を複数記載しない

FLOCSSでは意図しないCSSの適用を避けるため。SASS(.scss)の中に複数のブロック名をセレクタとして指定しないようにします。

OKな書き方

例えば、.c-reviewに対する処理を記述する場合は以下のように「.c-review」を一つだけ記述します。

.c-review{
  display: flex;
  position: relative;
  color: #333;
  background-color: lightyellow;
  &__icon{
    font-size: 12px;
    position: absolute;
    top: 10px;
    &--black{
      color: black;
    }
  }
  p {
    font-size: 16px;
  }
}


NGな書き方

例えば、「.c-review」が何度も登場すると、記述が分散してわかりにくくなってしまいます。

.c-review {
  display: flex;
  position: relative;
}

.c-review__icon {
  font-size: 12px;
  position: absolute;
  top: 10px;
}

.c-review {
  color: #333;
  background-color: lightyellow;
}

.c-review__icon--black {
  color: black;
}

.c-review p {
  font-size: 16px;
}


モジュール内で完結しない@extendを使用しない

SASSの@extendを使うと、指定したセレクタの処理の内容を呼び出すことができます。

ところが、これを他のファイルや、呼び出したファイルの中などで行ってしまうと、FLOCSSの構成・設計は破綻し、カスケーディングも複雑になってしまう可能性が高いため、@extendは一つのファイル内に留めておきます。

▼モジュール内なら使用OK

.button {
  display: inline-block;
  padding: 0.5em 1em;
  cursor: pointer;
}
.button--primary {
  @extend .button
  background-color: #CCAA00;
  color: #FFFFFF;
}
.button--secondary {
  @extend .button
  background-color: #FFCC00;
}


ファイル名の冒頭に_をつける

統合ファイル(app.scss)を除いて、SASSからCSSへのコンパイルを避けるため、ファイル名の冒頭に_をつけます。


統括ファイル(app.scss)の@import順序を変えない

FLOCSSのカスケーディング(スタイル適用順序)を壊さないようにするためapp.scssの中で読み込むファイルの順番はレイヤーの順番とします。


(参考)CSSプロパティの記述順序

CSSを記述する場合にも、どういったプロパティから順番に記述していくかをある程度決めておくと、各処理毎に統一感が出て可読性が上がります。

例えば、以下のよな優先順位にします。(決まりはないので自由にオリジナルルールを作ってください)

プロパティを記述する優先順位の例
  1. display
  2. position
  3. width,height
  4. margin,padding
  5. background
  6. border
  7. font
  8. animation
  9. …etc


FLOCSSの各ファイルの実例

参考として、ページの速度改善対応を施したFLOCSSの構造と各ファイルの例を記載しておきます。

通常、コンパイル用のファイルはapp.scssの一つにまとめますが、ブラウザの読み込み速度を上げるために、コンパイル用のファイルをファーストビューとなる全体の共通部分と、ファーストビュー以外のページ毎にまとめた二種類に分けて読み込みます。

ファーストビューで使用するスタイルの内容はheadタグの中のstyleタグに直接入れます。

ファーストビュー以外で使用するスタイルはbodyの直前でlinkタグを使って読み込みます。

こうすることで、ブラウザが1つのCSSファイルを読み込む時間が早くなり、レンダリングブロックによる読み込み遅延が発生しにくくなります。

ファーストビューの読み込み速度を上げるSEO対策です。


FLOCSSの構造

FLOCSSの各レイヤーとファイルは以下のようにします。

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 ページ毎のファーストビュー用のスタイルをまとめたコンパイル用のファイル。
├ ページ名_poverview.scss  ページ毎のファーストビュー以外のスタイルをまとめたコンパイル用のファイル。
....

foundation :サイト全体で共通のデフォルト設定

foundationには以下のファイルを設置しています。

foundation サイト全体で共通のデフォルト設定。
├ _normalize.scss 不要なデフォルトスタイルをリセット(reset.cssよりも軽量)
├ _base.scss 全体で共通のリセットスタイル
├ _variable.scss 変数をまとめるファイル
├ _mixin.scss mixinをまとめるファイル


_normalize.scss

hタグなどスタイルを初期化します。MIT Licenseのコードを使用しています。公式ページからダウンロードできます。


normalize.cssとreset.cssの違い

normalize.cssはreset.cssと異なり有効なスタイルを残しています。


_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に記述してあります。


_variable.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形式のデータ)から指定したキー名をと一致する値を抜き出すことができます。

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

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


_mixin.scss

mixin(どこでも呼び出せるコンポーネント)を定義するファイルです。

メディアクエリを定義するために使用しています。

$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に記述してあります。

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

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

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

#{ } 変数をそのまま表示する記述です。

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


layout :全体で共通のページのレイアウト

layoutレイヤーには全体で共通となるヘッダーやフッター、メインコンテンツエリア、グリッドシステムに関するファイルを保存しています。

layout 全体で共通のページのレイアウト
├ grid グリッド関連のCSSを保存(googleのマテリアルデザインを使用)
 ├ _grid.scss
 ├ _mixin.scss
 ├ _variable.scss
├ _container.scss
├ _header.scss
├ _footer.scss

なお、グリッドシステムはgoogleのマテリアルデザインをカスタムしたものを使用しています。

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

合わせて読みたい

グリッドシステムとは何か?については下記をご参考ください。

【CSS】グリッドシステム(grid system, display: grid;)とは何か?要素の長さや位置の調整方法を実例で解説


_grid.scss

_grid.scssはグリッドシステムの基本構成を記述したファイルです。変数やmixinは別ファイルから読み込んでいます。

/*
 * 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);
        }
      }
    }
  }
}


_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;


_mixins.scss

グリッドシステム用のmixinをまとめたファイルです。

@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;
  }
}


_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;
  }
}


_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;
    }
  }
}


共通のフッターのスタイルをまとめたファイルです。プロジェクト毎に必要に応じて編集します。

#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;
    }
  }
}


object

プロジェクト毎に固有となるページのスタイルや、再利用可能なモジュールなどを保存するディレクトリです。配下にcomponent, project, utilityの3つのディレクトリをもちます。

  1. component : 複数のページで使い回しをするモジュールなどのスタイル。
  2. project : ページやレイアウト毎に固有のモジュールのスタイル。
  3. utility : 色やマージンの変更などちょっとした変更を加えるためのスタイル。


component

componentは複数のページで使い回しをするモジュールなどのスタイルを保存するためのディレクトリです。

button、link、error、breadcrumbなどのコンポーネント用のファイルを作成します。

なお、クラス名は冒頭に「c-」を付けて記述します。

├ component いくつかのページで共通するモジュール
 ├ _button.scss
 ├ _link.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);
  }
}


.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;
      }
    }
  }
}


_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;
  }
}


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

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


_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; }
  }
}


_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;
    }
  }
}

など。


project

プロジェクト毎に固有のページやレイアウト毎に固有のモジュールのスタイルを記述したファイルを保存します。

ページやレイアウト毎にディレクトリを作成してその中にファイルを作成していきます。

例えば、ユーザー一覧、ユーザー詳細、趣味のページがある場合以下のようなディレクトリ構造になります。

├ projects
 ├ user
     ├ _user-list.scss
     ├ _user-detail.scss
     ├ _user-hobby.scss

なお、要素のクラス名は冒頭に「p-」をつけます。


utility

utilityはmarginやpaddingなど微調整をするスタイルを保存するディレクトリです。

強制的に適用のが基本となるため「!important」を設定しています。メディアクエリ毎のスタイルもまとめています。

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

対象となる要素のクラス名には冒頭に「u-」を付けて記述します。

├ utility 強制的に適用するスタイル(!importantがつくもの)
 ├ _display.scss
 ├ _margin.scss
 ├ _padding.scss
 ├ _typography.scss


_space.scss

marginとpaddingに関するスタイルです。

一定間隔のmarginとpaddingを用意します。間隔は_variable.scssで定義しています。(例: u-mt8margin-top: 8px !importantとなるセレクタを作成する)

.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で定義しています。(ここでは8の倍数の間隔を使用)

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


_typography.scss

textに関するスタイルをまとめています。font-weightやtext-alignなどのスタイルを定義しています。

// 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で定義しています。

// size
$sizes: tb, sp;

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

メディアクエリは_mixin@scssで定義しています。

_display.scss

displayに関するスタイルです。

.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で定義しています。

// size
$sizes: tb, sp;

メディアクエリは_mixin@scssで定義しています。


コンパイル用のファイル

実際にコンパイルするファイルはsassディレクトリ直下にある「_」のないファイルです。

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


inviewとoverviewとは何か?

読み込むファイルを1種類で読み込むのではなく、inviewoverviewの2つに分けています。

これは、クリティカルCSSの考え方で以下のような分類になります。

クリティカルCSSの考え方
  • inviewにはファーストビューで必要なスタイルを記述しする。headタグの中でstyleタグの中で呼び出し、HTML内に直接記述する。
  • overviewはファーストビュー以外で必要なスタイルを記述する。body閉じタグの前でlinkタグで読み込む。

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


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";


common_overview.scss

全体で共通となるファーストビュー以外で必要なスタイルをまとめたファイルです。

@charset 'utf-8';

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

// layout
@import "layout/footer";

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


補足

必要に応じて、ページ毎にページ名_inviewページ名_overviewを作成します。


タイトルとURLをコピーしました