- 投稿日:2019-11-24T22:53:28+09:00
初心者です。
書籍にあるcss,javascriptのサンプルコードを書いてみたのですが反映されません・・・
どうすればよいのでしょうか??
- 投稿日:2019-11-24T21:45:11+09:00
ブラウザレンダリングの仕組み
概要
webサービスを公開するにあったて必ず使われることになるのがブラウザです。ブラウザがユーザーにwebページを表示する仕組みを理解することで、フロントエンド開発に役立てたり、ページ表示までのレスポンスの改善などに役立てていきたいと思い、今回ブラウザのレンダリングの仕組みの基本事項についてまとめました。
レンダリングの流れ
ユーザーがwebブラウザにURLを入力すると、ブラウザはURLを元に指定のサーバーにTCP/IPプロトコルに基づいてリクエストを送ります。その後サーバはクライアントに対してレスポンスします。以降のレスポンスとして受け取るHTML,CSS,Javascriptをどう処理して画面に表示するのかをレンダリングと定義して、その処理の流れについてみていきます。(この工程はcritical rendering pathと呼ばれています)
https://developers.google.com/web/fundamentals/performance/critical-rendering-path
ブラウザがWebページをレンダリングする仕組みは上のような一連の流れになっています。以下でその一つ一つの工程の内容をみていきます。
オブジェクトモデルの構築
ブラウザはページを描画する前に、DOMとCSSOMツリーを構築する必要があります。
このDOMとCSSOMツリーを構築する工程は「オブジェクト構築モデル」といいます。バイト→文字列→トークン→ノード→オブジェクトモデル(DOM/CSSOM)
という流れでオブジェクトモデルは構築されます。
参考:https://developers.google.com/web/fundamentals/performance/critical-rendering-path/constructing-the-object-modelDOMツリーの構築
変換
ブラウザはディスクやネットワークからHTMLのバイトを読み取り、utf8などの文字コードに応じて<html>や<head>のような文字列に変換します
トークン化
取得した文字列をトークンに変換します。W3C HTML5 standardによって規則が定められています。
字句解析
トークンは<html>や<head>といったオブジェクトに変換されます。
DOMの構築
字句解析で作られたオブジェクトはオリジナルのマークアップの定義に基づいた親子関係をもつ木構造に整形されます。
<html>オブジェクトは<body>オブジェクトの親で、<body>は<p>の親でといったようなHTMLのマークアップでみる構成になります。この最後のプロセスの最終的な成果物が描画するページのDOMとなります。
CSSOMツリーの構築
ブラウザでDOMを構築している際にドキュメントのheadタグで外部のcssスタイルシートを参照しているlinkタグに遭遇すると、ブラウザはページのレンダリングにこのリソースが必要であると解釈してこのリソースに対するリクエストを即座にディスパッチし、CSSを受け取ります。
ブラウザがCSSを解釈して処理できるようにするために、受けっとたCSSをHTMLのDOMツリー構築の時と同じように処理していきます。
レンダリングツリーの構築
DOMツリーとCSSOMツリーを組み合わせることでレンダーツリーを作ります。レンダーツリーは個々の要素のレイアウトの計算し、またピクセルを画面に描画するプロセスである「ペイント」の工程が必要とする値を生成します。
レンダーツリーの生成
DOMツリーとCSSOMツリーを合成してレンダーツリーを生成します。ページの描画に使われる全てのDOMと個々のオブジェクトに使われるCSSをそれぞれ組み合わせます。
レンダーツリーを構築するために、ブラウザは大まかに以下の工程に従います
DOMツリーのルートからはじめて、個々のノードをトラバースしていきます
- scrpitタグなど画面の描画に直接関係ないいくつかのノードは除かれます
- いくつかのノードはCSSにより
display none
などど非表示に指定されたものも除かれます(上の図の例でいうと<span>にあたりますそれぞれのノードに対応したCSSOMをみつけて適用します
CSSが適用された表示可能になったノードを除きます
これらの工程によりページの描画に必要な全てのノードとスタイル情報を含んだレンダツリーが作成されます。
レイアウト
レンダリングツリーの構築まででどの要素が描画されてどんなスタイルが適用されるかが決まりました。この次に、デバイスのviewport内でそれら要素の厳密な位置やサイズを算出するレイアウトの工程が行われます(リフロートも言われます)
ページ上での個々の要素の正確なサイズや位置を求めるために、レンダーツリーのルートからブラウザはトラバースします。
ex)
<!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width,initial-scale=1"> <title>Critial Path: Hello world!</title> </head> <body> <div style="width: 50%"> <div style="width: 50%">Hello world!</div> </div> </body> </html>上のページのコンテンツは2つのネスとされたdiv要素をもち、最初のdivはviewportの横幅の50%に位置し、2つ目のdivは親要素のdivの50%の位置となります。
レイアウトプロセスで出力されるものを「ボックスモデル」といいます。ボックスモデルはviewport内での個々の要素の正確な位置とサイズを算出し、相対的な値を画面上でのピクセルの絶対値に変換します。
ペイント
最後に、レイアウトプロセスで得ることができた個々の要素のサイズと位置情報を最終的な正確なピクセル値へと変えるペイント(又はラスタライゼイション)の行程が行われます
【Chrome DevToolsでの処理の経過の様子】
https://developers.google.com/web/fundamentals/performance/critical-rendering-path/render-tree-constructionレンダーツリーの構築、レイアウト、そしてペイントの各工程に要する時間はドキュメントのサイズ、適用されたスタイルそしてデバイスによって様々です。
それぞれの工程の合計時間を最小化することでクリティカルレンダリングパスを最適化することができます。
その他
レンダリングエンジンとJavaScriptエンジン
ブラウザにはレンダリングエンジンとJavaScriptエンジンという2つのエンジンが動作しています。
レンダリングエンジン
HTMLやCSSなどを解析し、実際の画面に描画するためのもの。
レンダリングエンジンによってHTMLやCSSの解釈に差があるためデザインがブラウザによって崩れるという問題があります。JavaScriptエンジン
JavaScriptを実行するためのエンジン。【主なブラウザと各種エンジン】
ブラウザ レンダリングエンジン JavaScriptエンジン Google Chrome Blink V8 Safari Webkit Nitro IE Trident Chakra Microsoft Edge Blink V8 Mozilla Firefox Gecko SpiderMonkey Opera Blink V8 Microsoft Edgeの新しいversion(Chromiumベース)が来年の1月15日にリリース予定です。
https://forest.watch.impress.co.jp/docs/news/1216492.htmlまとめ
ブラウザレンダリングの仕組みを各工程ごとにみることで、ページライフサイクルのイベントがどの工程で発生するのかをきちんと理解できるようになりました。レンダリングの仕組みの知識を元に、ブラウザの開発ツールを駆使して開発時にデバッグやパフォーマンスのボトルネックの分析、改善に役立てていきたいと思います。
参考資料
- 投稿日:2019-11-24T15:06:20+09:00
HTML <br>タグは乱用するな!
コードレビュー会で
<必要なところに<br>タグを使うのは良いけど、レイアウトを整えるために<br>タグを使うのは良くないよ
とご指摘を受けたので<br>タグを使う時の注意点をまとめてみた。参考サイト→https://tech.pepabo.com/2017/06/22/html-markup-tips-01/
br_tag.html<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <title>brタグの乱用はダメ!</title> <link rel="stylesheet" href="css/br_tag.css"> </head> <body> <!-- brタグで行間を空ける --> <div class="container01"> 長い文章で作成したコンテンツの改行。 <br> 長い文章で作成したコンテンツの改行。 <br> 長い文章で作成したコンテンツの改行。 <br> 長い文章で作成したコンテンツの改行。 <br> <br> 長い文章で作成したコンテンツの改行。 <br> </div> <!-- pタグにclass名をつけて行間はCSSで調整 --> <div class="container02"> <p class="br_tag"> 長い文章で作成したコンテンツの改行。 </p> <p class="br_tag"> 長い文章で作成したコンテンツの改行。 </p> <p class="br_tag"> 長い文章で作成したコンテンツの改行。 </p> <p class="br_tag"> 長い文章で作成したコンテンツの改行。 </p> <p class="br_tag"> 長い文章で作成したコンテンツの改行。長い文章で作成したコンテンツの改行。長い文章で作成したコンテンツの改行。長い文章で作成したコンテンツの改行。 <br> 長い文章で作成したコンテンツの改行。長い文章で作成したコンテンツの改行。長い文章で作成したコンテンツの改行。長い文章で作成したコンテンツの改行。 </p> </div> </body> </html>br_tag.cssdiv { width: 50%; margin: 20px auto; text-align: center; } .container01 { background: rgb(231, 231, 231); color: darkblue; } .container02 { background: rgb(231, 231, 231); color: rgb(204, 7, 99); } .br_tag { margin: 5px 0; }表示させるとこんな感じ。ちょっと変だけど
影響は?
「行間空けるしbrタグ使おう」と安易な考えでマークアップしたのが青い字。
「きっと行間の調整もあるだろうしメンテナンスしやすい構造にしよう」と考えてマークアップしたのが赤い字。
brタグだけでは後々のメンテナンスが行いにくくなる。行間の自由が利かない。
brタグを2つ続けるなんてもっての外!
pタグ(改行が必要ない文ならspanタグでも良いかも)は段落を作るタグであり、文章が長く改行が必要なところにだけbrタグを使うべき。
行間の調整はclass名を付けてCSSで行う。こっちのほうが使い勝手が良く、メンテナンスもしやすい。
- 投稿日:2019-11-24T12:52:00+09:00
URIとURLの違いはソーセージとウィンナーの違いと覚えろ!!
まずはソーセージから
エンジニアの皆さま、ソーセージとウィンナーの違いはご存知でしょうか?
ちなみに私の好きなソーセージはシャウエッセンですね。
一回沸騰したお湯で3分くらい茹でてから、醤油を垂らしながら焼くと旨味がパンパンに閉じ込められてめちゃめちゃうまいです。。。
2袋で400円くらいなんで、ちょっと高いですけどね。
本題にもどりますね。
ソーセージとウィンナーには明確な違いがあります。ウィンナー
羊の腸に肉(豚肉や鶏肉)を詰めたもの
ソーセージ
肉を腸に詰めた食べ物の総称
つまり、ソーセージという腸詰めの食べ物の中の種類の一つにウィンナーがあります。
ウィンナーはソーセージの一種ということですねえ。
ちなみにソーセージの種類にはウィンナーの他にも何個かあってフランクフルトとかボロニアとかありますね。
URIも一緒
URIとURLの違いも全く同じです。
WEBの技術本等を呼んでるとしばしばURIって出てきます。
「URLはよく使うしなんとなくわかるけど、、、URIはまた別物?」
別物ではないです。URL(Uniform Resource Locator)
Web上にある、あらゆるファイルがWeb上のどの位置にあるのかを表したもの
URI(Uniform Resource Identifier)
Web上にある、あらゆるファイルを認識するための識別子の総称
つまりURLはWEBにあるサイトとかホームページとかの住所みたいなものですね。
例)https://qiita.com
一方URIはURL等を含むファイル識別子のこと全般を指します。親玉みたいなものですね。
URL=住所,URI=親玉と覚えておきましょう!!!ではURIにはURL以外にどんな識別子があるのでしょう?
URNって聞いたことがありますか?URN(Uniform Resource Name)
Web上にある、ファイルの名前のこと
ここでいう名前というのはそのファイル自体の名前ではなくて、いわばシリアルナンバーみたいなものですね。
例)urn:isbn:35488317990
あまり馴染みがありませんよね。
基本的にはユーザーの目に入ることはあまりない識別子なので当然です。
「まあこんなものがあるんだなあ」程度に覚えておいてください。一つ問題
「WEBページのアドレスはURLですか?URIですか?」
ここまで呼んでくださった皆さまならわかりますね。答えは「どっちも正解」です!!
しかし、本当は
「http:(もしくはhttps:)」はURI側のパーツで、URLには含まれない」ので、厳密にはURIと呼ぶのが適切でしょう。
(賛否両論あるらしいです、、、)
まあ技術者と話す時にはURIといったほうが無難そうですね。ソーセージ食べたくなってきた。
結論、
URI=ソーセージ
URL=ウィンナー
と覚えましょう!!!!明日の朝はシャウエッセンで決まりだなあ
- 投稿日:2019-11-24T08:25:26+09:00
初心者によるプログラミング学習ログ 167日目
100日チャレンジの167日目
twitterの100日チャレンジ#タグ、#100DaysOfCode実施中です。
すでに100日超えましたが、継続。100日チャレンジは、ぱぺまぺの中ではプログラミングに限らず継続学習のために使っています。
167日目は
おはようございます
— ぱぺまぺ@webエンジニアを目指したい社畜 (@yudapinokio) November 23, 2019
167日目
webサイトコーディング課題
休みだったけど、ほかにいろいろやることあったので、コーディング自体は1時間ぐらいです。
さぼりぎみなので、今日は集中してやります#100DaysOfCode #駆け出しエンジニアと繋がりたい #早起きチャレンジ
- 投稿日:2019-11-24T00:18:09+09:00
transform: scale()で縮めた要素をposition: absoluteで絶対位置表示した時に、想定位置に表示されない問題を調べた
経緯
8pxの文字を表示したいという意志
chrome君の絶対10px以下の文字は許さないという仕様うーん、そんな時には10pxの文字を0.8倍表示!
デザインの指定では、ブロックの右下の端に表示ってあるから絶対位置指定で・・・
html<body> <div class="container"> <div class="badge"> 8px </div> </div> </body>css.container { background: skyblue; height: 100px; width: 100px; position:relative; } .badge { background: green; color: white; height: 15px; width: 15px; font-size: 10px; transform: scale(0.8); position: absolute; bottom: 0; right: 0; }え、なん?隙間なんなん?
原因究明
原因を特定するため、
- 絶対位置指定をいったん止める
- コンテナサイズを縮小前バッヂのサイズと同じにする
でどうなるか見てみます。
css(変更後).container { background: skyblue; height: 15px; width: 15px; } .badge { background: green; color: white; height: 15px; width: 15px; font-size: 10px; transform: scale(0.8); }すると・・・
こうなりました。
ここから、
transform: scale()
で縮小・拡大する際は、中心を基準にして指定倍のサイズになるということがわかりました。バッヂサイズを0.8倍して、
(元サイズ - 縮小後サイズ) / 2
の1.5px分のマージン(に似て非なるもの)が、上下左右についた状態で表示される感じ解法1 transformでの変化の基準点を指定する
transform-origin: right bottom;
と指定することで、右下基準で変化させることができる。css.container { height: 100px; width: 100px; background: skyblue; position: relative; } .badge { padding: 0; background: green; color: white; height: 15px; width: 15px; font-size: 10px; transform: scale(0.8); transform-origin: right bottom; position: absolute; bottom: 0; right: 0; }解法2 絶対位置指定をマイナスで指定する
transform-origin
がどーしても使えない状況があった場合(なさそう)、(元サイズ - 縮小後サイズ) / 2
分だけマイナス絶対位置を指定することで無理やり右端に合わせることができる
が、
-1.5pxなど、少数が絡むとうまくいかないので注意!うまくいかないパターン
css.container { height: 100px; width: 100px; background: skyblue; position: relative; } .badge { padding: 0; background: green; color: white; height: 15px; width: 15px; font-size: 10px; transform: scale(0.8); position: absolute; bottom: -1.5px; right: -1.5px; }うまくいくパターン
css.container { height: 100px; width: 100px; background: skyblue; position: relative; } .badge { padding: 0; background: green; color: white; height: 15px; width: 15px; font-size: 10px; transform: scale(0.6); position: absolute; bottom: -3px; right: -3px; }なお、絶対位置は0指定でマイナスマージンをとってもよい(こちらも小数点以下指定でずれる)
css.badge { padding: 0; background: green; color: white; height: 15px; width: 15px; font-size: 10px; transform: scale(0.6); position: absolute; bottom: 0; right: 0; margin-bottom: -3px; margin-right: -3px; }結の論
transformを使うときは、transform-originの存在を頭に置いておこう!