20191124のHTMLに関する記事は6件です。

初心者です。

書籍にあるcss,javascriptのサンプルコードを書いてみたのですが反映されません・・・
どうすればよいのでしょうか??

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ブラウザレンダリングの仕組み

概要

webサービスを公開するにあったて必ず使われることになるのがブラウザです。ブラウザがユーザーにwebページを表示する仕組みを理解することで、フロントエンド開発に役立てたり、ページ表示までのレスポンスの改善などに役立てていきたいと思い、今回ブラウザのレンダリングの仕組みの基本事項についてまとめました。

レンダリングの流れ

ユーザーがwebブラウザにURLを入力すると、ブラウザはURLを元に指定のサーバーにTCP/IPプロトコルに基づいてリクエストを送ります。その後サーバはクライアントに対してレスポンスします。以降のレスポンスとして受け取るHTML,CSS,Javascriptをどう処理して画面に表示するのかをレンダリングと定義して、その処理の流れについてみていきます。(この工程はcritical rendering pathと呼ばれています)
progressive-rendering.png

https://developers.google.com/web/fundamentals/performance/critical-rendering-path

レンダリングの流れ.png

ブラウザがWebページをレンダリングする仕組みは上のような一連の流れになっています。以下でその一つ一つの工程の内容をみていきます。

オブジェクトモデルの構築

ブラウザはページを描画する前に、DOMとCSSOMツリーを構築する必要があります。
このDOMとCSSOMツリーを構築する工程は「オブジェクト構築モデル」といいます。

バイト→文字列→トークン→ノード→オブジェクトモデル(DOM/CSSOM)

という流れでオブジェクトモデルは構築されます。

constructingObjectModel.png
参考:https://developers.google.com/web/fundamentals/performance/critical-rendering-path/constructing-the-object-model

DOMツリーの構築

dom-tree.png

変換

ブラウザはディスクやネットワークからHTMLのバイトを読み取り、utf8などの文字コードに応じて<html>や<head>のような文字列に変換します

トークン化

取得した文字列をトークンに変換します。W3C HTML5 standardによって規則が定められています。

スクリーンショット 2019-11-27 23.17.34.png

字句解析

トークンは<html>や<head>といったオブジェクトに変換されます。
スクリーンショット 2019-11-27 23.19.39.png

DOMの構築

字句解析で作られたオブジェクトはオリジナルのマークアップの定義に基づいた親子関係をもつ木構造に整形されます。
<html>オブジェクトは<body>オブジェクトの親で、<body>は<p>の親でといったようなHTMLのマークアップでみる構成になります。

この最後のプロセスの最終的な成果物が描画するページのDOMとなります。

CSSOMツリーの構築

cssom-tree.png

ブラウザでDOMを構築している際にドキュメントのheadタグで外部のcssスタイルシートを参照しているlinkタグに遭遇すると、ブラウザはページのレンダリングにこのリソースが必要であると解釈してこのリソースに対するリクエストを即座にディスパッチし、CSSを受け取ります。

ブラウザがCSSを解釈して処理できるようにするために、受けっとたCSSをHTMLのDOMツリー構築の時と同じように処理していきます。

レンダリングツリーの構築

DOMツリーとCSSOMツリーを組み合わせることでレンダーツリーを作ります。レンダーツリーは個々の要素のレイアウトの計算し、またピクセルを画面に描画するプロセスである「ペイント」の工程が必要とする値を生成します。

レンダーツリーの生成

DOMツリーとCSSOMツリーを合成してレンダーツリーを生成します。ページの描画に使われる全てのDOMと個々のオブジェクトに使われるCSSをそれぞれ組み合わせます。

render-tree-construction.png

レンダーツリーを構築するために、ブラウザは大まかに以下の工程に従います

  1. DOMツリーのルートからはじめて、個々のノードをトラバースしていきます

    • scrpitタグなど画面の描画に直接関係ないいくつかのノードは除かれます
    • いくつかのノードはCSSによりdisplay noneなどど非表示に指定されたものも除かれます(上の図の例でいうと<span>にあたります
  2. それぞれのノードに対応したCSSOMをみつけて適用します

  3. 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%の位置となります。

layout-viewport.png

レイアウトプロセスで出力されるものを「ボックスモデル」といいます。ボックスモデルはviewport内での個々の要素の正確な位置とサイズを算出し、相対的な値を画面上でのピクセルの絶対値に変換します。

ペイント

最後に、レイアウトプロセスで得ることができた個々の要素のサイズと位置情報を最終的な正確なピクセル値へと変えるペイント(又はラスタライゼイション)の行程が行われます

layout-timeline.png
【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

まとめ

ブラウザレンダリングの仕組みを各工程ごとにみることで、ページライフサイクルのイベントがどの工程で発生するのかをきちんと理解できるようになりました。レンダリングの仕組みの知識を元に、ブラウザの開発ツールを駆使して開発時にデバッグやパフォーマンスのボトルネックの分析、改善に役立てていきたいと思います。

参考資料

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

HTML <br>タグは乱用するな!

コードレビュー会で
:busts_in_silhouette:<必要なところに<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.css
div {
    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;
}

20191122_Qiita01.png

表示させるとこんな感じ。ちょっと変だけど:sweat_smile:

影響は?

「行間空けるしbrタグ使おう」と安易な考えでマークアップしたのが青い字。
「きっと行間の調整もあるだろうしメンテナンスしやすい構造にしよう」と考えてマークアップしたのが赤い字。
brタグだけでは後々のメンテナンスが行いにくくなる。行間の自由が利かない
brタグを2つ続けるなんてもっての外!:angry:
pタグ(改行が必要ない文ならspanタグでも良いかも)は段落を作るタグであり、文章が長く改行が必要なところにだけbrタグを使うべき
行間の調整はclass名を付けてCSSで行う。こっちのほうが使い勝手が良く、メンテナンスもしやすい。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

URIとURLの違いはソーセージとウィンナーの違いと覚えろ!!

まずはソーセージから

エンジニアの皆さま、ソーセージとウィンナーの違いはご存知でしょうか?
ちなみに私の好きなソーセージはシャウエッセンですね。
一回沸騰したお湯で3分くらい茹でてから、醤油を垂らしながら焼くと旨味がパンパンに閉じ込められてめちゃめちゃうまいです。。。
2袋で400円くらいなんで、ちょっと高いですけどね。
image.png

本題にもどりますね。
ソーセージとウィンナーには明確な違いがあります。

ウィンナー

羊の腸に肉(豚肉や鶏肉)を詰めたもの

ソーセージ

肉を腸に詰めた食べ物の総称

つまり、ソーセージという腸詰めの食べ物の中の種類の一つにウィンナーがあります。
ウィンナーはソーセージの一種ということですねえ。
ちなみにソーセージの種類にはウィンナーの他にも何個かあってフランクフルトとかボロニアとかありますね。
スクリーンショット 2019-11-23 21.47.10.png

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
あまり馴染みがありませんよね。
基本的にはユーザーの目に入ることはあまりない識別子なので当然です。
「まあこんなものがあるんだなあ」程度に覚えておいてください。

スクリーンショット 2019-11-23 22.38.22.png

一つ問題

「WEBページのアドレスはURLですか?URIですか?」
ここまで呼んでくださった皆さまならわかりますね。

答えは「どっちも正解」です!!
しかし、本当は
「http:(もしくはhttps:)」はURI側のパーツで、URLには含まれない」ので、厳密にはURIと呼ぶのが適切でしょう。
(賛否両論あるらしいです、、、)
まあ技術者と話す時にはURIといったほうが無難そうですね。

ソーセージ食べたくなってきた。

結論、
URI=ソーセージ
URL=ウィンナー
と覚えましょう!!!!

明日の朝はシャウエッセンで決まりだなあ:hotdog::hotdog:

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

初心者によるプログラミング学習ログ 167日目

100日チャレンジの167日目

twitterの100日チャレンジ#タグ、#100DaysOfCode実施中です。
すでに100日超えましたが、継続。

100日チャレンジは、ぱぺまぺの中ではプログラミングに限らず継続学習のために使っています。

167日目は

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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

スクリーンショット 2019-11-23 22.04.11.png

え、なん?隙間なんなん?

原因究明

原因を特定するため、

  • 絶対位置指定をいったん止める
  • コンテナサイズを縮小前バッヂのサイズと同じにする

でどうなるか見てみます。

css(変更後)
.container {
    background: skyblue;
    height: 15px;
    width: 15px;
}

.badge {
    background: green;
    color: white;
    height: 15px;
    width: 15px;
    font-size: 10px;
    transform: scale(0.8);
}

すると・・・

スクリーンショット 2019-11-23 22.29.12.png

こうなりました。

ここから、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;
}

スクリーンショット 2019-11-23 23.48.54.png
想定どおりに表示された!

解法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;
}

スクリーンショット 2019-11-23 23.56.57.png
微妙にはみ出る・・・

うまくいくパターン

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

スクリーンショット 2019-11-23 23.56.21.png
うまくいきました!

なお、絶対位置は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の存在を頭に置いておこう!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む