前端图片详解(最全面、最新)

前言

当我们在做前端性能优化的时候,总是会离不开图片,尤其在首次内容绘制(FCP)最大内容绘制 (LCP)中,图片显得格外关键,而我发现关于图片格式的文章,一般不全,或者是偏旧。

所以这篇文章,我将把我学过的关于图片的知识,分享给大家

首先我们可以通过HTTP Archive: Page Weight来直观看一下页面的加载体积

总的 web 资源的平均请求体积是这样的

图片资源,平均请求体积是这样的

在这里插入图片描述

我们发现图片在所有资源中所占的比重,是非常惊人的,所以我们来系统地学习一下图片

图片格式

理解像素、颜色和二进制的关系

无论是通过扫描仪、数码相机还是其他图像捕捉设备,图片首先被转换成像素(picture elements)的阵列。每个像素代表图片中的一个小区域,并且拥有特定的颜色信息。

在计算机中,像素二进制数来表示。不同的图片格式中像素与二进制位数之间的对应关系是不同的。一个像素对应的二进制位数越多,它可以表示的颜色种类就越多,成像效果也就越细腻,文件体积相应也会越大。

一个二进制位表示两种颜色(0|1 对应黑|白),如果一种图片格式对应的二进制位数有 n 个,那么它就可以呈现 2^n 种颜色。

颜色通常通过红绿蓝(RGB)模型来表示,每个颜色通道可以有从0到255的值。在二进制中,一个字节(byte)有8位,足以表示0到255的任何值(因为2^8 = 256)。因此,每个颜色通道可以用8位二进制数来表示,例如,红色通道的值255可以表示为二进制的11111111

图片格式

一旦图片被数字化并分配了颜色值,它就可以被保存为不同的文件格式,那么我们常见的图片格式有哪些,使用场景是什么,区别是什么

这里我们首先可以看MDN提供的图像文件类型与格式指南 - Web 媒体技术 | MDN (mozilla.org)

然后我们稍微整理一下,方便大家观看

缩写MIME类型文件扩展名摘要压缩透明度动画
ANPGimage/apng.apng是无损动画序列的良好选择(GIF 性能较差)。AVIF 和 WebP 性能更好,但浏览器支持较少。无损压缩支持支持
AVIFimage/avif.avif由于其性能高,且无需版税,是图像和动画图像的理想选择。与 PNG 或 JPEG 相比,它的压缩效果更好,支持更高的色深、动画帧、透明度等。请注意,在使用 AVIF 时,应包含浏览器支持更好的回退格式(也就是说,要使用 <picture> 元素)。无损压缩支持支持
GIFimage/gif.gif是简单图像和动画的不错选择。无损有索引的静态图像首选 PNG,动画序列可考虑 WebP、AVIF 或 APNG。无损压缩支持支持
JEPGimage/jpeg.jpg、.jpeg、.jfif、.pjpeg、.pjp静态图像有损压缩的理想选择(目前最流行)。如果需要更精确地再现图像,则首选 PNG;如果需要更好的再现效果和更高的压缩率,则首选 WebP/AVIF。有损压缩不支持不支持
PNGimage/png.png与 JPEG 相比,PNG 能更精确地再现源图像,或在需要透明的情况下更受青睐。WebP/AVIF 可提供更好的压缩和再现效果,但浏览器的支持比较有限。无损压缩支持不支持
SVGimage/svg+xml.svg矢量图像格式;适用于用户界面元素、图标、图表等,必须以不同尺寸精确绘制。可以在传输过程中使用 HTTP 压缩技术进行压缩,也可以在磁盘上以 .svgz 文件的形式进行压缩。支持支持
WebPimage/webp.webp是静止图像和动画图像的绝佳选择。WebP 的压缩效果比 PNG 或 JPEG 好得多,而且支持更高的色深、动画帧和透明度等。AVIF 的压缩效果稍好,但在浏览器中的支持度不高,而且不支持渐进式渲染。无损和有损压缩支持支持

图片格式详解

我们梳理一下每个格式的优缺点,然后说一下常见的使用场景

这里我更想对比着说,看着更直观

GIF和ANPG

首先GIF诞生于1987年,APNG相对新一些,是Mozilla在2004年推出的

APNG实际上是PNG的拓展(看名字就看出来了),APNG 新增了三种区段:acTL、fcTL、fdAT,这三个区段不打算细讲,可能讲了大家也不能很好理解

那么可能有人会问,如果设备或者软件不支持ANPG只支持PNG,那怎么办呢

答案是不用担心,ANPG第一帧储存方式和普通的PNG一样在IDAT区段中

在压缩上GIF采用的是LZW(据说之前GIF的LZW算法有专利限制),而APNG采用的是Deflate,经测试,在经过各种优化手段进行压缩后,ANPG的体积是小于GIF的

在颜色和透明度上GIF最多支持256种颜色,进而导致导致了GIF画质都比较差,同时GIF虽然也支持透明,但是他只支持将某个颜色标记成透明,也就是说他不支持半透明,只支持完全透明或者完全不透明,所以会出现杂边问题,这个问题我正好在一篇ANPG的文章中看到了,正好解释一下

在这里插入图片描述

而反观ANPG,则是完全不受限制的

那么ANPG的缺点是什么呢,可能只有兼容性了和普适性问题了吧

关于使用场景,其实因具体情况而异,但是二者基本都用在动态显示

JPEG/JPG

有小伙伴可能一直不清楚JPG和JEPG的区别,这里咱们就稍微说一下

JPEG(全称Joint Photographic Experts Group)和JPG(全称Joint Photographic Experts Group format)实际上是指同一个图像格式,没有本质区别。"JPEG"通常是指这个格式的组织和标准,而"JPG"则是这种格式的文件扩展名。

JPG的优点较为明显:当我们把图片体积压缩至原有体积的 50% 以下时,JPG 仍然可以保持住60%的品质。同时JPG格式以24位存储单个图,可呈现多达1600万种颜色,这也是压缩后,我们肉眼依旧难以察觉的原因

同时JPG/JEPG兼容性非常好,所以经常在网页背景图片轮播图广告和宣传材料等显眼位置看到它的身影

但是它也有较为明显缺点,有损压缩,在压缩过程中会丢失一部分图像数据。虽然这种损失对于肉眼可能不明显,但在多次编辑和保存后,图像质量的下降可能会变得更加明显,以及在处理矢量图形Logo 等线条感较强、颜色对比强烈的图像时,人为压缩导致的图片模糊会相当明显

同时它不适合用于存储简单图形、图标或文字,因为这些类型的图像通常不需要复杂的颜色信息,而JPG的压缩方式可能会导致这些类型的图像模糊

再者它还不支持透明度处理,所以就需要配合别的格式进行使用

PNG-8 与 PNG-24

我们主要用PNG来呈现小的Logo、颜色简单且对比强烈的图片或背景等

说到PNG,基本上就是说PNG-8与PNG-24,说PNG-32的较少那我们就来说说二者的区别

首先PNG后面的8、24数字,意思是指该格式最多可以索引存储的颜色值

PNG-8:最多存储256种颜色,也就是2^8 = 256,2的8次方。

PNG-24最终的,意思是最多存储1600万种颜色,即2^24 = 16 777216种颜色,也就是2的8次方。

再者,二者的透明度不同

PNG-8:仅支持1位的布尔透明通道,不支持半透明效果

PNG-24:支持alpha半透明过渡效果,也就是可以完美呈现从不透明到完全透明的渐变过渡。

最后,二者的压缩率不同,这也导致最终的体积不同,PNG-24最终的体积是比PNG-8要大出不少的,所以PNG-24不适合存储照片等颜色较多、细节丰富的图片,多用于存储需要保留透明度、颜色单一的图片,比如LOGO、图片水印等文件应使用PNG-24存储。

SVG

SVG和上面的JPG和PNG等有些不同,SVG-可缩放矢量图形,为什么它叫做矢量图形

这是因为它的工作原理与传统的位图图形(如JPEG、PNG等)截然不同。矢量图形的核心特点在于它使用数学公式和几何形状来定义图像,而不是像素点的集合。

缩放性SVG图像是基于数学公式的,这意味着它们可以在任何尺寸下无损放大或缩小。无论图像被缩放到多大或多小,都能保持清晰和锐利,不会出现像素化或模糊,1 SVG足以适配n分辨率

小文件尺寸SVG文件通常比位图文件小,因为它们不需要存储每个像素的颜色信息。相反,它们只存储定义图形的数学方程式和属性,这使得文件尺寸更加紧凑。

文本和编码性SVG文件文本文件,使用XML格式编写。这意味着SVG图像可以被编辑器打开和编辑,就像编辑文本文件一样。可以像写代码一样定义 SVG,把它写在 HTML 里、成为 DOM 的一部分,也可以把对图形的描述写入以 .svg 为后缀的独立文件,这种文本基础的特性也使得SVG文件可以被搜索、索引和脚本化。

交互性SVG支持CSSJavaScript,这意味着可以给SVG元素添加样式和行为,从而创建动态和交互式的图形。例如,可以响应用户的操作,如鼠标悬停、点击等事件。

例如:假设我们有一个简单的SVG图标,我们想在鼠标悬停时改变它的颜色

<svg width="100" height="100">
  <circle cx="50" cy="50" r="40" fill="blue" class="hoverable">
    <title>Hover over me!</title>
  </circle>
</svg>

<style>
  .hoverable:hover {
    fill: red; /* 鼠标悬停时变为红色 */
    cursor: pointer; /* 鼠标悬停时变为手指形状 */
  }
</style>

又或者:通过JavaScript为同一个SVG圆添加点击事件,使其在被点击时改变大小

<svg width="100" height="100" id="mysvg">
  <circle cx="50" cy="50" r="40" fill="blue" class="clickable">
    <title>Click on me!</title>
  </circle>
</svg>

<script>
  var svg = document.getElementById('mysvg');
  var circle = svg.querySelector('.clickable');

  circle.addEventListener('click', function() {
    var currentRadius = parseInt(circle.getAttribute('r'));
    var newRadius = (currentRadius == 40) ? 60 : 40; // 切换半径大小
    circle.setAttribute('r', newRadius);
  });
</script>

再或者:将SVG写入独立文件后引入HTML:

<img src="文件名.svg" alt="">

以上就是简单地举例,目的是为了体现出SVG灵活性

在实际开发中,我们更多用到的是后者。很多情况下设计师会给到我们 SVG 文件,就算没有设计师,我们还有非常好用的 iconfont-阿里巴巴矢量图标库。对于矢量图,我们无须深究过多,只需要对其核心特性有所掌握、日后在应用时做到有迹可循即可。(这段是修言说的,我觉得很好,就摘抄了~)

但是我在使用的时候,也发现了一些SVG的问题:虽然SVG通常比位图图像小,但在描述的矢量元素几何复杂度较高时,基于文本的SVG文件可能比二进制编码的栅格化图像要大(但是的确不能算缺点,只能说不是特别适用)

Base64

Base64其实不是一种图片格式,而是一种编码方法,Base64是为了减少加载网页图片时对服务器的请求次数,从而提升网页性能,它可以将二进制数据(如图片)转换为ASCII字符串。但是会增加页面的总体大小,因为Base64编码后的字符串通常比原始的二进制数据要大(这也是Base64不适用于大图,适用于小图的原因

这种感觉有点类似于雪碧图,但是原理不一样,雪碧图是一种将多个小图片合并到一张大图片中的技术,通过CSS的background-imagebackground-position属性来引用大图中的特定小图片,这样减少了HTTP请求次数,提升了网页加载速度,并且可以提前加载可能需要用到的小图片,减少页面闪烁

二者更像是相辅相成的关系,它们都可以用于优化网页性能,但选择哪一种技术取决于具体的应用场景和需求

WebP和AVIF

二者都是10年后诞生的,我们称之为现代图片格式,它的优点明显,都能覆盖传统格式(JPG、PNG等)的动态图片无损压缩等功能和特性,传统格式特性较为单一,现代格式支持动态图片、无损压缩等特性更多,并且体积变小,相较于jpg格式,webp格式的图片一般能减少10%左右的体积,avif格式更是能减少40%以上的文件体积。

缺点基本就是兼容性(其实WebP还好了,早些年的确兼容性的确不行,现在基本都支持了),这里我们二者进行对比

工作原理上

  • WebP:基于VP8编解码器,使用有损和无损压缩方法的组合来实现更小的文件大小,有损压缩与 JPEG 相似,但增加了优化功能,从而提高了图像质量。它的无损压缩使用一种称为预测编码的技术,该技术可预测相邻像素的值,并只对实际值和预测值之间的差值进行编码。
  • AVIF:使用AV1编解码器,在不影响图像质量的情况下减小文件大小,具有内部预测(根据邻近块预测块的内容)和自适应量化(根据图像的复杂程度调整压缩级别)的功能,既是最先进的又是免版税的。

色彩上

  • WebP:支持8位和10位色深
  • AVIF:支持8位和10位以及12位色深,可见AVIF这个后起之秀,在色彩准确度和鲜艳度方面更胜一筹

这样看来AVIF尤其适用于高质量图像(如照片这种的),而如果需要的是一种通用的图像格式,并能获得广泛的浏览器支持,那么 WebP 就是您的不二之选

用现代图片格式优化性能以及体验

我们经过上面的学习发现,如果能使用webp,avif等现代格式,对解决前端应用图片类资源体积较大,加载耗时较长、CDN开销较高的痛点会有明显优化。那么我们具体怎么做呢?

回答是:<picture>元素

我们看一下MDN对于picture 元素的定义吧

在这里插入图片描述

看起来很懵,什么意思呢

<picture>元素允许同时引入多个图片格式的子元素,并根据浏览器的兼容性,按先后顺序、自适应加载其中1个格式的图片,实现所有用户根据自身兼容性,获取到最优图片格式。

我写一段代码,大家就明白了

<picture>
  <!-- WebP格式的图片,具有无损和有损压缩 -->
  <source srcset="image.webp" type="image/webp">
  <!-- AVIF格式的图片,具有更高的压缩率 -->
  <source srcset="image.avif" type="image/avif">
  <!-- JPEG格式的图片,作为备选 -->
  <source srcset="image.jpg" type="image/jpeg">
  <!-- 如果浏览器不支持上述任何格式,就使用这个img标签作为最后的备选 -->
  <img src="fallback-image.jpg" alt="Description of Image">
</picture>
  • <picture>元素是一个容器元素,元素中包含了2个<source>元素和1个<img>元素。
  • 每个<source>元素都有一个srcset属性,它指定了图片的URL,以及一个type属性,它描述了图片的MIME类型。浏览器会根据这些信息和自身的兼容性来决定加载哪个图片。
  • 如果所有的<source>元素都不被支持,那么<img>元素将作为最后的备选方案。这是一个包含JPEG图片(别的格式也可以,选兼容性好的即可)的<img>标签,相当于一个兜底操作

通过这种方式,可以确保所有用户都能加载到他们设备支持的最佳格式的图片,从而提供更好的网页体验和性能,而大家也不要小瞧这种方式,现在其实是很常用的。

结尾

本文带着大家过一遍常见的图片格式,包括内容优缺点等,希望带着大家了解关于图片的具体内容,其实本来是想着把关于图片的优化都写在这一篇的,奈何实在是过于散乱,配合这篇基础文章显得不合适,所以只介绍了一种较为简单,还能承接上文的<picture>元素的方式给大家

其实关于什么雪碧图之类的网上已有全面的教程,所以不打算写了,而关于什么懒加载的实际上是交互上的优化内容,所以也不会去写

在之后的文章中会接着写一下关于图片的知识点,图片优化实战方面的内容,比如写一下辅助函数配合CDN啦,压缩图片具体操作啦等内容,蟹蟹大家支持~

  • 28
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

林多多@

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值