问题:不同长宽的div中放大小不定的图片(比例不能扭曲),需要默认使用同一个png透明默认图片,加上自定义的背景色#e1e2e4,等之后渲染真实图片时,再替换。因为项目图片需要懒加载,图片只能放在img中。
我第一反应是外面套个flex,然后双向居中就完事,但是这样图片会产生留白。就算把max-height换成max-width,更宽的图片又会产生上下留白。
.lazy-div{
width: 不一;
height: 不一;
background: #e1e2e4;
display: flex;
overflow: hidden;
align-items: center;
justify-content: center;
}
.lazy-div img{
max-height: 100%;
}
<div class="lazy-div">
<img src="默认图片" lay-src="真实图片"/>
</div>
// js部分
<div class="lazy-div">
<img src="真实图片" onerror="this.src='默认图片'"/>
</div>
然后使用第二个方法:
.lazy-div{
width: 不一;
height: 不一;
background: #e1e2e4;
position: relative;
overflow: hidden;
}
.lazy-div img{
max-height: 100%;
transform: translate(-50%,-50%);
position: absolute;
top: 50%;
left: 50%;
}
<div class="lazy-div">
<img src="默认图片" lay-src="真实图片"/>
</div>
// ajax加载部分
<div class="lazy-div">
<img src="真实图片" onerror="this.src='默认图片'"/>
</div>
还是同样的老问题。
第三个方法,使用object-fit: cover,但这样的问题就变成了:默认图片比div更小,然后会撑大变得很糊。
所以,默认图片比div小,真实图片又比div大的情况下,感觉似乎没有两全的方法。
后来实在是觉得留白太难看了,又冒出第四个想法:默认图片放到div当background,真实图片放img填充遮盖,于是两全的方法出来了。
.lazy-div{
overflow: hidden;
background-image: url(默认图片);
background-size: contain;
background-position: center center;
background-repeat: no-repeat;
background-color: #e1e2e4;
}
.lazy-div img{
width: 不一;
height: 不一;
object-fit: cover;
}
<div class="lazy-div">
<img lay-src="真实图片"/>
</div>
// ajax加载部分
<div class="lazy-div">
<img src="真实图片" onerror="this.src='';onerror=null"/>
</div>
结果方法四还是存在一种问题:当真实图片也是png透明时……它的弊端就出现了。
为了解决png透明图问题,最终选择方法五:
重点从lazy-div转移到img(img的宽高固定),html里改写了layui的lay-src方法比较方便。但js方面问题就比较多了,首先onerror会出现图片破裂小图标,之前用
img[src=""],img:not([src]){
opacity:0;
}
的方式行不通了,因为默认背景图也会被隐藏,所以得加一张1像素的透明图进行错误替换。但图片没发生错误时,真实图片含有透明png又会与默认图片重叠,所以加载成功时又必须隐藏默认图片。
.lazy-div{
overflow: hidden;
}
.lazy-div img{
object-fit: cover;
background-image: 默认图片;
background-position: center center;
background-repeat: no-repeat;
background-color: #e1e2e4;
background-size: contain;
}
<div class="lazy-div">
<img lay-src="真实图片"/>
</div>
// ajax加载部分
<div class="lazy-div">
<img src="真实图片" onerror="this.src=1px透明图;onload=null;onerror=null" onload="this.style='background:none'" />
</div>