前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Hugo 图片懒加载和自适应 CSS 图片占位

Hugo 图片懒加载和自适应 CSS 图片占位

作者头像
Shiroka
发布2022-05-29 15:56:11
2K0
发布2022-05-29 15:56:11
举报
文章被收录于专栏:pwpw

对于未对中国大陆优化的博客站点而言,图片懒加载几乎是必备的功能,它能够有效提高页面的首屏速度。静态站点的懒加载方案有很多,但都必然会带来布局偏移的问题,影响页面的 CLS 分数

本文将基于浏览器原生懒加载和 Hugo 使用的 Golang html/template 模板引擎,实现图片懒加载和对不同比例自适应的 CSS 图片占位。

懒加载实现

图片懒加载有很多实现方式。很久以前有基于 jQuery 的 Lazy Load,如今随着 jQuery 退场几乎不再使用了;后来有基于原生 Intersection Observer API 实现的 vanilla-lazyload,可以基本上符合懒加载的需求。

随着越来越多曾经的第三方 JS 实现的功能被标准化,针对图片和 iframe 的浏览器原生的懒加载出现在了 HTML 标准中。在写下这篇文章的 2022 年中旬,根据 Can I use,Chrome 77+、Edge 79+、Firefox 75+ 和 Safari 15.4+ 均支持了对图片元素的原生懒加载。

作为一个仅对最新大版本提供支持的博客,使用原生懒加载已经不成问题,且原生懒加载的策略由浏览器决定,可以随着版本更新而优化,实现也非常简单:

代码语言:javascript
复制
<img src="https://example.org/img.jpg" loading="lazy" alt="Lazy Image" />

布局偏移问题

凡是懒加载的图片,必然会出现布局偏移的问题。在图片加载前,图片占据高度为 0,而图片加载后,图片占据高度可能会发生变化,从而导致布局偏移。

布局偏移问题的常规解决方案如下,以全宽图片为例:

  1. img 元素放置在两层 div 容器中
  2. 设置外层容器的 position 属性为 relativewidth100%
  3. 设置内层容器的 height0, padding 为图片宽高比
  4. 为最外层容器设置占位背景色
代码语言:javascript
复制
.fiximg {
  position: relative;
  display: block;
  overflow: hidden;
  background-color: var(--color-wrapper);
  width: 100%;

  &__container {
    display: block;
    width: 100%;
    height: 0;
    margin: 0;
    padding-bottom: '<ASPECT RATIO HERE>';

    img {
      display: block;
      width: 100%;
      margin: 0;
      color: var(--color-primary);
      font-size: inherit;
      text-align: center;
    }
  }
}

但是,对于博客文章而言,插入图片的宽高比是不确定的,因此将固定宽高比的效果非常一般。

Go HTML 模板实现

本站的静态网页生成器 Hugo 使用 Golang 的 html/template 模板引擎实现模板。

本站的图片资源结构是分散式的。对于每篇文章,Hugo 都存在页面资源这一概念,即在每篇文章的 index.md 同目录下的资源文件会被 Hugo 认为是该文章特有的资源。

Hugo 在渲染插入图片时,允许通过 Markdown Render Hooks 的方法对渲染的 HTML 进行自定义,因此主要的实现就在这之中进行。

首先创建 layouts/_default/_markup/render-image.html 文件,获取图片资源:

代码语言:javascript
复制
{{ $image := .Page.Resources.Match .Destination }}
{{ if ge (len $image) 1 }}
{{ $image = index $image 0 }}
{{ else }}
{{ warnf "Image not found \"%s\"" .Destination }}
{{ end }}

获取图片后,解析图片的宽高,并将宽高乘上 1.0 转换为浮点数:

代码语言:javascript
复制
{{ $imageHeight := mul $image.Height 1.0 }}
{{ $imageWidth := mul $image.Width 1.0 }}
{{ if or (lt $imageHeight 1) (lt $imageWidth 1) }}
{{ warnf "Image not valid \"%s\"" .Destination }}
{{ end }}

随后,根据宽高计算图片的宽高比,并生成底部 padding 的内联样式:

代码语言:javascript
复制
{{ $ratio := mul (div $imageHeight $imageWidth) 100 }}
{{ $css := printf "padding-bottom: %.4f%%;" $ratio }}

最后,根据图片宽度,为大图设置全宽,小图设置为原始宽度,并输出 HTML 即可:

代码语言:javascript
复制
{{ $width := "width: 100%;" }}
{{ if le $imageWidth 652 }}
{{ $width = printf "width: %.0fpx;" $imageWidth }}
{{ end }}
代码语言:javascript
复制
<!-- goldmark will insert p tag before & after image div so theres no need to wrap it with p tag -->
<div class="fiximg" style="{{ $width | safeCSS }}">
  <div class="fiximg__container" style="{{ $css | safeCSS }}">
    <img loading="lazy" src="{{ $image.Permalink }}" alt="{{ .Text }}" />
  </div>
</div>

效果预览

以这篇文章上文的图片为例,加载前:

加载完成后:

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-05-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 懒加载实现
  • 布局偏移问题
  • Go HTML 模板实现
  • 效果预览
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档