.../articles/

scopedを前提とした小~中規模CSS設計を考える

案件ではNuxtを利用することが多く、大仰なCSS設計は逆に作業効率を悪化させる。コンポーネントごとに閉じる世界なので、命名規則をがちがちに決めて冗長なクラス名を付けたくない。ということで今自分が思っているCSSの設計粒度を、メンバーとすり合わせる意味でもまとめておく。

前提

案件でいつもこんな流れでやっているなーという以下条件を前提として考えています。

  • Nuxt.jsを利用。小~中規模のウェブサービス(サイト)構築案件が対象。
  • 基本的にCSSはscopedでvueファイルに記載
  • ノーマライズ、リセットCSSなどはconfigなどで読み込んでおく

コンポーネント分けについてはこの記事では言及しないです。あれはあれで考え始めると本当に沼が深い。

HTMLとはなにか

こういう哲学的な問いはふわっとしているしいろいろな意見があるけど、一応原点に立ち返りたいのでメモ。
HTMLとは構造化された文章であり、 構造には意味がある。
決してdivでパズルを組むのがHTMLの役割ではない、という点だけ認識が取れていればOKです。

  • 構造上無意味なdiv, spanの利用は避ける(装飾のためだけに使用するのは避ける)
  • section, main, nav, figureなど、HTML5で再定義された要素を使用してセマンティックに要素を配置する
  • 要素はなるべく少なくできる方が良い(場合によるけど)

要素をラップするときは必要なのでdivを使っても良いと思っています。むしろそういう使用方法に限定しておく方がなんのためのdivなのかわかりやすくて良いし。

シンプルに書こう

「シンプルに書く」というと難しく聞こえるかもしれないけど、 明示的に簡単に書く 、ということを意識するとイメージが付きやすいかもしれないです。
情報量を削ぎ落とすこと ≠ シンプルに書くということは注意したいところ。

特に自分以外の人間が見ても分かるかどうかが重要です。
「他人が見ても分かる」「どこに何が書いてあるか分かりやすい」 と言い換えることができると思います。

その他こういったことも意識できると良いかも。

あなたはDRY原則を誤認している? - Qiita

すべての知識はシステム内において、単一、かつ明確な、そして信頼できる表現になっていなければならない。

具体的な記述方法

ではどうやって書くか、具体例を出しつつ列挙していきます。

  • セクションにユニークなクラスを付ける(コンポーネント名をつけるイメージ)
    • 名前はそれ単体でわかるものに極力したい
      • OK例 : hero, newsなど機能や役割が明示される名前
      • NG例 : information1など順序に依存したり、役割が分からない名前
  • セクション配下の命名は基本的に一般的な名詞で良いかなと思います
    • Newsの配下であれば、 .list.item のようなわかりやすいクラス名で良い
    • ただし、きちんとscssを構造化し、 直下セレクタ > を使用する
      • scssの構造化は見やすくするための大事なポイント
  • クラスを書く順序もなるべく意識してHTML側と合わせる
  • そのクラスに付けるプロパティ → レスポンシブ対応用メディアクエリ → 子要素、など、書く順番をルールにしておくとわかりやすいと思います
  • 同じようなプロパティがあっても、やたらとmixinにしたりしない
    • 省力化より明示することを優先する
    • 逆に、色指定やフォントの指定などは変数にしておいて記法のブレを無くす
<!-- 例:ヒーローエリアの下に、ニュースとSNS埋め込みの2カラム表示 -->
<template>
  <main class="cout-wrap">
    <section class="col-wrap wrap-center">
      <div class="hero col-lg-10">
        <h1>Lorem Ipsum</h1>
        <p>Lorem Ipsum is simply dummy text. </p>
      </div>
    </section>
    <section class="col-wrap wrap-center">
      <div class="news col-lg-5">
        <h2>News</h2>
        <ul class="list">
          <li class="item">
            <div class="date">YYYY.MM.DD</div>
            <div class="title">newstitle</div>
          </li>
          <li class="item">
            <div class="date">YYYY.MM.DD</div>
            <div class="title">newstitle</div>
          </li>
          <li class="item">
            <div class="date">YYYY.MM.DD</div>
            <div class="title">newstitle</div>
          </li>
        </ul>
      </div>
      <div class="sns col-lg-5">
        <h2>SNS</h2>
        <div class="twittermodule">
          <iframe>...</iframe>
        </div>
        <div class="facebookmodule">
          <iframe>...</iframe>
        </div>
      </div>
    </section>
  </main>
</template>
/* scoped内に書くcssの構造 */
.hero{
  > h1{
    hogehoge
  }
  > p{
    hogehoge
  }
}
.news{
  > .list{
    > .item{
      > .date{
        hogehoge
      }
      > .title{
        hogehoge
      }
    }
  }
}

.cout-wrap.col-wrap.col-lg-10 などはレイアウトのためのクラスです。
またそれは別途記事にしますので、ここではスルーで。

HTML要素に直接プロパティを指定している箇所もありますが、任意にクラスを付けるイメージです。
scopedの恩恵を最大限利用しています。一般的な名詞はクラス名にすべきではないという声も大きいと思いますが、scopedと直下セレクタを利用して影響範囲を区切るようにします。

共通化するためには

共通化したいクラスはどうするんだ、という問題がありますが、それは Atomic DesignのAtomsをどうするか、という問題と最終的に紐付いてくるな、 というのが自分の考えです。
コンポーネントを階層化して分けて、それぞれを読み込んでいくと、末端はスタイルを指定するプロパティの塊みたいになっていきます。
Atomsレベルのボタンコンポーネントなんかは、ほぼスタイル指定くらいしかすることないですもんね。

そういったプロパティは、クラスを作成し、グローバルで読み込んでおく、というのが良さそうです。
vueファイルとしてコンポーネントするのも分かりやすいですが、小~中規模案件であまりコンポーネント化が激しくなると負担の方が増えてしまいます。

やらないで欲しいこと

以下はアンチパターンです。レビューしてて思ったかなり初歩的なことを列挙しています。

  • 同じクラスに当てるプロパティをばらばらの場所に書かない
  • width,flexなどのプロパティ名をクラス名で使わない
  • 略語を使わない
    • infoなど自分も使いがちだけどやめる
    • btnなどもやめる
  • 何を示しているのか分からないクラスはつくらない
    • mini_infoなどのクラス名を使わない。
  • sp,tbなどのクラス名を使わない。
  • :nth-childやfirst-of-typeは同じ要素の羅列のときにつかう
    • 違う役割の要素を、親要素内の順番で指定する、というような意味で使わない
  • 同じことを何度も書かなくて済むようにする
    • メディアクエリでデバイス幅ごとに同じことを書く、というようなことは避ける

今回は小~中規模と絞ってCSS設計について書きました。
以下のような記事も参考しました。
OOCSS、BEM、SMACSS、FLOCSS、RSCSSを比較して自分にあった設計思想をみつける | Black Everyday Company

ECSSの概要と考え方のまとめ - Qiita

冗長なクラス名が苦手なので、こういった考え方を自分なりに咀嚼して導入していきたいです。
なにかご意見やご感想あればぜひお寄せください。

.../articles/

Articles

記事

AWS AmplifyにmonorepoのNext.js(App Router)をデプロイする

AWS AmplifyにmonorepoのNext.js(App Router)をデプロイする

monorepo管理しているNext.jsをAmplifyにデプロイしようとした際にいくつか躓く内容があったのでまとめておきます。

リモートワーク・オンライン会議でも、スムーズに制作を進めるために大切なこと[資料編]

リモートワーク・オンライン会議でも、スムーズに制作を進めるために大切なこと[資料編]

コロナ禍の影響により、リモートワークの導入をおこなっている制作会社も多く、実際に弊社でも導入しています。

売れるECサイトデザインを作るために。参考にしたいおしゃれな事例の探し方。

売れるECサイトデザインを作るために。参考にしたいおしゃれな事例の探し方。

売れるECサイトのデザインは、「この形式」という決まりはありません。ECサイトで売り上げを上げるなら、しっかりとしたコンセプトと、コンセプトを決定するまでのリサーチが必要です。

制作会社の考える、業務効率化ツールのおすすめ。個人でも使いやすいサービスなど。

制作会社の考える、業務効率化ツールのおすすめ。個人でも使いやすいサービスなど。

新型コロナウイルス感染拡大の影響で、リモートワークが主流になり、弊社でも週のほとんどは各自宅で作業をしています。

Figmaでデザインのコミット履歴を残せるプラグイン【Thought Recorder】をリリースしました

Figmaでデザインのコミット履歴を残せるプラグイン【Thought Recorder】をリリースしました

Figmaを利用するWebデザイナーの助けになれると嬉しいです。使い方は本記事をご覧ください。

ECの構築方法、おすすめのECサービス。

ECの構築方法、おすすめのECサービス。

ファッションや家電、スーパーの買い物でさえもECサイトを利用することが当たり前になりました。加えて新型コロナウイルスの影響もあり、弊社にも「どんなプラットフォームを利用したら良いか」「どれくらいコストがかかるのか」などECに関するさまざまなご相談を頂きます。

FastAPIのスキーマクラスをOpenAPIから生成する方法

FastAPIのスキーマクラスをOpenAPIから生成する方法

PythonでAPIを構築する要件があり、フレームワークに比較的モダンなFastAPIを採用しました。FastAPIはバックエンドの開発を行えば自動でOepnApi定義を生成する機能が備わっていますが、今回はこれを使わず、事前に用意したOepnApi定義からFastAPIで利用するスキーマクラスを生成する方法を紹介します。

Laravel 日本一解りやすい全文検索のマイグレーション記載方法解説

Laravel 日本一解りやすい全文検索のマイグレーション記載方法解説

Laravel + MySQLで全文検索を実装する

GiFT1号目新卒デザイナーの2021年振り返り

GiFT1号目新卒デザイナーの2021年振り返り

いつの間に、年末ですね。入社してもう、9ヶ月も立っていたようです。2021年の振り返りを記事にしました。

TimesclaeDBのデータ圧縮に関して

TimesclaeDBのデータ圧縮に関して

TimescaleDBはデータベース内の一部のテーブルを時系列データとして扱えるPostgreSQLの拡張です。PostgreSQLの機能拡張なので非常に手軽に導入できます。今回はこのTimesaceDBの圧縮について調べたので備忘録として書き綴りました。

すべての記事

お問い合わせ