img
标签使用 srcset
属性是实现响应式图片的好方法。是否有等效的语法可以在 CSS 的 background-image
属性中使用?
HTML
<img src="small.jpg" srcset="medium.jpg 1000w, large.jpg 2000w" alt="yah">
CSS
.mycontainer {
background: url('what goes here?');
}
img
标签使用 srcset
属性是实现响应式图片的好方法。是否有等效的语法可以在 CSS 的 background-image
属性中使用?
HTML
<img src="small.jpg" srcset="medium.jpg 1000w, large.jpg 2000w" alt="yah">
CSS
.mycontainer {
background: url('what goes here?');
}
image-set
是CSS的一个功能,表示根据不同的设备像素比选择不同的图像。我们应该在规范中添加类似的功能(根据资源的尺寸定义资源)。
目前所有主流浏览器(Firefox,Chrome,Safari,Edge)都已经实现,但需要使用 -webkit-
前缀。Safari仅支持 x
描述符。
另一个更为可靠的方法是,将背景图像的特性和选项适应具有srcset属性的图像。
要实现这一点,将图像设置为宽度:100%;高度:100%;并且object-fit:cover或contain。
以下是示例:
.pseudo-background-img-container {
position: relative;
width:400px;
height: 200px;
}
.pseudo-background-img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: cover;
}
<div class="pseudo-background-img-container">
<img class="pseudo-background-img" src="https://cdn3.tnwcdn.com/wp-content/blogs.dir/1/files/2016/12/Keep.jpg" srcset="https://cdn0.tnwcdn.com/wp-content/blogs.dir/1/files/2016/12/Keep.jpg 640w, https://cdn0.tnwcdn.com/wp-content/blogs.dir/1/files/2016/12/Keep-280x175.jpg 280w, https://cdn0.tnwcdn.com/wp-content/blogs.dir/1/files/2016/12/Keep-432x270.jpg 432w, https://cdn0.tnwcdn.com/wp-content/blogs.dir/1/files/2016/12/Keep-216x135.jpg 216w" sizes="(max-width: 640px) 100vw, 640px">
</div>
这可能不适合所有人,但我想它将在没有任何JavaScript解决方法的情况下获得大多数所需的结果。
object-fit: cover;
的存在,谢谢。对我来说,这是使我的代码工作的最后一步(我正在使用 <picture>
标签)。 - Gendrith我很确定:
background: -webkit-image-set( url('path/to/image') 1x, url('path/to/high-res-image') 2x );
这个过程是一样的。浏览器会检查图片,选择最适合的并使用它。
您可以使用媒体查询来实现您的目的。它很简单,只需这样:
.mycontainer {
background-image:url("img/image-big.jpg"); // big image
}
@media(max-width: 768px){
.mycontainer {
background-image:url("img/image-sm.jpg"); // small image
}
}
我认为它可以在支持媒体查询的每个浏览器上运行;)
如果需要一个polyfill,您可以使用具有srcset属性的img作为下载正确图片尺寸的机制,然后使用JS隐藏它并设置其父元素的background-image。
这里有一个例子: http://jsbin.com/garetikubu/edit?html,output
使用onload
和将JS作为阻止脚本放置在<head>
中非常重要。如果您将脚本放置得太晚(例如放在<body>
的末尾),则可能会出现竞争条件,其中img.currentSrc尚未由浏览器设置。最好等待它被加载。
该示例允许您查看原始img的下载过程。您可以使用一些CSS轻松隐藏它。
根据CSSTricks的说法,从2021年开始应该使用image-set()
来实现这个目的。
以下是它推荐的支持所有现代浏览器版本的完整代码片段:
.hero {
/* Fallback */
background-image: url("platypus.png");
/* Chrome/Edge/Opera/Samsung, Safari will fallback to this as well */
background-image: -webkit-image-set(url("platypus.png") 1x, url("platypus-2x.png") 2x);
/* Standard use */
background-image: image-set(url("platypus.png") 1x, url("platypus-2x.png") 2x);
}
使用<picture>
元素的类似解决方案:这里是教程
教程示例:
我有疑问,如果我在较小的屏幕上使用同一张图片,我的图片的主要内容可能会变得太小。我想在不同的屏幕尺寸下显示不同的图片(更加聚焦于主要内容),但我仍然想根据设备像素比显示相同图像的不同资源,并且我想根据视口自定义图像的高度和宽度。
示例代码:
<picture>
<source media="(max-width: 20em)" srcset="images/small/space-needle.jpg 1x,
images/small/space-needle-2x.jpg 2x, images/small/space-needle-hd.jpg 3x">
<source media="(max-width: 40em)" srcset="images/medium/space-needle.jpg 1x,
images/medium/space-needle-2x.jpg 2x, images/medium/space-needle-hd.jpg 3x">
<img src="space-needle.jpg" alt="Space Needle">
</picture>
<div data-interchange="[assets/img/interchange/small.jpg, small],
[assets/img/interchange/medium.jpg, medium],
[assets/img/interchange/large.jpg, large]">
</div>
https://foundation.zurb.com/sites/docs/interchange.html#use-with-background-images
responsive-loader
很好地连接起来,得到了一个非常棒的解决方案。 - fredrivett我曾经使用过Lazysizes插件中的bg-set功能来为背景图片添加响应式。它与srcset类似,根据设备宽度提供一组多个背景图片。
<div class="lazyload" data-bgset="image-200.jpg 200w, image-300.jpg 300w, image-400.jpg 400w" data-sizes="auto">
数据背景集中的图像是相同的,我们只提供指定宽度的图像,让浏览器可以选择使用。
根据@Weston的答案,我建立了一个更通用的jQuery解决方案,你可以基本上只需复制并粘贴JS和CSS,并专注于HTML部分 ;)
...以确保在加载时图像几乎不可见
.srcSet{
position: fixed;
z-index: 0;
z-index: -1;
z-index: -100;
/* you could probably also add visibility: hidden; */
}
此脚本将遍历所有具有srcSet
类的图像,并绑定load
事件,该事件将以currentSrc
(如果不支持,则为src
)并将其作为background-image
CSS放置在最接近的父元素中,该父元素具有bgFromSrcSet
类。
但这还不够!因此,它还在window
load
事件上放置了一个间隔检查器,以测试是否已完成加载事件,如果没有,则触发它们。(img
load
事件通常仅在第一次加载时触发,在后续加载中,图像源可以从缓存中检索,导致img load事件未被触发!)
jQuery(function($){ //ON DOCUMENT READY
var $window = $(window); //prepare window as jQuery object
var $srcSets = $('.srcSet'); //get all images with srcSet clas
$srcSets.each(function(){ //for each .srcSet do...
var $currImg = $(this); //prepare current srcSet as jQuery object
$currImg
.load(function(){ //bind the load event
var img = $currImg.get(0); //retrieve DOM element from $currImg
//test currentSrc support, if not supported, use the old src
var src = img.currentSrc ? img.currentSrc : img.src;
//To the closest parent with bgFromSrcSet class,
//set the final src as a background-image CSS
$currImg.closest('.bgFromSrcSet').css('background-image', "url('"+src+"')");
//remove processed image from the jQuery set
//(to update $srcSets.length that is checked in the loadChecker)
$srcSets = $srcSets.not($currImg);
$currImg.remove(); //remove the <img ...> itself
})
;
});
//window's load event is called even on following loads...
$window.load(function(){
//prepare the checker
var loadChecker = setInterval(function(){
if( $srcSets.length > 0 ) //if there is still work to do...
$srcSets.load(); //...do it!
else
clearInterval(loadChecker); //if there is nothing to do - stop the checker
}, 150);
});
});
...可能看起来像这样:
<div class="bgFromSrcSet">
<img class="srcSet"
alt=""
src="http://example.com/something.jpeg"
srcset="http://example.com/something.jpeg 5760w, http://example.com/something-300x200.jpeg 300w, http://example.com/something-768x512.jpeg 768w, http://example.com/something-1024x683.jpeg 1024w, http://example.com/something-1000x667.jpeg 1000w"
sizes="(max-width: 2000px) 100vw, 2000px"
>
Something else...
</div>
注意:类 bgFromSrcSet
不应该被设置在 img
元素本身上!它只能被设置在 img
DOM 父级树中的元素上。
image-set()
调用的那一行之前指定background-image: url("");
。@O.MeeKoh - quinqui