すたすた式
Blogger QooQ
追記(2022年2月27日):PageSpeed Insightsの「画像要素でwidthとheightが明示的に指定されていない」の指摘は回避することは出来ましたが、実際のパフォーマンス向上は確認出来ません。Twitterで教えてもらいましたあくまで実験的なものとご理解ください。
パフォーマンスの向上を含めた動作は、 些細な日常|結城永人さんが書かれた以下の記事を参考になさってください。
「画像を挿入」で追加した画像が対象です。
下記のような構造になっている画像に適用されます。(class="separator"以下のイメージタグ<img>に適用されます)
class="separator"
<img>
<div class="separator" style="clear: both;"> <a href="https:..." style="..."> <img alt="" border="0" width="" data-original-height="" data-original-width="" src="https:..."/> </a></div>
PageSpeed Insightsで指摘されるこれ。
画像要素でwidthとheightが明示的に指定されていない
自分の環境では、「HTMLビュー」で画像を挿入すると、
と、いずれかの属性が「ない」状態で挿入されます。(または両方ない状態で)
モードを「作成ビュー」にして画像を挿入すればwidthとheight両方付きますが、過去記事の量なども考慮して、足りない属性と属性値を追加するJavaScriptを書きました。
設置場所は<post-body>の直後あたりや、または</body>の上あたりでしょうか?(試行錯誤中です)
<post-body>
</body>
HTMLを編集します。必ずバックアップを取ってから作業してください。
<script> // [画像を挿入]で追加した画像にwidthとheightを明示的に指定する (+ Lazyload + decoding async) //<![CDATA[ (() => { const basePoint = document.querySelector(".post-body"); const postImages = basePoint.querySelectorAll(".separator img"); if (postImages.length > 0) { postImages.forEach((imgElm) => { /* Lazyload */ //imgElm.setAttribute("loading", "lazy"); /* decoding async */ //imgElm.setAttribute("decoding", "async"); const originalHeight = imgElm.getAttribute("data-original-height"); const originalWidth = imgElm.getAttribute("data-original-width"); const ratio = originalWidth / originalHeight; const attrHeight = imgElm.hasAttribute("height"); const attrWidth = imgElm.hasAttribute("width"); // heightとwidthがある場合 if (attrHeight == true && attrWidth == true) { return; } else { } // heightとwidthがない場合 if (attrHeight == false && attrWidth == false) { imgElm.setAttribute("height", originalHeight); imgElm.setAttribute("width", originalWidth); return; } else { } // heightがない場合 if (attrHeight == false) { const width = imgElm.getAttribute("width"); const calcHeight = Math.round(width / ratio); imgElm.setAttribute("height", calcHeight); return; } else { } // widthがない場合 if (attrWidth == false) { const height = imgElm.getAttribute("height"); if (originalHeight > height) { const calcWidth = Math.round(height * ratio); imgElm.setAttribute("width", calcWidth); } else { imgElm.setAttribute("width", originalWidth); } } }); } else { } })(); //]]> </script>
愚直にif文を並べました。(else ifほうが良かったかも)
もっとカッコイイ書き方があるはず。。。
汎用性が高そうな、.post-bodyを記事内を指定するセレクターに使いました。
.post-body
const basePoint = document.querySelector(".post-body");
お使いのテンプレートによってはセレクターを変更する必要があります。
loading="lazy"とdecoding="async"が必要であれば//(コメントアウト)をはずしてください。
loading="lazy"
decoding="async"
//
/* Lazyload */ //imgElm.setAttribute("loading", "lazy"); /* decoding async */ //imgElm.setAttribute("decoding", "async"); ↓ /* Lazyload */ imgElm.setAttribute("loading", "lazy"); /* decoding async */ imgElm.setAttribute("decoding", "async");
この3行は置き換え可能です
const originalHeight = imgElm.getAttribute("data-original-height"); const originalWidth = imgElm.getAttribute("data-original-width"); const ratio = originalWidth / originalHeight; ↓ const originalHeight = imgElm.dataset.originalHeight; const originalWidth = imgElm.dataset.originalWidth const ratio = imgElm.dataset.originalWidth / imgElm.dataset.originalHeight;
計算した値はMath.roundで四捨五入しました
Math.round
JavaScript | 小数点以下を四捨五入/切り上げ/切り捨てする(Math.round, Math.ceil, Math.floor)
const calcHeight = Math.round(width / ratio); const calcWidth = Math.round(height * ratio);
投稿とページのみに適用させる場合は <b:if cond='data:view.isSingleItem'>...</b:if>や <b:if cond='data:view.isSingleItem and data:view.featuredImage'>...</b:if>などを使ってください。
<b:if cond='data:view.isSingleItem and data:view.featuredImage'> コード </b:if>
画像のタグに直接属性を書いた方が表示スピード的にはいいと思います。
(属性が両方付くようにBloggerにフィードバックを送ってみました)
作成中、挙動が不安定だったので「heightがない」、「widthがない」部分のif文は公開時このように書きました。
// heightがない場合 if (attrHeight == false && attrWidth == true) { // widthがない場合 if (attrWidth == false && attrHeight == true) {
あらためて確認したところ安定しているようなので以下に変更しました。
// heightがない場合 if (attrHeight == false) { // widthがない場合 if (attrWidth == false) {
作っている途中で気がつきましたが、どうやら内部的にwidthやheightの値を保持しているようです。
計算をしなくても、足りない値を得ることができました。
内部的に保持している情報からwidthやheightの値を得るタイプも作ってみましたが、挙動が不安定だったり表示すらされないケースがあったので採用しませんでした。
不具合例
記録として残しておきます。
//うまく動かないので使わないこと //<![CDATA[ (() => { const basePoint = document.querySelector(".post-body"); const postImages = basePoint.querySelectorAll(".separator img"); if (postImages.length > 0) { postImages.forEach((imgElm) => { /* Lazyload */ //imgElm.setAttribute("loading", "lazy"); /* decoding async */ //imgElm.setAttribute("decoding", "async"); // heightとwidthがある場合 if (imgElm.hasAttribute("height") && imgElm.hasAttribute("width")) { return; } else { } // heightとwidthがない場合 if (!imgElm.hasAttribute("height") && !imgElm.hasAttribute("width")) { imgElm.setAttribute("height", imgElm.dataset.originalHeight); imgElm.setAttribute("width", imgElm.dataset.originalWidth); return; } else { } // heightがない場合 if (!imgElm.hasAttribute("height") && imgElm.hasAttribute("width")) { imgElm.setAttribute("height", imgElm.height); return; } else { } // widthがない場合 if (!imgElm.hasAttribute("width") && imgElm.hasAttribute("height")) { if (imgElm.dataset.originalHeight > imgElm.height) { imgElm.setAttribute("width", imgElm.width); } else { imgElm.setAttribute("width", imgElm.dataset.originalWidth); } } }); } else { } })(); //]]>
データ属性の使用 - ウェブ開発を学ぶ | MDN
サイト内検索に使ってください 🐤
© 2015 すたすた式
Enjoy!👍
QooQ
コメントなし:
コメントを投稿