1.picture
根据屏幕匹配的不同尺寸显示不同图片,如果没有匹配到或浏览器不支持 picture 属性则使用 img 元素
<picture>
<source media="(max-width:750px)" srcset="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/fa8a465887b744629fc8d509f04ddee0~tplv-k3u1fbpfcp-zoom-mark-crop-v2:460:460:0:0.awebp" >
<img src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/496767f91dd44ee1a427c4423007537b~tplv-k3u1fbpfcp-zoom-mark-crop-v2:240:240:0:0.awebp">
</picture>
2. js图片懒加载
在data-srcset 、data-src放入正常显示的图片;
在srcset 、src 放入一张loading图片,来代替网络还未加载正常图片前的页面空白。
<picture>
<source media="(max-width:750px)" srcset="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/9a05115a403f4a0c866993e4d7291f88~tplv-k3u1fbpfcp-zoom-mark-crop-v2:460:460:0:0.awebp" data-srcset="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/fa8a465887b744629fc8d509f04ddee0~tplv-k3u1fbpfcp-zoom-mark-crop-v2:460:460:0:0.awebp">
<img src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/9a05115a403f4a0c866993e4d7291f88~tplv-k3u1fbpfcp-zoom-mark-crop-v2:460:460:0:0.awebp" data-src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/496767f91dd44ee1a427c4423007537b~tplv-k3u1fbpfcp-zoom-mark-crop-v2:240:240:0:0.awebp" alt="">
</picture>
let images = document.querySelectorAll('[data-src],[data-srcset]');
let observer = new IntersectionObserver(entries => {
entries.forEach(item => {
if (item.isIntersecting) {
if (item.target.dataset.src) {
item.target.src = item.target.dataset.src;
}
if (item.target.dataset.srcset) {
item.target.srcset = item.target.dataset.srcset;
}
observer.unobserve(item.target); // 停止监听已开始加载的图片
}
});
}, {rootMargin: "0px 0px 200px 0px"});
images.forEach(item => observer.observe(item));
3. 占位符以及响应式适配
在写响应式适配时,图片、文字(即图片可以当背景图,上面有文字)同时需要响应式。我这里用到的是——定位,外层裹一个div,里面放 图片、文字进行定位。
这里的图片假设本身的宽高是 1400 x 1000; loading的图片假设本身的宽高是 240 x 240;
<style>
.box-big{
max-width: 1400px;
width: 100%;
position: relative;
}
.box-big img {
max-width: 100%;
display: block;
margin: 0 auto;
}
.box-big .box-title {
position: absolute;
left: 10%;
top: 8%;
z-index: 33;
}
</style>
<div class="box-big">
<picture>
<source media="(max-width:750px)" srcset="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/9a05115a403f4a0c866993e4d7291f88~tplv-k3u1fbpfcp-zoom-mark-crop-v2:460:460:0:0.awebp" data-srcset="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/fa8a465887b744629fc8d509f04ddee0~tplv-k3u1fbpfcp-zoom-mark-crop-v2:460:460:0:0.awebp">
<img src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/9a05115a403f4a0c866993e4d7291f88~tplv-k3u1fbpfcp-zoom-mark-crop-v2:460:460:0:0.awebp" data-src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/496767f91dd44ee1a427c4423007537b~tplv-k3u1fbpfcp-zoom-mark-crop-v2:240:240:0:0.awebp" alt="">
</picture>
<div class="box-title">
<h3>title</h3>
<P>words</P>
<P>words</P>
<P>words</P>
<P>words</P>
</div>
</div>
这样会有一个问题,当网络迟迟加载不出原本的图片,而loading图片的高度只有240,远远撑不起原本高度的样式;当好几个loading累加在一起会出现一团乱麻。
解决:办法有很多,比如给一张同样的高度是1000 的loading 图即可。
我这里的是用js,当是loading图时,则把外层的div的高度设置为1000;相反当不是loading图时,则把外层div的高度设置为auto。
let images = document.querySelectorAll('[data-src],[data-srcset]');
let observer = new IntersectionObserver(entries => {
entries.forEach(item => {
if (item.isIntersecting) {
if (item.target.dataset.src) {
item.target.src = item.target.dataset.src;
const parentDom = item.target.parentNode.parentNode
if (parentDom.dataset.minHeight === '1') {
const img = new Image()
img.src = item.target.src
img.onload = () => {
parentDom.style.minHeight = 'auto' // 把外层div的高度设置为auto
parentDom.dataset.minHeight = '0' // 标记设置回 0
}
}
}
if (item.target.dataset.srcset) {
item.target.srcset = item.target.dataset.srcset;
const parentDom = item.target.parentNode.parentNode
if (parentDom.dataset.minHeight === '1') {
const img = new Image()
img.src = item.target.src
img.onload = () => {
parentDom.style.minHeight = 'auto'
parentDom.dataset.minHeight = '0'
}
}
}
observer.unobserve(item.target); // 停止监听已开始加载的图片
}
});
}, {rootMargin: "0px 0px 200px 0px"});
images.forEach(item => observer.observe(item));
let bigImg = document.querySelectorAll('.box-big')
let samllImg = document.querySelectorAll('.box-samll')
function lazyload(arr,val) {
arr = [...arr]
arr.forEach((item) => {
let isGif = (item.querySelector('img') && item.querySelector('img').src.includes('2205/photo/0bcda4d0d7')) || false
if (isGif) {
item.style.minHeight = val
item.dataset.minHeight = '1'
} else {
item.style.minHeight = 'auto'
item.dataset.minHeight = '0'
}
})
}
lazyload(bigImg,'1000px')
lazyload(samllImg,'700px')
最后延申一个点:当图片设置为背景图时,背景图进行懒加载
// html里面的img的占位符—— data-src
<div class="b-Big">
<div class="b-Img"><img src="loading.gif" data-src="./img/content-product-mark.jpg" alt=""></div>
<div class="b-Words">
<p>Words</p>
<p>Words</p>
<p>Words"</p>
</div>
</div>
<style>
// 在css样式中的背景图进行懒加载—— data-bgsrc
.box-bg {
width:100%;
height: 500px;
background: url("./img/loading.gif");
background-size: 240px;
background-repeat: no-repeat!important;
background-position: center!important;
}
</style>
<div class="box-bg" data-bgsrc="./img/content-product-rearLight-bg.jpg">
<div class="bikeEb-title">
<h3>title</h3>
<p>Words</p>
<p>Words</p>
</div>
</div>
// js 代码
let images = document.querySelectorAll('[data-src],[data-bgsrc]');
let observer = new IntersectionObserver(entries => {
entries.forEach(item => {
if (item.isIntersecting) {
if (item.target.dataset.src) {
item.target.src = item.target.dataset.src;
}
console.log(item.target.dataset.bgsrc)
if (item.target.dataset.bgsrc) {
item.target.style.background = `url(${item.target.dataset.bgsrc})`;
item.target.style.backgroundSize = '100%'
}
observer.unobserve(item.target); // 停止监听已开始加载的图片
}
});
}, {rootMargin: "0px 0px 200px 0px"});
images.forEach(item => observer.observe(item));