CSS Nite LP54「Coder's High 2017」フォローアップ(4)久保 知己さん(まぼろし)+伊藤 由暁さん(まぼろし)

2017年11月4日(土)ベルサール半蔵門 イベントホールで開催したCSS Nite LP54「Coder's High 2017」のフォローアップとして、久保 知己さん(まぼろし)+伊藤 由暁さん(まぼろし)の『CSSをちゃんと書くためには?』セッションのスライドなどを公開します。

フォローアップメッセージは、イベント開催直後(2017年11月)の時点のものです。

フォローアップメッセージ(補足など)

p>「CSSをちゃんと書くためには?」のCSSを担当した久保です。
CSSでは重要な仕様だけど、なかなか触れられない「視覚整形モデル」について、ご紹介しました。
ちゃんと理解するのは難しい内容ですが、これを理解しておくと不思議なCSSの挙動も理解しやすくなります。
視覚整形モデルには、位置決定スキームというものあり、通常の要素の流れから逸脱すると、marginの動きに違いが出ます。プロパティの働きなどを調べる際に、視覚整形モデルがわかっていると、より理解が進むでしょう。

またセッションでは、CSSの宣言を紹介した継承の特性やwidthプロパティを使った例を2つご紹介しました。
CSS設計というと、命名規則やコンポーネントの分け方などに注視されがちがですが、宣言もCSS設計の重要な要素のひとつというこをお伝えしました。宣言の行い方は、それぞれのプロパティの特性などを理解する必要があり、習得が難しいポイントです。
しかし宣言もCSS設計のひとつと意識することで、宣言の行い方も上達していくことでしょう。
再現したデザインとCSSの振る舞いがスマートに一致したCSSを目指すことが大切です。


「CSSをちゃんと書くためには?」のSassを担当した伊藤です。ご参加ありがとうございました。

CSSは命名規則や構造化だけでなく宣言そのものも重要であり、その宣言記述に注力するために効率的で意味のあるSassを構築しましょうという話でした。

セッション後の質問の補足

無駄なCSSやSassを書いていないかチェックしてくれるルールはありますか?

完全ではありませんが、Style Validatorというブラウザの拡張機能があります。

http://style-validator.io/

display: inlineが指定されたセレクタにwidth指定やheight指定があると「No effect(効果なし)」というエラーを表示してくれます。

アンケートへの回答

今回の授業だけなく何か情報を発信しているなら教えて欲しい

書籍やAdobeの公式ブログでも執筆を行なっています。また個人ブログでも、定期的に情報を発信しています。

久保

伊藤

詳細度を高めている案件がある場合のリファクタリングが悩みである

詳細度が高くなっているとリファクタリングがしにくいのは私も感じます。
どの程度リファクタリングするのかわからないのですが、もし全てのCSSを書き換えていいのであれば、私はセレクタの命名規則を変えてリファクタリングすることをおすすめします。
命名規則を変えることによって、古いCSSとリファクタリングのCSSが混同していても、セレクタ名のバッティングを防ぐことができます。

ただしこの方法は、全て書き換えるのでコストがかかります。既存の状態を残してリファクタリングするのであれば、ボタンなどの小さく影響範囲の小さい箇所から、リファクタリングするしかないと思います。

メディアクエリの書き方ですが、(min-width: *) and (max-width: *) ってかくのと、1つだけ指定して上書きしていくのと、どちらがおすすめですか?

デザインによります。PCとスマートフォンで見た目が異なる箇所が多いのであれば、限定的に指定できるandを使って指定が有効です。
ただ見た目で似た部分が多く、CSSの宣言の差が少ないようであれば、1つだけ指定して上書きする方法をとっています。

CSSのプロパティでは仕様書と一般的な認識と違うようなものがあれば聞いてみたいです。

一般的な認識が難しいですが、例えばwidthとmarginプロパティとの関係性は、10の状態によって変化します。
幅とマージンの計算 | 視覚整形モデル詳細

また別の例をあげると、displayプロパティの最初値はinlineです。ではなぜ、ブラウザで見たときは、divやul要素などはdisplay: block;の挙動を行うのか。それはブラウザのスタイルシート「User Agent Stylesheet」が効いているからです。そのためブラウザが対応していなかったり、未知のHTMl要素は、すべてdisplay: inline;として表示されます。

CSSフレームワークとCSS設計の組み合わせってやりますか?

はい、弊社でCSSフレームワークを利用する場合はBootstrapを利用しています。CSSフレームワークとは別のCSSを追加するときは、命名規則が重複しないようにMindBEMなどを使う場合が多いです。

widthを9xxpxにしてmargin: autoにしちゃってるんですが、ダメでしょうか?

もちろん、ダメではありません。
レスポンシブなどで、もし段階的に幅の指定を変えなければならないのであれば、widthプロパティをメディアクエリで操作しなければなりません。
CSSで実現したい振る舞いによって、宣言の解は変わってきます。

どの段階で無駄を省いていくか?

サイトの規模にもよりますが、ある程度のコンポーネントが揃った時に、行なっています。

命名規則ではどういうルールで書いているか教えて欲しい

案件によって指定される場合もありますが、弊社では下記が多いです。

  • MindBEM
  • FLOCSS

&記号を使うとgrep検索しづらくなる

なりますね。目的のセレクタがあるSCSSファイルをすぐgrepするために、伊藤はセレクタの上にフルのセレクタをSCSSコメントで書いておくなどしています。

.box {// .boxheader&header {}// .boxbody&body {}// .boxfooter&footer {}}

エディタによっては追跡可能です。

WebStorm 2017.3 EAP にて。 https://t.co/1vKCCEqZhG"

あるいは&記号でセレクタを分断せずに、

.box {@at-root {& {color: navy}.boxheader {color: gold}.boxbody {color: tomato}.boxfooter {color: skyblue}}}

と書いています。@at-rootもSassの機能の一つで、中身がトップレベルのスコープで解釈されます。それでいて&記号もちゃんと親ブロックのセレクタを取得してコンパイルされます。

.box {color: navy}.boxheader {color: gold}.boxbody {color: tomato}.boxfooter {color: skyblue}

&を使う際、一つのSCSSファイルの中で違うの文脈の&が出てしまうと混乱しますので、BEMで言うところのブロック単位(SMACSSではっモジュール単位)でSCSSファイルを分けると良いです。

.header {&logo {}&lede {}}.header-nav {&list {}&item {}}

前述のような形ですと、&が.headerだったり.header-navだったりしてしまうので、header.scssとheader-nav.scssのように別ファイルに分けてください。

ネストは何段階まで許容している?

本当に必要であればいくらでもネスティングしていく、程度の気持ちです。BEMならブロックの子要素は全て&_Element {}のようにSCSS上で並列して書けますので、そもそも深くなりません。BEMエレメントから3階層程度が個人的な許容範囲です。@at-rootを使うとそのぶんインデントが増えますがそれすら気になるならネスティングは使わないとプロジェクトで決めてしまった方が気が楽かと思います。

&の問題点?

&はgrepしづらい、セレクタが分かりづらくなるという意見をいくつかいただきました。伊藤としてはブロック / モジュール単位でSCSSファイルを分割しているので、&は常にそのブロックであるという認識で書いています。よって&で分かりづらくなったことはありません。

このセクションでは、漫然としたネスティングで詳細度を高めるのはやめましょうというニュアンスをお伝えしたかったのですが、&記号の方に意識が注がれてしまう説明だったと反省しています。

改めてまとめますと「ネスティングは主従関係が可視化されるので便利だが、不必要なネスティングで詳細度が高くなると、保守・運用フェーズでメンテナンス性が下がる。必要な場合は&記号を活用して詳細度を下げましょう」ということです。

CSSの管理・設計を行うにあたり、プロダクトマネージャーやデザイナーにどうアプローチすれば良いか

HTMLとCSSもプロダクトを構成するに欠かせないものの一つであり、「誰がやっても同じもの」ではないことは啓蒙が必要です。無秩序に作ったCSSではスケジュールやクオリティーは保証できません。CSSにも相応の作業時間と専門知識が欠かせないからです。単にデザインを再現しているだけと思われないよう、プロダクトにとって保守性・可搬性の高いCSSを書き、それをアピールしていくと良いでしょう。

@functionを使ったz-indexの管理方法がためになった

ありがとうございます。z-indexの管理が必要ではないプロジェクトでは無用の長物ですので、このセクションが響かなかった方もいるかと思います。

CSSではマジックナンバーはやめようというTIPSは有名ですね。とりあえず一番上に出したいからz-index: 9999というような指定はCSSではよくないとされています。大規模なウェブサイトや施策が入り乱れるサービスですと、z-indexの値は混沌を極めます。@functionで重なり順だけ管理すれば、数字の大きさは気にしなくて済みます。

数字が大きい方が上に来るのだから管理しなくても別にいいのでは、という意見もあるかもしれません。しかし、z-indexは数字が大きい方が前面に表示されるとは限りません。スタック文脈と呼ばれる概念があり、単純な数字の大小だけでは説明できないのがz-indexなのです。

時間の関係でスライドに入れられませんでしたが、z-indexのスタック文脈問題に対応すべく、久保がカスタムした関数があります。二階層以上や逆順での管理が可能になっていますのでぜひチェックしてみてください。

Sassを使ったz-indexの管理 - Qiita

@functionの他の活用法

Sassの組み込み関数のuniqueid()と組み合わせてキャッシュバスターを付与することができます。

@function cache-buster($path) {@return #{$path + "?" + uniqueid()};}.kv {background-image: url(cache-buster("/assets/images/kv.png"));}
.kv {background-image: url(/assets/images/kv.png?u278e85ca);}

作成したcache-buster関数に画像パスを引数に入れると、コンパイル時にパスの後ろに?u278e85caというパラメータが付与されます。uniqueid関数はコンパイルの度に新しい文字列を出力するので、キャッシュバスターに利用できるというわけです。

Generated by SassMeister.com.

@importで変数を使う方法はありますか?

残念ながらないです。Sassの@importはurl()型か文字列しか受け取れず、インターポレーションやquote()を挟むことができません。

汎用性の高い変数がうまく作れない

用途が限定されすぎてる値を変数化するのはあまり意味がありません。かといって、$base: 10px;などを作りあらゆるところで演算して使えばいいというわけでもありません。

汎用性に必要な観点は「粒度」です。変数がpx系か%系といった粒度ではなく「.boxに使うサイズバリエーション」「ブレークポイントのサイズバリエーション」という具合に主に何に使われるかでカテゴリ分けしています。

まずは変数を使わずにベタ書きでコーディングを進め、変数でまとめた方がいいと感じたものを変数化すれば良いでしょう。変数を使うか使わないかでコンパイル結果が変わることはないので、定期的に変数を見直すのも良いです。

SCSS記法とSass記法の違い

SCSS記法は素のCSSと同じように {} や ;を使いますが、Sass記法はスペースとインデントと改行で書く、とセッションでは説明しました。Sass記法は

  • {}を使わない
  • 次のプロパティーは必ず改行して記述
  • :のうしろに必ずスペースが必要
  • ;が不要
  • インデントが宣言ブロックを表す
  • mixinはショートハンドがある

といった特徴があります。

// SCSS記法@mixin ir {display: block;overflow: hidden;text-indent: 101%;white-space: nowrap;}.nav {color: blue;font-size: 0.3em;a {width: 50px;@include ir;&:hover {background-color: #eee;}}}
// Sass記法=irdisplay: blockoverflow: hiddentext-indent: 101%white-space: nowrap.navcolor: bluefont-size: 0.3ema+irwidth: 50px&:hoverbackground-color: #eee

前述の2つのコンパイル結果は同じですが、Sass記法の方が記述が少なくて済むので好きという人は少なくありません。

社内でCSSを書くスタッフにレベル差があってSassが導入しづらいがどうしたらよいか

組織の規模に関わらず個人向けでも大勢向けでも同じで、「繰り返し啓蒙していく」のが一番です。仲のいい社員をイベントに誘って一緒に参加したり、社内勉強会を開いたり、啓蒙活動にも色々方法があります。Slackなどの分報でブログ記事などを共有するのも良いですね。まずは業務で関わった人から巻き込んでいってはどうでしょうか。

2019年、CSS Niteでは49回の関連イベントを通して123セッションが行われました。その中からベスト・セッション+αを選びました。

2010年から2019年のベスト・セッション