【Udemy(CSS / Sass) : CSSとブラウザ】
良いHTMLとCSSを書くための3本柱
下記3つを常に意識して書く
1. レスポンシブデザイン(応答性の高いwebデザイン)
┣ あらゆるデバイスの、あらゆるスクリーンサイズで美しく機能する1つのwebサイトを構築する
┣ 今の時代スタンダード、2017年以降以降にレスポンシブでないwebサイトを構築することはあり得ない
2. 保守性と拡張性のあるコードの記述
┣ ユーザーにと言うより、開発者である自分にとって大事。CSSやフロントエンド開発者としてよりプロフェッショナルになるためには重要。
┣ 綺麗でわかりやすく、将来の成長を支えるコードを書くことで、将来引き継ぐかもしれない他の開発者にとっても再利用可能なコードを書く = CSSアーキテクチャに気を配る
3. webパフォーマンス
┣ webサイトやアプリのパフォーマンスを向上させると言うことは、より速く・より小さなサイズで、ユーザーがダウンロードするデータを少なくすることを意味します。
パフォーマンスに影響を与えるものはたくさんある。
3-1. HTTPリクエストをできるだけ少なくすること = HTML文章に含めるファイルをできるだけ少なくすること(クマーラさんが言ってた、コードを少なくする。Sassなどのプリプロセッサを使う)
3-2. パフォーマンスに
┣ 画像を圧縮することで、最終的なユーザーの使用帯域幅を少なくすることができる。
⭐️⭐️⭐️より良いCSS開発者になる為の概念
◎あるwebページをブラウザで読み込んだ時に、cssのコードが実際にどうなるのか、と言うことから始める。インターネットの裏側では、ブラウザが要求したwebサイトの読み込みを開始するまでに、さまざまなことが起こる。
┣ httpリクエスト・適切なドメインネームサービスの把握 = しかし今回はその全てに注目しなくて良い。
ユーザーがページを開いたコンピュータのブラウザで何が起こっているのかにのみ関心を寄せている。
流れ
- ブラウザが実際に最初のhtmlファイルを読み込み始めた時が出発点。(Load HTML)
- そして読み込まれたHTMLコードを受け取り、解析する。(Parse HTML)
- このプロセスから、ブラウザはいわゆるDocument Obfect Model(DOM)を構築。
┣ DOMは基本的にweb文章全体を親・子・兄弟要素からなあある家系図のように記述している。Document Obfect Modelには、デコードされたhtmlのコード全体が格納されている。
◆css解析手順(第一段階)
- ブラウザがhtmlを解析すると、htmlのheadに含まれるスタイルシートも見つかり、読み込みを開始する(Load CSS)
- 解析段階では、主に2つのステップがある htmlと同じようにcssも解析されますが、cssの解析はもう少し複雑。
┣ 競合するcss宣言は、カスケードと呼ばれる処理によって解決される(Resolve conflicting CSS declarations (cascade))
◆css解析手順(第二段階)
第2段階は、CSSの最終的な値を処理することである。
ex) パーセント単位で定義されたマージンをピクセル単位に変換する。
・margin-leftを50%と定義したとする。しかし、スマホの50%と大画面の50%は全く違う
・最終的なCSSもDOMと同じようにCSS Object Modelというツリー状の構造体に格納されます。
そして、HTMLとCSSを解析して保存したものが、Render Treeを形成している
・これで、ようやくページのレンダリングに必要なものが揃う
・ビジュアルフォーマットモデルは、私たちのコードの書き方に大きく関わってくる。
◎こうしてビジュアルフォーマットモデルが作業を終えると、いよいよwebサイトが画面にレンダリング(描画)され、プロセスは終了。
CSSの解析段階
◎前段
- 最初に矛盾するCSS宣言を解決し、次に最終的なCSS値を処理することを忘れないでください。
💡CSSはさまざまなソースから取得することができる
・一番多いのは私たち開発者が書くCSS。スタイルシートに入れるこれらの宣言は、Author(著者宣言)
・もう一つのソースはユーザー宣言(User)。これはユーザーから来るCSSである。
┣ ユーザーがブラウザのデフォルトのフォントサイズを変更した場合、それはユーザーCSSであり、最後に、デフォルトのブラウザの宣言がある。
┣ ex) リンク用のアンカータグをHTMLに記述した後、スタイルを一切変更しないと、通常は青いテキストと架線が表示される。それは、ブラウザが設定するためのユーザーエージェントCSS=Browser(user agetnと呼ばれる。
=カスケードでは、これらの異なるソースから来るCSS宣言を組み合わせているが、複数のルールが適用される場合、カスケードでは実際にどのように競合を解決するのでしょうか?
1. 重要度
2. セレクタの特異性
3. 競合する宣言のソース順
※英文訳:異なるスタイルシートを組み合わせて解決するプロセス異なる CSS ルールと宣言の間で競合が発生する場合、複数のルールが特定の要素に適用されます。
仕組み
・まず、カスケードは、競合する宣言が宣言された場合、つまりソースにもとづいて、異なる重要度を与えることから始まる。最も重要な宣言は、importantキーワードでマークされたユーザー宣言である。
・次に重要なのは、importantと書かれた作者の宣言である。
・3番目に通常の作者宣言
・4番目 通常のユーザー宣言
・そして最後に、最も重要でないのがデフォルトのブラウザ宣言。これはブラウザからデフォルトで来るこれらの宣言を簡単に上書きすることができるので、実はとても理にかなっている。
仕組み2
2-1.
・カスケードが何をしているかと言うと、宣言セレクタの特異性を計算し、比較すると言うもの。インラインスタイルは最も特異性が高く、次にID、クラス、擬似クラス属性セレクタ、最後に最も特異度の低い要素セレクタと擬似要素セレクタが続く。
・同じ重要度をもつ競合する宣言がある場合、先ほど示した優先順位に基づいてセレクタの特異性を計算する。
2-2. 中央下、画像部分
◎背景色が青、緑、紫、黄のいずれになるか
┣ インラインスタイル、ID、クラス、擬似要素と属性、そして最後に要素、セレクタ内での出現回数をカウント。※インラインスタイルはHTMLに記述する必要があるが、ここではそうなっていないので、0になっている
・項目❷:elemantsのカウント、nav要素とdiv要素、要素カテゴリに対しても2つ
・項目❸:クラスのカウント、ボタンクラス、そして擬似クラスであるhoverで2つ
💡仮に❷・❹が同点だった場合、最後に記述されたCSS宣言が適用される。
※SOURCE ORDER英語訳:コードの最後の宣言は、他のすべての宣言をオーバーライドし、が適用されます。
◎まとめ
-
! important でマークされた CSS 宣言は最も高い優先度を持ちます。
-
ただし、! important は最後のリソースとしてのみ使用してください。正しい特異性を使用する方が良い — 詳細
メンテナンス可能なコード!
※何が起こっているか突き止める必要がある。その方が、ただ重要なものを追加するよりも、簡単な方法で問題を解決できる。保守性の高いコードとは、具体的に考えて、最後のリソースとして重要なものだけを使う -
インライン スタイルは常に外部スタイルシートのスタイルよりも優先されます。
-
1 つの ID を含むセレクターは、1000 のクラスを含むセレクターよりも具体的です。(IDが優先、本当に特定したい場合はIDを使用)
-
1 つのクラスを含むセレクターは、1000 個の要素を含むセレクターよりも具体的です。
-
ユニバーサル セレクター * には特異性の値 (0, 0, 0, 0) がありません。
-
セレクターの順序よりも具体性を重視します。
┣ こうしておけば、いつかCSSのこーそを全て並べ変えたとしてもコード全体を混乱させることは少ない -
ただし、サードパーティのスタイルシートを使用する場合は、順序に注意してください。作成者のスタイルシートは常に最後に配置してください。
カスケード補足
・!importantを使うことは悪い兆候。コードをリファクタリングして、そこにあるものを変更した方がいい
・特異性の重要:期待通りに動かなかったら、セレクタの指定に注意
CSS パース
CSSの解析段階で値がどのように処理されるかについて
「なぜ、このようなことを学ぶことが重要なのか」
┣ rem、vhなどのピクセル以外の相対的な単位を使うたびに、最終的にピクセルに変換されることを知る必要があり、それがどのように行われているか知る必要がある。
◎まとめ
翻訳:
・各プロパティには初期値があり、何も宣言されていない場合 (および継承がない場合 - 次の講義を参照) に使用されます。
・ ブラウザは各ページのルート フォント サイズ (通常は 16 ピクセル) を指定します。
・パーセントは、フォント サイズの指定に使用される場合、親のフォント サイズを基準にして測定されます。
・長さを指定するために使用される場合、パーセンテージは親の幅を基準にして測定されます。
・em は、font-size の指定に使用される場合、親の font-size を基準にして測定されます。
・em は、長さを指定するために使用される場合、現在のフォント サイズを基準にして測定されます。
・rem は常にドキュメントのルートフォントサイズを基準にして測定されます。
・vh と vw は、ビューポートの高さと幅のパーセンテージ測定値です。
の順番が期待通りにならないことがある。
:::
CSS パース補足
継承とは
・親要素のプロパティ値を子要素に伝搬させる方法
ex)子要素のline-heightをどうするか
-
CSSの各プロパティには値が必要である。(Every CSS)
-
要素のあるプロパティを処理する際、CSSエンジンがまず尋ねるのは、カスケード値があるかどうか(Is there a cascaded value?)
・あればその値が使用される(Specified value)
・カスケード値がない場合:継承されるかどうか = 内容によって異なる(Is the property inherited?)
┣ プロパティには継承されるものとされないものがある(Computed value of)
・されるプロパティが継承された場合、プロパティの値は、その親要素の計算値となる。
◎まとめ(英訳)
• 継承により、いくつかの特定のプロパティの値が親から子に渡されます。
より少ないコードで、より保守性の高いコードを書くことが可能。
• フォントファミリー、フォントサイズ、色など、テキストに関連するプロパティが継承されます。
┣ margin / paddingは継承されない。してしまったらどえらいことになる。
• プロパティの計算値は、宣言された値ではなく、継承されるものです。
• プロパティの継承は、誰もそのプロパティの値を宣言しない場合にのみ機能します。
• 継承キーワードは、特定のプロパティの継承を強制します。
•Initial キーワードは、プロパティを初期値にリセットします。
remの使い方
絶対画素単位(px)を、相対画素単位(rem)へ
┣ モバイル端末でページを表示するためのブレークポイントを押さえた時、1つの簡単な設定でページ上のすべての測定値を変更できる方法が欲しいから
※何百行ものコードやメディアクエリを記述する代わりに、一つのグローバルな設定を変更するだけでいいから
rem単位は常にルートフォントサイズとの関係である
①⭐️⭐️ルートフォントサイズを設定
・ページ上の他のすべてのサイズを簡単にremに変更することができる
html{
font-size: 10px;/* 10pxの理由:1remが10pxに相当するから */
}
body{
padding: 3rem;
}
.btn:hover{
transform: translateY(-3px);
box-shadow: 0 .5rem 1rem rgba(0,0,0,.2); /* 0.5はなるべく「.5rem」と書く。プロが書いているいい習慣というだけ */
}
レスポンシブ時にとても効果的
Udemy CSS/sass 18
⭐️⭐️継承の力
・継承を使えるときは、いつでも使うようにする
/* 擬似要素の後や前には、この動作はしませんし、変な動作が起きると困るのでこれらの要素もここにいれる */
*,
*::after,
*::before{
margin: 0;
padding: 0;
/* inheritを使って強制的に継承させる。box-size自体には継承させれないが、ページ全体の各要素のbox-sizingプロパティを継承に設定することで、ここでborder-boxに設定したものが自動的に継承される */
/* プラグインや他のコンポーネントでボックスサイズを変更する際に、ボックスサイズに別のプロパティを使用したい場合など、ボックスサイズの変更が容易になるため、CSSコミュニティではこの方法がやや優れていると考えられている*/
box-sizing: inherit;
}
body{
box-sizing: border-box;
}
webサイトのレンダリング
英文訳:CSSビジュアルフォーマットモデルは、レンダツリーの各要素に対して、ボックスを計算してレイアウトを決定するアルゴリズムレンダー ツリー内の要素ごとに、これらのボックスのページの最終的なレイアウト
- ボックスの寸法: ボックスモデル。
- ボックスの種類: インライン、ブロック、およびインラインブロック。
- 位置決めスキーム: フロートと位置決め。
- コンテキストのスタッキング。
- レンダー ツリー内のその他の要素。
- ビューポートのサイズ、画像の寸法など。
これらの要素を総合して、ブラウザは最終的にユーザーにとってどのようなwebサイトになるかを判断
ボックスの形
英文訳:
• コンテンツ: テキスト、画像など。
• パディング: 周囲の透明な領域、内容物、箱の内側。
• ボーダー: paddingの周囲を囲み、内容。
• マージン: ボックス間のスペース。
• 塗りつぶし領域: 塗りつぶされる領域、background color またはbackground image.。
ボックスモデル: 高さと幅
・ある要素の高さや幅を指定しないことにした場合、ビジュアルフォーマッティングモデルは、ボックスの内容を利用して、そのサイズを決定するだけ。
total width = 右ボーダー + 右パディング + 指定幅 + 左パディング + 左ボーダー
total height = 上の境界線 + 上のパディング + 指定高さ + 下のパディング + 下の境界線
ex) 高さ = 0 + 20px + 100px + 20px + 0 = 140px
┣ つまり、ボックスの幅や高さを定義するたびに、paddingとborderが定義したものに追加される。 = 現実的ではない
ボックスサイズのボックスモデル: ボーダーボックス
そこで、上記問題を解決するために、border-boxの値でbox-sizingプロパティを使用することにした。
・box-sizing: border-boxに設定すると、heightとwidthはcontent areaだけでなく、paddingとborderを含むbox全体に対して定義されることになる。
┣ これは、同時に指定したpaddingやborderは要素の高さや幅に加算されるのではなく、コンテンツ領域の内側の幅を縮小することを意味する。
ボックスのタイプ: インライン、ブロックレベル、およびインラインブロック
-
Block-level-boxは常にdisplayプロパティで定義されている。
┣ (display: flex)、(display: list-item)、(display: table)ブロックレベルのボックスも生成することに注意。 ブロックは常に縦方向に次々とフォーマットされていく -
Inline-boxは、ブロックレベルのボックスとは基本的に逆(資料左側)
┣ コンテンツが行単位で配置されるため、コンテンツが実際に必要とするスペースのみを占有することになる。したがって、その後に改行が入ったり、一緒に改行されることもない。しかし、その代わりブロックレベルの親要素の中に収まっているだけ。
┣ heightとwidthのプロパティは適用されない。・水平方向のpaddingとmarginしか指定できない(左と右だけ) -
Inline-block-boxは、技術的に上記2つを併せたもの(Inline-boxでありながら、内側はBlock-level-boxとして機能する)
┣ 技術的にはインライン要素なので、コンテンツスペースだけを使い改行もしない。しかし、内側はブロックレベルのボックスとして機能するため、通常のブロックレベルボックスと同様にボックスモデルが適用される。
位置決めスキーム: 通常のフロー、絶対位置決めおよびフロート
1.Normal flow (Default、position: relative)
• デフォルトの位置決めスキーム。
• フローティングではありません。
• 絶対的な位置ではありません。
• 要素は以下に従ってレイアウトされます。ソースの順序。
-
Floats(float: left、float: right)
• 要素が通常の流れから完全に外し、可能な限り左・右に移動させ、その要素を含むボックスの端または他のfloatされた要素に接触させるものである。
• テキスト要素とインライン要素は、フローティングされた要素の周囲に回り込む。
• 要素をフロートさせた場合、コンテナは要素に合わせて高さを調整しないので、問題が生じることがある。 -
Absolute positioning (position: absolute、position: fixed)
・floatと同様、positionプロパティをabsoluteにしたり、fixedにすると、その要素は通常のフローから外れる。
• 要素が周囲のコンテンツまたは要素に全く影響を与えないという点。むしろ重なることもある
• 上、下、左、および右に要素を相対的な位置からオフセットします
?:絶対位置の要素は、同じスペースを占める他の要素と重なることがある
スタッキングコンテキスト
スタッキングコンテキストは、ページ上の要素のレンダリング順を決定するもの。
新しい積層コンテキストは、異なるCSSプロパティによって作成することができ、最も多く知られているのはZ-index
・z指数が高いものが上に、z指数が低いものが下
CSSのアーキテクチャ、レイアウトの考え方、プロフェッショナルなコードのマークアップの仕方 ※ワークフローに大きな価値をもたらす
保守可能そしてスケーラブルなコード(Maintainable and scalable code)
・綺麗
・モジュール化
・再利用可能
・webページやアプリが成長する必要がある場合に、より多くの機能を簡単に追加できるようなコードを求めている
プロジェクトの初期段階からHTML/CSSのコードに関する重要な決定を行う必要がある
実際にコードを書く前に、WEBページやwebアプリのレイアウトを考える必要がある
◎3つのマインドセット
・シンク(THINK)
┣ 実際にコードを書く前に、WEBページやwebアプリのレイアウトを考える必要がある
。
・ビルド(BUILD)
┣ HTMLとCSSで、クラス名を統一した構造で構築します。
・アーキテクト(ARCHITECT)
┣ 同時に複数のファイルやフォルダーを使用することで、論理的なCSSアーキテクチャを構築する必要がある。
シンク(THINK)
◎コンポーネント駆動設計
• インターフェイスを構成するために使用するビルディングブロック。(すべてのソフトウェア開発で使われている原則)
┣ CSSでは、コンポーネント駆動設計により、ページをモジュール化したコンポーネントに分割することを試みています。
• ページのレイアウトによってまとめられます。
┣ 基本的にインターフェースは、ページ全体のレイアウトによってまとめられた、コンポーネントの集合体であると考えることができる。
• プロジェクト間および異なるプロジェクト間で再利用可能。
┣ コンポーネントのライブラリを構築し、それをプロジェクト間で再利用することで、開発のスピードアップを図ることができる。
• コンポーネントは、ページのどこにあっても完全に単独で使えるように、独立している必要がある
┣ コンポーネントが親要素に依存しないことを意味する。
これらの全てによって、CSSコードのメンテナンスが容易になり、必要に応じて拡張することができる。
◎アトミックデザインに少し似ている
ビルド(BUILD)
クラスの命名に一貫した戦略と構造を持たせることが、重要。
BEM
• ブロック要素修飾子 (BEM)
┣ レイアウトをマークアップするために、すっきりとしたシステム。最後のスライドで定義したコンポーネントがBEMのブロックであることを意味する。
• BLOCK: ブロックは単体で意味を持つ部品である。
• ELEMENT: 要素とはブロックの一部であり、それ自体では意味を持たない。
┣ スライドでは、情報パネルや統計ボックスがそれにあたる。
• MODIFIER: ブロックまたは要素の異なるバージョン。
┣ 通常のブロックや要素とは、異なるものにするためのフラグ
ex)この例では、ボタンを丸くするためのモディファイアを用意している。すべてのボタンにたいしていくつかのルールがあり、モディファイアを使って、より具体的な別のボタンを作ることもできる
CSSのアーキテクト化 (ARCHITECT)
CSSを格納するための論理的なフォルダとファイル構造を作成すること
◎Hugo Giraudelが紹介した7-1パターン
┣ 7つのフォルダに部分的なSassファイルを置き、1つのメインSassファイルにすべての部分ファイルをインポートして、最終的に1つのコンパイル済みCSSスタイルシートを作成する。
- 基本的な製品の定義を入れるbaseフォルダ
- コンポーネントごとに1つのファイルを置く、componentsフォルダ
- プロジェクト全体のレイアウトを定義するlayoutフォルダ
- プロジェクトの特定のページ用のスタイルを置くpagesフォルダ
- 異なる視覚テーマを実装したい場合はthemeフォルダ
- 変数やミックスインなど、CSSを出力しないコードを置くabstractsフォルダ
- すべてのサードパーティCSSが入るbendorフォルダ
BEMでの書き方 実践
◎headerはBEMシステムにおいて、それ自体で意味を持つ独立したコンポーネントであるため、明らかにブロックであり、ブロックであるため、その中にあるすべての要素のにもヘッダーが付属しているはず。
ex)
- logo-boxはヘッダーの中にしか存在しない要素になる。ブロックの一部ではあるが、単体での意味はないため。(この場合headerがブロック、logo-boxが要素になる)
- ブロックの見出しとなる部分、単に少し異なるバージョンを作成するだけ。ブロックそしてモディファイアがある場合はダッシュダッシュ モディファイアの名前、要素であればアンダースコア-
◎プロフェッショナルになるためには、理論的・基礎的な部分を理解することが必要
修正前
<header class="header">
<div class="logo-box">
<img src="img/logo-white.png" alt="logo" class="logo">
</div>
<div class="text-box">
<h1 class="heading-primary">
<span class="heading-primary-main">Octdoors</span>
<span class="heading-primary-sub">is where life happens</span>
</h1>
<a href="#" class="btn btn-white btn-animated">Discover our toues</a>
</div>
</header>
修正後
<header class="header">
<!-- BEM:について ブロックの見出しとなる部分、単に少し異なるバージョンを作成するだけ。ブロックそしてモディファイアがある場合は[ダッシュダッシュ モディファイアの名前]、要素であればアンダースコア-->
<div class="header__logo-box"><!-- BEMについて = headerと、ブロックとエレメントを分けるのはダブルアンダースコア -->
<img src="img/logo-white.png" alt="logo" class="header__logo"><!-- BEM:このヘッダーにしか存在しないから -->
</div>
<div class="text-box">
<!-- BEMについて:少し事情が違う、これを単独でブロックとして扱うことができる。このh1要素を他で使いたいとする。別のページがあり、このようなヘッダーがなく、この主見出しを使いたいとする。この1つは独立したブロック -->
<h1 class="heading-primary">
<!--[ダッシュダッシュ モディファイアの名前]-->
<span class="heading-primary--main">Octdoors</span>
<span class="heading-primary--sub">is where life happens</span>
</h1>
<!-- BEMについて:ボタンはもちろん独立したコンポーネントなので、BEM記法ではブロックと考えることができる。このボタンは、このページ全体で使用することになるから -->
<!-- ここでは[--]とみなすことができる -->
<a href="#" class="btn btn-white btn-animated">Discover our toues</a>
</div>
</header>