整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

前端初学者:手把手教你写一个图片库

前端初学者:手把手教你写一个图片库

者有话要说:此文适合前端初学者哦~如有大神路过,请多多指教。

最近在看《JavaScript DOM编程艺术》这本书,顺手给大家安利下。不得不说作者真真是极其细致的一个人,写得不仅通俗易懂,而且妙趣横生,非常适合初学者。本文也是来自书中第四-六章的案例。好啦,废话不多说,直接先上成果。

<script src="https://lf3-cdn-tos.bytescm.com/obj/cdn-static-resource/tt_player/tt.player.js?v=20160723"></script>

我这里写了一个二十四节气,图片均源自网络,仅用于分享教学,如涉及侵权,请联系我删除。大家可自行发挥创意,比如写一个情侣照片库啦,旅游照片合辑啦等等都是非常不错的idea呢。

1.整体结构和框架

从视频中可以看到我们的需求是点击相应的文本,在当前窗口内切换图片和相应的说明文字。那么需要在网页内设置一个图片占位符,并阻止超链接的默认弹窗行为。将整个文档分为两部分,列表部分和展示部分。

分别设置list和show的CSS属性。

2.列表部分

接下来优化list,这部分的思路就是一个4x6的弹性盒。首先补充list中的a标签,添加图片路径和title属性。二十四个节气就有24个a标签,此处有省略。

我这里将每个小格子命名为block,同样设置为弹性盒,这样可以方便地把文本链接用margin:auto实现上下左右居中。最后可根据自己的喜好更改链接被鼠标悬停、被访问后的状态。

至此list部分就写好啦。

列表部分整体的完成效果

3.占位符初始状态

占位符初始状态指的是链接未被点击之前显示的一张默认图片,我这里就用第一张图片(第一个节气)来显示。最最关键的部分要来了,如何使图片在当前占位符位置切换呢?这里肯定是要编写一个JS函数的,把它命名为replace.js。

占位符初始状态

4.编写一个简单的showPic()

为图片占位符命名为placeholder,替换文本命名为description,分别设置CSS属性。

占位符整体的效果

当链接被点击时进行替换行为。我们可以在每个a链接中绑上onclick属性,将行为函数命名showPic(),参数即为当前a标签(this)。

在showPic()里需要完成的事件是:获取a标签中的href属性,用它来替换placeholder中的src属性;获取a标签中的title属性,用它来替换description中的文本(nodeValue值)。注意此处文本是p标签的第一个子节点,所以要加上.firstChild。

showPic()函数写完了,接下来就是要阻止a链接被点击时的默认弹出新窗口行为(因为我们想要图片切换就发生在占位符位置)。有以下两种实现方式:

一是在onclick中直接添加return false;

二是让showPic()函数的返回值直接为false,然后在onclick中返回showPic()函数的返回值。

至此这个图片库就全部写好啦,快去试试吧~

之前的文章中,我们讨论了图片的尺寸自适应、裁切与缩放、压缩、动态webp等技术。这些技术都是对单张图片的处理,而在实际项目中,我们往往需要处理大量的图片。本文将讨论如何高效批量优化图片,并介绍一些图片加载技巧。

一、图片预加载

图片预加载(Preloading Images)是一种提前加载即将使用的图片资源的技术。通过在页面加载时就将未来可能用到的图片资源进行预加载,可以在用户真正需要这些图片时,减少等待时间,提升用户体验。


HTML中的预加载


在HTML中,可以通过<link>标签的rel属性来实现图片预加载。例如,我们可以在页面的`<head>`标签中添加如下代码:

<link rel="preload" href="image.jpg" as="image" fetchpriority="high">


<link> 标签用于预加载一个图片资源。让我们逐个解释其中的属性及其作用:


  • rel="preload":


当前<link>标签的用途是预加载资源。preload告诉浏览器提前加载指定的资源(在这里是图片),以便在后续使用时能够更快地提供资源。这有助于提高页面的加载性能,尤其是在资源密集型的网站上。


  • href="image.jpg":


指定要预加载的资源的URL。href属性是一个URL,指向需要预加载的资源。在这个例子中,image.jpg是要预加载的图片的路径。


  • as="image":

指定预加载资源的类型。as属性告诉浏览器预加载资源的类型,以便正确地处理和优化加载过程。在这个例子中,as="image"明确了资源是一个图片。这对于浏览器优化资源加载顺序和优先级非常重要。


  • fetchpriority="high":


指定预加载资源的获取优先级。fetchpriority属性是一个新的属性,用于指示浏览器在预加载资源时的优先级。在这个例子中,fetchpriority="high"告诉浏览器这是一个高优先级的资源,应该尽快加载。这在需要确保关键资源(如首屏图片)快速加载时非常有用。


CSS中的预加载


在CSS中,可以通过background-image属性来实现图片预加载。例如,我们可以在CSS文件中添加如下代码:

.preload {
 background-image: url('image.jpg');
}

这段CSS代码定义了一个`.preload`类,其中包含了一个 background-image 属性,指定了要预加载的图片资源的URL。在页面加载时,浏览器会提前加载这个图片资源,以便在后续使用时能够更快地提供资源。


JavaScript中的预加载


JavaScript中,可以通过Image对象来实现图片预加载。例如,我们可以在JavaScript代码中添加如下代码:

var img=new Image();
img.src='image.jpg';

这段JavaScript代码创建了一个新的Image对象,并设置了src属性为要预加载的图片资源的URL。当这段代码执行时,浏览器会开始加载这个图片资源,以便在后续使用时能够更快地提供资源。


二、图片懒加载

图片懒加载(Lazy Loading Images)是一种延迟加载图片资源的技术。通过在页面加载时只加载可见区域内的图片资源,可以减少页面的加载时间,提升用户体验。


img loading属性


HTML中,可以通过loading属性来实现图片懒加载。例如,我们可以在<img>标签中添加如下代码:


<img src="image.jpg" loading="lazy" alt="Image">

loading属性是一个新的属性,用于指定图片的加载方式。它有三个可能的值:


  • auto: 默认值,表示图片会在页面加载时立即加载。
  • lazy: 表示图片会在视口内时才会加载。
  • eager: 表示图片会在页面加载时立即加载,不管是否在视口内。


Intersection Observer API


JavaScript中,可以通过Intersection Observer API来实现图片懒加载。Intersection Observer API是一种用于监视元素与视口交叉状态的API,可以用于实现懒加载、无限滚动等功能。


例如,我们可以在JavaScript代码中添加如下代码:

// 创建一个IntersectionObserver实例
 const intersectionObserver=new IntersectionObserver((entries)=> {
  entries.forEach(entry=> {
  if (entry.isIntersecting) {
  // 当元素与视窗交叉时执行的操作
  const img=entry.target; // entry.target是交叉的元素
  // 假设data-src属性包含了图片的路径
  img.src=img.dataset.src;
  intersectionObserver.unobserve(img); // 停止观察该元素
 }
 });
});

// 为所有需要滚动加载的元素(例如图片)设置观察
document.querySelectorAll('img[data-src]').forEach((img)=> {
 intersectionObserver.observe(img);
});

这段JavaScript代码创建了一个IntersectionObserver实例,并为所有带有data-src属性的图片元素设置了观察。当图片元素与视口交叉时,会加载图片资源,并停止观察该元素。

Scroll事件


JavaScript中,也可以通过监听scroll事件来实现图片懒加载。例如,我们可以在JavaScript代码中添加如下代码:

// 获取所有带有data-src属性的图片元素
 const lazyImages=document.querySelectorAll('img[data-src]');
 // 懒加载函数
 function lazyLoad() {
  lazyImages.forEach((img)=> {
  if (img.offsetTop < window.innerHeight + window.pageYOffset + 200) {
  img.src=img.dataset.src;
  img.removeAttribute('data-src');
  }
 });
 // 更新 lazyImages,排除已加载的图片
 lazyImages=document.querySelectorAll('img[data-src]');
 // 如果所有的图片都已经加载,则移除事件监听器
 if (lazyImages.length===0) {
 document.removeEventListener('scroll', lazyLoad);
 }
}
// 监听scroll事件
document.addEventListener('scroll', lazyLoad);
// 初始检查一次,以便在页面加载时懒加载位于视窗中的图片
lazyLoad();

这段JavaScript代码监听了scroll事件,并在图片元素进入视口时加载图片资源。当图片进入视口时,会加载图片资源,并移除data-src属性。


结合多种方法来实现图片懒加载


在实际项目中,我们可以结合多种方法来实现图片懒加载,以便在不同浏览器和环境下提供最佳的用户体验。例如,我们可以先检查浏览器是否支持loading属性,如果支持,则使用`loading`属性实现图片懒加载;如果不支持,则检查浏览器是否支持Intersection Observer API,如果支持,则使用Intersection Observer API实现图片懒加载;如果不支持,则使用scroll事件实现图片懒加载。


下面是一个示例代码,演示了如何结合多种方法来实现图片懒加载:


html

<body>
 <img src="placeholder.jpg" data-src="image1.jpg" alt="Description 1">
 <img src="placeholder.jpg" data-src="image2.jpg" alt="Description 2">
 <img src="placeholder.jpg" data-src="image3.jpg" alt="Description 3">
 <!-- 更多 img -->
 <script src="lazyload.js"></script>
</body>

javascript

const lazyImages=document.querySelectorAll('img[data-src]');
// 判断浏览器是否支持 loading 属性
if('loading' in HTMLImageElement.prototype) {
  lazyImages.forEach(img=> {
  img.src=img.dataset.src;
  });
 } else if('IntersectionObserver' in window) {
  // 使用Intersection Observer API实现懒加载
 const intersectionObserver=new IntersectionObserver((entries)=> {
 entries.forEach(entry=> {
 if (entry.isIntersecting) {
 const img=entry.target;
 img.src=img.dataset.src;
 intersectionObserver.unobserve(img);
 }
 });
 });

 lazyImages.forEach((img)=> {
 intersectionObserver.observe(img);
 });
} else {
 // 使用scroll事件实现懒加载
 let lazyImages=document.querySelectorAll('img[data-src]');
 function lazyLoad() {
 lazyImages.forEach((img)=> {
 if (img.offsetTop < window.innerHeight + window.pageYOffset + 200) {
 img.src=img.dataset.src;
 img.removeAttribute('data-src');
 }
 });
 lazyImages=document.querySelectorAll('img[data-src]');
 if (lazyImages.length===0) {
 document.removeEventListener('scroll', lazyLoad);
 }
 }
 document.addEventListener('scroll', lazyLoad);
 lazyLoad();
}

三、渐进式图片加载

图片渐进式加载(Progressive Image Loading)是一种逐步加载图片资源的技术。通过在图片加载过程中逐步显示模糊的低分辨率图片,可以提升用户体验,减少等待时间。这种技术不仅适用于优化页面性能,还可以为用户提供视觉上的反馈,使页面显得更加流畅。


渐进式 JPEG


渐进式 JPEG (Progressive JPEG) 是一种通过逐步显示图片的技术,渐进式 JPEG 与标准的 JPEG 图片区别在于,渐进式 JPEG 图片在加载时会逐步显示图片的分辨率,而不是一次性显示完整的图片。这种逐步加载的方式可以提升用户体验,减少等待时间。渐进式 JPEG 图片最初会显示的是一张模糊的低分辨率图片,随着数据的不断加载,图片的分辨率会逐步提高,直至达到全分辨率。这种方法特别适合需要加载大图的场景。


许多图像编辑工具和压缩工具都支持将图片保存为渐进式 JPEG。在实际项目中,例如,在 Photoshop 中保存图片时,可以勾选“渐进式”选项。也可以使用命令行工具如ImageMagick(https://imagemagick.org/index.php)来生成渐进式 JPEG:

1convert input.jpg -interlace Plane output.jpg




需要注意的是渐进式 JPEG 图片的文件大小通常会比标准的 JPEG 图片稍大,因为渐进式 JPEG 图片包含了更多的数据,用于逐步显示图片的分辨率,但是这种额外的数据可以提升用户体验。因此,在选择使用渐进式 JPEG 图片时,需要权衡图片质量和文件大小之间的关系。


占位图技术


占位图技术(Placeholder Image)通常使用一个非常小的、模糊的低分辨率图像作为占位符,在高分辨率图像加载完成之前先显示出来。这种方法通过减少初始加载时间和网络请求,可以显著提升页面的首屏加载速度。


占位图实现原理很简单,只需要在页面中插入一个占位图像,然后在高分辨率图像加载完成后替换为真实图像即可。


  • 生成一个小尺寸的图片,并将其模糊化处理。
  • 在页面初始加载时,先显示这张模糊的小图,待高分辨率图像加载完成后再替换。


代码示例:

html:

<img src="https://fs.autohome.com.cn/energyspace_views/image_demo/compress_before.png?format=webp&dis_rule=20x0_q50_" data-src="https://fs.autohome.com.cn/energyspace_views/image_demo/compress_before.png?format=webp&dis_rule=400x0_q90_" alt="Description">

javascript:

document.addEventListener('DOMContentLoaded', function() {
  const lazyImages=document.querySelectorAll('img[data-src]');
  lazyImages.forEach(img=> {
  const placeholder=new Image();
  placeholder.src=img.src;
  placeholder.onload=()=> {
  img.src=img.dataset.src;
  };
  });
});



img src 属性中的图片是一个模糊的小图,data-src 属性中的图片是高分辨率图像。在页面加载时,先显示模糊的小图,待高分辨率图像加载完成后再替换。


使用占位图技术可以有效减少页面的加载时间,提升用户体验。同时,占位图技术也可以结合图片懒加载技术一起使用,进一步提升页面性能。

四、Base64 编码

在 Web 开发中,将图片转换为 Base64 编码是一种优化页面加载速度的方法,但需要权衡其优缺点。一般来说,适用于 Base64 编码的图片大小取决于几个因素,包括页面的总体加载时间、HTTP 请求的数量以及文件大小。


Base64 编码的优点


  • 减少 HTTP 请求:将图像嵌入到 HTML 或 CSS 中可以减少 HTTP 请求,从而加快页面加载速度。对于小图标或背景图片,效果尤为显著。
  • 简单易用:Base64 编码图像是一种文本格式,可以方便地嵌入 HTML、CSS 或 JSON 中,不需要额外的图像文件管理。
  • 适用于小图像:Base64 编码特别适合用于小图像,例如网站的 logo、按钮、图标等。


Base64 编码的缺点


  • 增加文件体积:Base64 编码会使文件体积增加,因此对于大图像,不推荐使用这种方法。
  • 缓存问题:由于 Base64 图像嵌入在 HTML 或 CSS 文件中,浏览器不能单独缓存这些图像文件,因此在更新图像时需要重新下载整个 HTML 或 CSS 文件。
  • 可读性差:Base64 编码图像是一长串字符,嵌入到文档中会降低文档的可读性和可维护性。


适合转为 Base64 的图片大小一般为 1KB 到 10KB 的图片:通常,文件大小在 1KB 到 10KB 之间的图片是转为 Base64 编码的最佳选择。这样的图片往往是小图标、按钮、背景图案等。对于这些小图片,Base64 编码可以显著减少 HTTP 请求的数量,从而提升页面加载速度。


在实际Web项目开发中,使用 Webpack Vite 将小图片自动转换为 Base64 编码是一个常见的优化方法。这种自动化的处理可以简化开发流程,并确保在构建过程中优化资源。


webpack 配置示例:

module.exports={
  module: {
  rules: [
  {
  test: /\.(png|jpe?g|gif)$/i,
  use: [
  {
  loader: 'url-loader',
  options: {
 limit: 10240, // 10KB
 },
 },
 ],
 },
 ],
 },
};

Vite 配置示例:

import { defineConfig } from 'vite';

export default defineConfig({
 build: {
 assetsInlineLimit: 10240, // 10KB
 },
});

在以上配置中,limit assetsInlineLimit 选项指定了图片转为 Base64 编码的阈值,超过这个阈值的图片将被单独打包为文件,而小于这个阈值的图片将被转为 Base64 编码

五、结语

通过结合多种图片加载与优化技术,可以提升页面性能,提供更好的用户体验。预加载、懒加载、渐进式加载等技术在不同场景下有着不同的优势,通过合理地选择和组合这些技术,可以有效地优化图片加载过程。


在实际项目中,建议根据项目的具体需求,选择合适的技术和工具进行图片优化和加载。希望本文所介绍的技术和示例代码能够帮助您更好地实现图片批量处理与加载优化,提升网页的加载速度和用户体验。


WEB 图片优化的相关文章到此结束,希望对你有所帮助。如果有任何问题或建议,欢迎在评论区留言,谢谢!



作者:之家-梁家玮

来源-微信公众号:之家前端共享流

出处:https://mp.weixin.qq.com/s/bhxtIED32lJP7PY9g28GNA

般我们常见placeholder伪类选择器用来修改默认样式及文案,忽然发现placeholder-shown伪类选择器,比较官方的解释是

CSS伪类表示任何显示占位符文本的form元素。

简单来说就是当输入框的placeholder内容显示的时候,输入框干嘛干嘛。

兼容性如下,在移动端没什么问题

placeholder-show是如何工作的?

:placeholder-shown CSS 伪类 在 <input> 或 <textarea> 元素显示 placeholder text 时生效,简单的说就是 placeholder 有值才生效,如下所示:

// html
<input placeholder="placeholder text" />
<textarea placeholder="placeholder text"></textarea>

// css 
input:placeholder-shown, textarea:placeholder-shown{ 
  border:1px solid pink;
}

如果 placeholder 为空 placeholder-show 就没效果了:

// html
<input placeholder="" />
<textarea placeholder=" text"></textarea>

:placeholder-shown vs ::placeholder

我们可以使用:placeholder-shown设置input元素的样式。

input:placeholder-shown {
  border: 1px solid pink;
  background: yellow;
  color: green;
}

注意一些奇怪的问题-我们设置 color: green,但没有作用用。这是因为:placeholder-shown仅会针对input本身。对于实际的占位符文本,必须使用伪元素::placeholder。

input::placeholder {
  color: green;
}

?? 我注意到有一些其他的属性,如果应用::placeholder-shown,也会影响placeholder的样式。

input:placeholder-shown, textarea:placeholder-shown{ 
  font-style: italic;
  text-transform: uppercase;
  letter-spacing: 5px;
}

我也不知道这是啥情况,也许是因为这些属性被placeholder继承了,如果你知道原因,欢迎留言告诉我一下,谢谢。

:placeholder-shown vs :empty

:placeholder-shown是专门用于确定元素是否显示占位符的对象,我们主要使用它来检查input 内容是否为空(假设所有的input都有一个占位符)。这里你可能会想,使用 empty 也是可以的吧?我们来看看。

// html
<input value="not empty">
<input><!-- empty -->

// css
input:empty {
  border: 1px solid pink;
}

input {
  border: 1px solid black;
}

这里看似empty起作用了,因为我们看到的是粉红色边框,但这实际上不起作用

之所以显示粉红色,是因为伪类增加了 css 的权重。类似于类选择器(即.form-input)比类型选择器(即input)具有更高的权重。高权限选择器将始终覆盖低权重设置的样式。

所以我们可以这样说:不要使用:empty检查输入元素是否为空。

如果检查 input 内容是否为空(在没有点位符的情况下)?

我们检查输入是否为空的唯一方法是使用:placeholder-shown。但是如果我们的输入元素没有占位符会发生什么呢? 这里有个取巧的方法:传入一个空字符串" "。

// html
<input placeholder=" "><!--  pass empty string -->

//css
input:placeholder-shown {
  border-color: pink;
}

组合其它选择器

我们可以使用:not伪类对某些事物进行逆运算。在这里,我们可以在输入不是空的情况下进行定位。

//html
<input placeholder="placeholder" value="not empty" />

// css
input:not(:placeholder-shown) {
  border: 1px solid green;
}

实战

用placeholder-shown我们可以实现下面动效

具体代码如下:

Html

<div class="input">
    <input class="input-fill" placeholder="邮箱">
    <label class="input-label">邮箱</label>
</div>

Css

.input{
   position: relative;
 }
.input-fill{
  border: 1px solid #ececec;
  outline: none;
  padding: 13px 16px 13px;
  font-size: 16px;
  line-height: 1.5;
  width: fit-content;
  border-radius: 5px;
}
.input-fill:placeholder-shown::placeholder {
  color: transparent;
}
.input-label {
  position: absolute;
  font-size: 16px;
  line-height: 1.5;
  left: 16px; top: 14px;
  color: #a2a9b6;
  padding: 0 2px;
  transform-origin: 0 0;
  pointer-events: none;
  transition: all .25s;
}
.input-fill:focus{
  border: 1px solid #2486ff;
}
.input-fill:not(:placeholder-shown) ~ .input-label,
.input-fill:focus ~ .input-label {
  transform: scale(0.75) translate(0, -32px);
  background-color: #fff;
  color: #2486ff;
}

作者:Samantha Ming 译者:前端小智 来源:medium 原文:https://www.samanthaming.com/tidbits/88-css-placeholder-shown/