Chromeのloading属性は、指定しなくてもデフォルトで"lazy"の挙動となりうる　～loading属性の落とし穴から学ぶ、機能拡張と初期値・デフォルト挙動の話～

#【事前知識】loading属性について
Chromeの`img`・`iframe`要素には、`loading`属性というものがある。
こいつをHTMLで`loading="lazy"`のように指定すると、遅延読み込みする（画像等がスクロール等で画面内に入ってきた時に初めて読み込み始める）。
こうすることで、時間がかかる無駄な読み込みが抑えられ、ページ表示速度が速くなったり、通信量を減らせたりする。

値には次の3種類があり、`"lazy"`が遅延読み込みオン、`"eager"`は遅延読み込みオフ（遅延せず愚直にすぐ読み込み）、`"auto"`はlazyかeagerかをChromeがネットワーク速度などを考えて自動で決める。

これはChrome 75の時に登場した新機能で、Chrome独自の試験的なものらしい。これまでは同じことをするのにJavaScriptを使わねばならなかったのが手軽に書けるようになったとあって、人気のようだ。

#【事前知識2】loading属性とonloadの落とし穴
普段はプラスの側面しか見えず無害に見えるloading属性（遅延読み込み）だが、こいつには盛大な落とし穴がある。
それは、**ページ全体に対する`onload`イベントがあてにならなくなる**点だ。

`onload`イベントには、要素が完全に読み込まれたら実行する処理を書くことができる。`img`要素に指定すればその画像が、`body`要素や`window`等ページ全体に指定すればページ内の本文・画像・iframe・動画等全ての要素が読み込み完了した時に処理が走る。
例えば、複数ある画像の縦横比が不定のため`img`要素の高さを`height:auto`とせざるを得ず、高さがあらかじめ分からないが、どうしても**画像を含めたページ全体の高さをJavaScriptで取得する**必要がある時。
こんな時、ページ全体への`onload`イベントが便利だ。読み込み完了時には全ての画像が出そろっているため、高さが判明しているからだ。

しかし、`loading="lazy"`はこの便利なカラクリを破壊する。

`loading="lazy"`によって遅延読み込みが指定された画像は、ページ下部にある場合、スクロールするなどして画面内に顔を出さない限り読み込まれない。しかしこの時、**ページ上部の画像だけ読み込んだところで先にページ全体の`onload`処理が走ってしまう**。**まだ下部の画像読み込みが`loading="lazy"`によって保留されてるにも拘らず、あたかもページ内の画像全てが読み込み終わったかのように`onload`が発動してしまう**のだ。ようは、`onload`のフライングである。

`loading`は読み込みを遅延させるのだから、これが`onload`の挙動に影響することは考えれば当然なのだが、この挙動はあまりにもトラップがすぎるというか、直感に反する。酷い落とし穴だ。

だが、こんな仕様になったのもしょうがないのかもしれない。
というのも、もし`onload`が従来通り正真正銘の完全読み込み後にしか発動しない挙動を貫いていたら、ページ内を隅から隅までスクロールしきって、`loading="lazy"`な要素を全て読み込みきらなければ`onload`が走ってくれないことになる。それはそれで困る。だから、このようにフライングさせるようにしたのだろう。


よって、**ページ内の全画像等の読み込み完了時に走らせたい`onload`処理がある場合は、`loading="lazy"`を使ってはいけない**。

---

ワシ「そっか！何でもかんでも`loading="lazy"`を付ければいいって訳じゃないんやな！」
ワシ「じゃあ、読み込み完了時に走らせたい処理があるこのページでは、**`loading="lazy"`を付けないで、従来通りimgを書けばいいんやな！**」




しかし・・・そこに更なる落とし穴が潜んでいたのである・・・

#【本題】loading属性の初期値は"auto"である

これまで私は、`loading`という属性を**明示的に書かない限り**、今回の新機能は発動しないと思い込んでいた。

画像含めページ全体が読み込み終わってから`onload`するページは、これまでずっとうまく動いてくれていたし、実際、今も目の前のPCのテストで、通常の読み込み・F12のレスポンシブモードによる読み込み共に、`onload`はうまく動いている。

これからも、`loading="lazy"`さえ書かなければ変わらない、そう信じていた。なにせ、試験的な拡張機能なのだから。

しかし、ふと思い立って手元のAndroid実機のChromeでそのページを開いてみると・・・

**ファッ！？！？！？！？！？`onload`で取得する数値がズレている！？！？**なんかデカい画像の高さの分だけズレてる気がするな。しかも、他のブラウザではズレないな。これはもしや、`loading="lazy"`の仕業か・・・？？　でも、**`loading="lazy"`など一言も書いていないから遅延読み込みはさせていないはずだし、実際PCではうまく動くぞ！？そもそも`loading`なんていう属性には微塵も触れていないぞ！？なぜ実機だけ遅延読み込みになるんだ！？これはどういうことだ！！！**

つまりそのページでは、
**PCでは**F12のレスポンシブモードだろうが**通常の読み込み**（`loading="eager"`相当）、**Android実機では遅延読み込み**（`loading="lazy"`相当）が発生していたのである。
`loading="lazy"`を書いてないにも拘らず、Android実機から見るとあたかも`loading="lazy"`を指定したかのような挙動を見せたのだ。

---

ここで、`loading`について解説する数々のページをググり、真相を確かめに行った。こいつはChrome独自拡張のため、MDNには見当たらない。個々人のブログに頼ることとなった。また、自分自身でもテストコードをいくつか書き、挙動を検証していった。

そこで判明したのが、**`loading`属性の初期値は`"auto"`である**という事実、
そして更に、**`loading`属性は、書かなくても暗黙にその初期値が指定されたものとみなされる、つまり`loading="auto"`が書かれたものとみなされる**という事実だった。

ここで、私は
「ちょっとちょっとオイオイオイChromeさん！？！？いくら何でもそれは勝手すぎでは？？？？」
と思ったのだった。

---

まず、[【事前知識】loading属性について](#事前知識loading属性について)でも触れた、`loading="auto"`の挙動を復習する。

> `auto`は`lazy`か`eager`かをChromeがネットワーク速度などを考えて自動で決める。

「lazyかeagerかをChromeが自動で決める。」つまり、**loading="auto"の場合は、ネットワーク環境次第でloading="lazy"の挙動になる可能性がある**、ということだ。

そして、先程言った通り、
Chromeでは（`loading`対応要素である`img`や`iframe`に）`loading="auto"`を**書かなくても、書いたのと同じ**と見なされる。

つまり、まとめると・・・

Chromeでは、**`loading`属性を全く書かずに従来の方法で`img`や`iframe`を書いたとしても、暗黙にデフォルトで`loading="auto"`が指定された扱いになり、ネットワーク環境次第で意図せず`loading="lazy"`の挙動を起こしてしまい、ページ全体の`onload`があてにならなくなってしまう**のである・・・！！！！！！！！

驚愕の事実だ。非常にまずい事態。過去に動かしてきたコードが今でも動くかどうか、**再検証**を強いられたのだ。まさか、Chromeでこんなハメに陥るとは。IEかよ…

---

これで、問題のページの挙動に説明がつく。
テストPCでは通常の読み込み、Android実機では遅延読み込みが発生していたのは、
テストPCの繋がっていた有線のネットワークは速度が速かったためにChromeがeager読み込みできると判断した一方、
Android実機の繋げていた携帯回線はネットワーク速度が遅かったために、Chromeが勝手にlazy読み込みをし、その結果`onload`バグを起こしていた、ということだ。

そして、私はそれまで、**`loading`属性の初期値は`"eager"`だと思い込んでいた**のだ。
Chromeの**独自拡張である`loading`属性を書かない時の挙動は、拡張前及び他ブラウザと同じ挙動、つまり`loading="eager"`の挙動であってしかるべき**、と思っていたのだ。
でも、実際のChromeはそうではなかったのだ。`auto`だったのだ・・・

`img`要素に`loading`って書かなくても、`loading="auto"`と解釈されてしまう。過去の既存のHTML文書でもそうだ。
これって、重大な**互換性**破壊では・・・？（←後述する。）





#【解決】対処法

件の`onload`バグの発生メカニズムは上記の通りなので、対処法は当然、以下のようになる：

Chromeでは、**ページ全体への`onload`イベントがあり、かつその`onload`がページ内全ての`img`や`iframe`の読み込み完了時を意図したものである場合、ページ内全ての`img`や`iframe`への`loading="eager"`（＝lazyな読み込みを無効化）の指定が必須となる。**さもなくば、Chromeの`onload`はあてにならない。

だが、今更全てに`loading="eager"`を付けてまわるなんてとんでもない労力だ。そんな時は**JavaScriptで動的に`loading="eager"`を付けてもよい**。つまり、`document.getElementsByTagName("img")`とかで要素取ってきてそれぞれの`element.loading="eager"`とする。手元のChrome 77でテストしたが、それでもうまくいった。

IE対応やiOS対応というのはよくあるが、
シェアが多く、馬鹿げたバグの少ない信頼のChromeで対応が必須になるというのは、なんとも気持ち悪い。


#【結論】初期値やデフォルトの挙動を把握しよう

教訓。

**新しい機能や項目が登場したら、
何もしなかった場合の初期値・デフォルトの挙動を把握しよう。**

その機能に触れなった場合、その機能が無効と見なされるのか、有効と見なされるのか。
**その新機能は、初めから暗黙でオンなのか、それとも明示的に設定しないとオンにならないオプション的存在なのか**。これがどちらなのかをはっきりさせとく必要があるのだ。暗黙というのは恐ろしい。

そして、今度は新機能提供側の話になるが、
**新機能を追加する場合は、できれば、
新機能の初期値の挙動を従来の挙動に合わせた状態で（＝デフォルトの挙動が追加前と変わらないようにして）
追加されるのが望ましい**。

これはHTML属性に限った話ではない。CSSプロパティにしろ、アプリの設定項目にしろ、もうこの世の全てに対して言える。

デフォルト値というのは、目に見えない。目に見えない値をもって加えられた変更（＝暗黙の変更）は、検知しにくいため、問題の把握を遅らせる。非常に良くない。ユーザにとっては使いづらく、コーディングする人にとっても、今回の`onload`バグのようにバグの原因にもなる。誰にも良いことがない。
ユーザ（今回の件で言えば、コーディング者もChromeとHTMLのユーザである）は、アプデ後も見えない部分は変わっていないと思い込んで使うため、暗黙なデフォルト挙動を変えられてしまったら、今回の`loading`属性の落とし穴のような面倒事が起こりやすくなるのだ。



---

CSSでの例も書こう。

今回こそCSSの話題ではなかったが、ことにCSSというのは、暗黙デフォルト値のオンパレードだ。何も指定しない場合`line-height`はいくつとして扱われるのか。`img`の`display`だって、デフォルトでは`inline`だ。だから、`img`をブロック的に表示したい殆どの人にとって、必然的に`img{display:block}`の指定が必要になる。さもなくば、「画像の下に余白が～」「`vertical-align`をいじって！」とかいう学習上のロス（遠回り）が発生する。初心者泣かせにも程がある設計だ。[CSS初期値一覧なチートシート](https://qiita.com/jyane/items/aed390415cb0d804a11b)なんていう記事もあるくらいだ。

ただ、CSSの学習過程で、これらのデフォルト値を一通り（なんとなくでいいから）覚えてしまえば、楽になる。というか、CSSというのは正直、初期値を変更していくいわば設定変更言語（VSCodeの`settings.json`や、`.bashrc`のような存在）で、むしろ、「初期値を制する者はCSSを制する」と言っても過言ではないくらいだ。

その後大事になってくるのは、**デフォルトの挙動や初期値は、一度制定されたら恒久的に変更されないのが望ましい**、ということだ。

つまり、ある日突然、`img`の`display`の初期値が`inline`から`block`に変更されてはいけないのである。**初期値は目に見えないため、解説書（ドキュメント等）が必須**になる。そんな目に見えない値を勝手に変更するのは、過渡期に新旧解説書が混在して学習者を混乱させる上に、既習得者も覚え直しが必要となり、既存データという財産の持つ意味も変わってしまう。損失しかない。

ところで、思えば`overscroll-behavior`が登場した時。あれはそれほど混乱にはならなかった。何故、`overscroll-behavior`には今回の`loading`のような落とし穴が無かったのか。

それは、**`overscroll-behavior`の初期値`"auto"`の挙動が、`overscroll-behavior`の無かった時代と同じ挙動**だったからだ。
つまり、**`overscroll-behavior`を明記しない＝その新機能が発動しない＝これまでと同じ**というありがたい仕様だったからなのだ。

そのおかげで、われわれは`overscroll-behavior`を**必要な時だけ呼び出せる**便利な機能として平和に迎え入れることができたのである。素直な拡張、**後方互換性のある拡張**である。機能拡張の主(既存)・従(新規)の関係が変わらず、綺麗なのだ。

それに対し、今回の`loading`属性の導入がこのような面倒事になった理由はもうお分かりだろう。

それは、**`loading`属性の初期値`"auto"`の挙動が、`loading`属性の無かった時代と異なる**からだ。
つまり、**`loading`の無い時代に書かれた昔のHTML文書の`img`タグが、これからは`loading="auto"`が指定されたものとして解釈されてしまう（ネットワーク環境によっては`loading="lazy"`な挙動をとりうる）**。これは、**後方互換性を崩しかねない拡張**である。同じデータが異なる意味を持ち始めるのだ。

今回のChromeの設計に関しては、かなりしょうがない側面もあるが、
正直、上記の理由から、Chrome側の機能拡張の仕方に問題があった、と言わざるを得ない。

---

言語だけでなく、アプリでの例も書こう。

例えば、iOSをアプデしたら、**「英単語のタイプミスを自動修正する」とかいう要らない機能が追加され、その機能が暗黙にオンにされた状態で**アプデされている。つまり、OSのデフォルト挙動が暗黙に変わった状態でアプデされる。

ユーザは、その機能を不便と思ってオフにしたくても、暗黙である以上、**どの設定項目が原因なのか**を突き止めるのが難しい。自分自身でオンにしたわけではないからだ。誰かが設定項目を研究し、「iOSの迷惑機能のオフの仕方！ ○○という設定項目の××をオフにすればいいよ」というHowTo記事でも書かない限り、ユーザはその迷惑機能をオフにする方法を知ることができない。好みの設定にたどり着けない。

Windowsのコントロールパネルなんかも同じだ。あれの設計の悪さと言ったらゲロものだが、あの**コントロールパネル中の大量の項目のどれかがアプデのたびに暗黙に書き替わってると思うと、吐き気**がする。新機能追加ではないが、これまで無いと思ってた余計な機能に初めて遭遇した時も、そのユーザにとっては新機能の発見という意味で追加だ。なんか**ウィンドウをドラッグして端に持っていったら勝手に最大化するやんけ、ウッザ**ってなったなら、「ウィンドウ　勝手に最大化」とかでググって、誰かのHowTo記事でも見つけない限り、「`コントロール パネル`＞`コンピュータの簡単操作`＞`コンピュータの簡単操作センター`＞`マウスを使いやすくします`＞`ウィンドウが画面の端に移動されたとき自動的に整列されないようにします`にチェック」とかいうクッソ分かりづらい解決策にはたどり着けない。~~何が「簡単」操作だ、よう言うわ~~
（Microsoftはその設計の悪さを認めたのか、それを「設定」という別アプリに移して再編する最中だが、そうすると今度は過去に蓄積されたHowTo記事が無駄になり、また1からHowToの作り直し。そもそも「コンパネ」から「設定」へ移行させること自体、デフォルトなものの書き替えだ。どの項目がどう対応し、どう移動し、どれがまだコンパネに残っているのかの情報がない点も、暗黙だ。初めから設計の良い設定画面を作っていればよかったものだ）

それに対し、iOS13の夜間モードは、良い例だ。**夜間モードは、機能追加の周知のみが行われ、機能自体はデフォルトではオフの状態で追加された**。そのお陰で、これまで通り使いたい人はこれまで通りの感覚で使い続けられるし、オンにしたいユーザは自分で選んでオンにできる。これが一番混乱が少なく、理想的なのだ。機能拡張の主(既存)・従(新規)の関係が変わらず、綺麗なのだ。

---

ただ、それでも新機能をデフォルトでオンにしたい、という人はいるだろう。

その理由の一つに、「**新機能をまず使ってほしい**」というものがある。
周知が失敗すれば、それは追加しなかったのと全く同じになり、せっかく作った新機能が勿体ないからだ。
まず使ってもらうことで、その新機能の存在だけでも知ってもらおう、という魂胆だ。

しかし、いい機能・求められる機能というのは、まず周知の時点で大いに期待され、周知が失敗することは少ない。初めは使われなかったとしても、本当にいい機能というのは誰かしらが布教ツイートしたりしていつの間にか支持されるものだ。夜間モードもその例だろう。

また、使われない新機能というのは、設計者は「まず試してもらうチャンスが少ないせいだ」と、**使ってもらうチャンスの少なさのせい**にしたがるが、実際には往々にして大多数のユーザにとって本当に必要ないから無視されている、ということがとても多いのだ。その**新機能を「良くなった！」「便利になった！」「こんなの実装できたんだ！すごいだろ」と思ってるのは導入した本人やチームだけ**で、**大多数のユーザはそんな機能なんてどうでもいいと思ってる**場合が殆どだ。

実は、全く同じことは芸術でも起こり、例えば「こんな絵を描いたんだ！見てほしい！」「私の動画が再生されないのはまず見てもらうチャンスが少ないせいだ」と思ってるのは制作者だけで、実際には見に来た鑑賞者がその作品であまりいい体験を得られなかったからシェアされなかったのが事実、ということが多いのだ（制作者は勿論、自分の作品の完成度のせいにはしたくないため、チャンスの少なさのせいにする傾向がある）。本当に完成度の高い芸術作品というのは、少ないチャンスやきっかけで一気にファンが付くものだ。

つまり、作品を見てもらう／実装した機能を使ってもらえるチャンスの少なさではなく、結局は作ったものそのものの出来栄えで決まるところが大きいのだ。**使ってもらうチャンスを増やそうとやたら新機能を無理やり使わせたがるのは、見てもらうチャンスを増やそうとしつこく自作品をリツイート(再掲)したり、「相互フォローしますから」とかいう臭いタグを使ってばかりの日々に明け暮れて、肝心の作品制作そのものに力を注がないでいるのと同じ**なのだ。いい作品は報われるべくして広まるし、いい機能は報われるべくして受け入れられ、定着する。これを考えると、やはり**新機能はデフォルトでオフにすべき**、という結論になるのだ。

---

※2019/10/17追記：
新機能デフォルトオンについて完全否定しているわけではなく、"暗黙の"新機能デフォルトオンのみを否定しているため、誤解を生まないための補足説明を[コメント欄](#comments)にて追記しました。



#【余談】CSSのcaret-colorへの願い
「後方互換性のある綺麗な機能拡張」という話にちなんで、
個人的にCSS、および`caret-color`へ抱いてる妄想を書く。

---

CSSでも、過去に多くの機能拡張（追加）が行われた。
例えば、昔`text-decoration`はそれ自体しか存在しなかった。`text-decoration: none`でリンクから下線を消したり、`text-decoration: line-through`で打消し線を引いたりするのに使われた。

しかし、今はこれが見事に**後方互換性を維持したまま意味合いを変えて拡張**されている。
今や`text-decoration`は、下線なのか上線なのかの線の引き方を指定する`text-decoration-line`・点線なのか実線なのかの線の種類を指定する`text-decoration-style`・線の色を指定する`text-decoration-color`の3つのプロパティを**一括指定**する[ショートハンドプロパティ](https://developer.mozilla.org/ja/docs/Web/CSS/Shorthand_properties)（一括指定プロパティ）として定義され直された。一括指定プロパティには他に、`background-color`等に対する`background`や、`margin-left`等に対する`margin`がある。一括指定プロパティの下に子分のように連なる子プロパティたちは、「`-line`」「`-style`」「`-color`」「`-left`」のように、ハイフンで命名されている（こういうのを[ケバブケース](https://qiita.com/deerboy/items/f035b9044edf9a51aff7)というらしい）。

このような派手な拡張をしたにも拘らず混乱が起きていないのは、一括指定の書き方の仕様上、値に1つしか書かなくてもいい（触れなかった指定は暗黙に初期値となる）ため、例えば`text-decoration: line-through`はこれまで通り機能するというわけだ。
従来の`text-decoration: line-through`は、「`text-decoration`が`line-through`である」以上の意味を持たなかったが、
今の`text-decoration: line-through`は、「`text-decoration-line`が`line-through`で、`text-decoration-style`が初期値`solid`で、`text-decoration-color`が初期値`currentcolor`である」という意味に変わるものの、**初期値がうまいこと仕事して結果的に従来と同じ挙動**になり、互換性が見事に維持されている。

※ `background: #000`と書いたとしても、（その他`background-position`・`background-repeat`・`background-size`等多くの子プロパティを初期値に任せることで、）具体的に`background-color: #000`と書いたのと同じように背景色を黒くできるが、これも同じことだ。

---

ここで、`caret-color`の話になる。

CSSには現在、[caret-color](https://developer.mozilla.org/ja/docs/Web/CSS/caret-color)というプロパティがあり、キャレット（入力欄の点滅するやつ）の色を変えられる。初期値は`auto`で、普通は黒だ（厳密には、入力欄のテキストと同じ色になる）。

しかしこれ、すごく機能不足な気がする。設定できるの色だけなの？
初めから名前にハイフン入ってるが、`caret`というプロパティは2020年現在、CSSには存在しない。

というか、**キャレットの種類には縦棒・下線・ブロックとかいくつか種類ある**じゃん。
個人的には、その種類が指定できてほしいんですけど（というか、ブロックなキャレットの方がテキストエディタっぽくて好き）。
それに、現在の縦棒キャレットは、正直細くて見づらい。目が悪い人にとっては、ブロックキャレットの方が見やすいのでは？

ブロックキャレットをJavaScriptで疑似的に再現したコードは数あれど、
全角半角交じりの日本語フォントに対応できているものは何一つ無かった。
いずれも、日本語文字を入れたり消したりするごとにどんどんキャレット位置がずれていくバグや、IMEへの対応が悪いことで変換確定文字が倍増するバグなどがあり、実用に耐えない（例：[Stack Overflow](https://stackoverflow.com/questions/3758023/how-to-use-this-square-cursor-in-a-html-input-field)、[Secure Shell Extension](https://chrome.google.com/webstore/detail/secure-shell-extension/iodihamcpbpeioajjeobimgagajmlibd)）。
JavaScriptで無理があるなら、ブラウザ側がCSSでブロックキャレットを用意してくれればいいのだ。

これって…　超可能性秘めてない？

そう、ここまで読んだ君なら分かるだろう。
こいつは`text-decoration`の後に続くべきだ、と。
こいつも後方互換性を維持した拡張がたやすくできるはずだろうに、と。

##これが新しいCSSプロパティ、caretとcaret-styleだ！

※架空の妄想のため実在しない。ていうか何で実在しないのか理解できない。実在しろ（）

```css
caret: block red;      /* caret-styleとcaret-colorの一括指定。
                          他の一括指定プロパティ同様、片方の値を省くこともできる。 */

  caret-style: block;  /* 初期値はauto。多くのブラウザは、vertical-bar（縦棒）の値を使うだろう。
                          値は他に、block（ブロック）、underscore（下線）、
                          outline（ブロックの枠線だけバージョン）等。 */

  caret-color: red;    /* 初期値はauto。既存のcaret-colorと同じく、キャレットの色指定。
                          但し、caret-style:block; 時、ブロック型キャレットの中に文字が入った場合、
                          キャレット内の文字色はどうするかという問題があるが、
                          それは素直に入力欄の背景色を透過させるのがいいだろう。 */
```

※他に `caret-width:px値;` `caret-height:px値;` とかも有りうるが、
　縦棒キャレットの幅を太くしてブロックっぽくした場合のブロックとの区別問題や、
　そもそも半角幅のブロックキャレットは全角文字に重なった場合その全角幅に合わせて正方形のキャレットになるのが普通だが
　絶対値指定だとその融通が利かず望ましくない等、問題点が多いため却下。
　（Windowsのキャレット幅設定がこれなんだよなぁ…）

※`caret-blink: none;`でキャレットの点滅を止める、`s`や`ms`値で点滅速度、とかも考えたが、
　そもそも点滅の仕方まで制御するとかいうそんな小細工めいた需要は少ないと思われる。
　それでも、どうしてもキャレットの点滅を制御したい人のために、
　キャレットの点滅実装をCSSアニメーションと紐づけ、
　`caret-animation: animationの値;` とかを用意してあげてもいいかもしれない。
　ただ、そんなことすると点滅以外のアニメーションもできるようになってカオスなので、
　値を制限するか、やはり無しか、保留。議論の余地あり。

#まとめ

- Chromeでは、**`loading`属性を全く書かずに従来通り`img`や`iframe`を書いたとしても、暗黙にデフォルトで`loading="auto"`が指定されたものとされ**、ネットワーク環境次第で**意図せず`loading="lazy"`の挙動を起こしてしまい、ページ全体の`onload`があてにならなくなってしまう**という落とし穴がある。それを防ぐには、**明示的に`loading="eager"`を指定**せねばならない。

- 今回の`loading`の落とし穴を分析すると、教訓が判明した： 新しい機能や項目が登場した時は、何もしなかった場合の**初期値・デフォルトの挙動を徹底的に把握しよう**。初期値の設計が悪い場合、落とし穴があるかもしれないからだ。

- また、新機能提供側にも教訓が判明した： **暗黙の仕様(挙動)変更**は悪。異論は認めない。機能拡張や仕様変更をする時は、**初期値を従来の挙動に合わせることで、暗黙の変更が発生しないように**配慮すべし。実際、初期値のオンパレードなCSSは、これが上手く考慮された設計になっている。