以下是 Parker Bennett 的客座文章,他探讨了处理灵活和响应式图像行为的不同方法。
有时你希望一张图像在调整大小时可以响应式地调整大小,但限制其高度,并在图像变宽时进行裁剪。在本篇文章中,我们将探讨三种具有不同权衡的选项。
background-position: center bottom
。选项一:background-image
在这里,我们使用一个带有 background-image
的 div 来替代 <img>
,并使用 CSS3 的新特性 background-size: cover
来使其按比例缩放。作为奖励,我们可以使用 background-position
很容易地从顶部、中心或底部进行裁剪。
一个潜在的问题是,我们需要为 div
指定一个高度才能显示它。这会赋予它一个固定高度,而这个高度不会按比例缩放(至少在没有 CSS 媒体查询的情况下不会)。当它变得足够窄时,两侧将开始裁剪(这可能是可取的,这取决于情况)。
此外,使用 caniuse.com 进行快速检查表明,这在 IE8 中会显着失败(显示全尺寸图像),但感谢 Louis-Rémi Babé,有一个 background-size 填充 解决方法(尽管它确实需要一个相对位置或固定位置,以及一个 z-index)。IE8 还需要一个 CSS 媒体查询的填充。有 几个 选项。
.bg-image {
/* image specified in separate class below */
height: 240px;
width: 100%;
}
.bg-image-wedding {
background-image: url(img/photo-wedding_1200x800.jpg);
/* lt ie8 */
-ms-background-position-x: center;
-ms-background-position-y: bottom;
background-position: center bottom;
/* scale bg image proportionately */
background-size: cover;
/* ie8 workaround - http://louisremi.github.io/background-size-polyfill/ */
-ms-behavior: url(/backgroundsize.min.htc);
/* prevent scaling past src width (or not) */
/* max-width: 1200px; */
}
/* example media queries */
@media only screen and (min-width : 768px) {
.bg-image { height: 320px; }
}
@media only screen and (min-width : 1200px) {
.bg-image { height: 400px; }
}
background-position: center center
。需要注意的是,background-size: cover
会很容易地将图像放大到超过源图像的原始大小(或者不会,如果你设置了一个 max-width)。*
尽管如此,使用 background-image
还是有一些缺点。它不像 img
那样语义化或模块化,因此维护起来没有那么直接。你似乎只能使用固定高度或繁琐的 CSS 媒体查询。此外,用户无法轻松保存图像(有时这是可取的)。
选项二:img 带有调整
在这里,我们使用一个带有 max-width
设置为包含元素百分比的 img
,使其可以响应式地缩放,然后将其包裹在一个带有 overflow: hidden
和指定高度或 max-height
的 div 中。

.crop-height {
/* max-width: 1200px; /* img src width (if known) */
max-height: 320px;
overflow: hidden;
}
img.scale {
/* corrects inline gap in enclosing div */
display: block;
max-width: 100%;
/* just in case, to force correct aspect ratio */
height: auto !important;
width: auto\9; /* ie8+9 */
/* lt ie8 */
-ms-interpolation-mode: bicubic;
}
如你所见,图像的底部现在会在图像变宽时被裁剪。但是,如果你想从顶部裁剪呢?令人惊讶的是,你可以做到——使用 CSS3 的 transform:rotate()
,我们将 "flip" 类添加到 img.scale
和 div.crop-height
中——将 img 翻转过来。

/* apply to both img.scale and div.crop-height */
.flip {
-webkit-transform: rotate(180deg);
-moz-transform: rotate(180deg);
-ms-transform: rotate(180deg);
-o-transform: rotate(180deg);
transform: rotate(180deg);
/* needed? not sure */
zoom: 1;
}
img.flip {
/* if native or declared width of img.scale
is less than div.crop-height, this will
flipped img left */
float: right;
/* add clearfix if needed */
}
新颖,但仅限于顶部裁剪。而且,如你所料,这 在 IE8 中也不起作用——可能不会显着失败(它只会像以前一样从底部裁剪)。坏消息是,我还没有找到任何 填充 选项 有效,因为它们需要指定高度和宽度。
选项三:混合方法
如果我们可以同时拥有指定 img
的优势(例如,使用 max-height
使我们在低于一定高度时获得按比例的垂直缩放),以及 background-image
提供的灵活裁剪和 IE8 填充支持呢?我们可以!

visibility: hidden
,background-image 的 background-position: center center
。诀窍是使响应式缩放的 img
不可见。使用 visibility: hidden
它会保留布局,因此我们会在它的后面看到 background-image
。(由于它使用的是同一个图像源,因此它不应该需要下载两次)。如果你想让用户可以轻松访问,你可以使用 opacity: 0
代替。现在用户可以拖动图像或右键单击保存。(不透明度和 background-size 需要一些额外的 IE8 解决方法)。

opacity: 0
。一个可以拖动或右键单击保存的 background-image。在 IE8 中有效(借助帮助)。另一个想法是使用一个压缩程度更高的代理 img
,并使用 CSS 媒体查询根据需要提供更高分辨率的 background-image
。这个 img 甚至可以是一个按比例缩小的尺寸(例如,与你的 max-height 相匹配),或带有水印。查看这篇文章 关于媒体查询的 CSS-Tricks 文章,以及这个有用的 用于 Sass 的分辨率 mixin。

img
用于为更高分辨率的 background-image
保留空间。.crop-height {
/* max-width: 1200px; /* img src width (if known) */
max-height: 320px;
overflow: hidden; }
.bg-image-wedding {
/* for small devices */
background-image: url(img/photo-wedding_1200x800.jpg);
/* lt ie8 */
-ms-background-position-x: center;
-ms-background-position-y: bottom;
background-position: center bottom;
/* scale bg image proportionately */
background-size: cover;
/* ie8 workaround - http://louisremi.github.io/background-size-polyfill/ */
-ms-behavior: url(/backgroundsize.min.htc);
*/ prevent scaling past src width (or not) */
/* max-width: 1200px; */ }
.invisible {
visibility: hidden; }
.transparent {
/* trigger hasLayout for IE filters below */
zoom: 1;
/* 0 opacity in filters still displays layout */
-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
filter: alpha(opacity=10);
opacity: 0; }
/* example media query for smaller non-retina devices */
@media
only screen and (max-device-width : 600px) and (-webkit-max-device-pixel-ratio: 1),
only screen and (max-device-width : 600px) and ( max-device-pixel-ratio: 1) {
.bg-image-wedding {
background-image: url(img/photo-wedding_600x400.jpg);
}
}
/* example media query for retina ipad and up */
@media
only screen and (min-device-width : 768px) and (-webkit-min-device-pixel-ratio: 1.5),
only screen and (min-device-width : 768px) and ( min-device-pixel-ratio: 1.5) {
.bg-image-wedding {
background-image: url(img/[email protected]);
}
}
总结
在 CSS3 的 object-fit
支持到来之前,这可能还需要一段时间,这个混合选项在我看来是最好的方法。尽管如此,拥有选择总归是好的。我希望你能从我这次过于详尽的探索中有所收获。你可以查看源代码了解更多信息(选项 一、二 或 三),或者 在这里下载示例文件。如果你有任何问题、评论或更正,请给我留言:parker@parkerbennett.com.
* 如果你想让 img 像 background-image 一样放大,你可以做到。你只需要 "预放大" 它,在 img 元素本身添加一个按比例更大的宽度和高度:<img width="2400px" height="1600px" src="img/photo-wedding_1200x800.jpg />
(在 CodePen 上编辑).
看起来有人要被背景中的东西用棍子打死了 :S
lmfaooo! 观察得真仔细!:)
让我更仔细地观察了这张图像。那里还有其他有趣的人。
真希望看到一秒钟后拍的照片…
嘿,Parker,
很棒的文章!我在我的阅读器中关注这个网站,我非常喜欢它。
关于你的文章
使用
background-size:100%
和background-position:bottom center
会怎么样?< div style=”display:block; width:100%; height:300px; background-image:url(http://cdn.css-tricks.com/wp-content/uploads/2013/06/photo-wedding_1200x800.jpg); background-position:bottom center; background-size:100%;”>
http://jsfiddle.net/gomidefabio/BVXGj/1/
谢谢,Fabio!你可以看到
background-size:100%
在将窗格大小调整为小于图像纵横比时是如何不同的。在你的示例中,图像垂直重复。我们可以添加background-repeat: no-repeat
,但对于位于图像底部的中央,我们会看到图像上方有一个间隙,因为当图像变小时,div 的高度仍然保持 300 像素。使用background-size:cover
,图像会填充该间隙,但会从侧面裁剪。感谢你发布这篇很棒的文章。我正在制作一个作品,你的示例中的一行代码就为我解决了 5 个问题。很棒的文章。
关于 css 的很棒文章,面向前端工程师的优质内容!
有没有简单的方法可以用鼠标平移这张图像(以便看到图像的剩余部分)?
或者,您可以使用填充技巧来保持响应式纵横比并在其中居中图像。
谢谢,Corey!我在 选项一 CodePen 中添加了这个“填充技巧”以进行比较。
问题在于它不会限制图像的高度,而这正是我开始走这条路的方式(我有一个客户想要“在页面折叠之上”的东西)。它的作用很像
max-width:100%
对 img 的作用,除了您可以使用background-position
和不同的padding-bottom
来获得一些裁剪灵活性。^ 这。
您甚至可以在 img 元素本身进行此操作,以避免使用额外的包装 DIV。
那么如何用内联 1x1 像素透明图像替换混合选项中的 img src,以避免在启动时加载 http://parkerbennett.com/croptop/img/photo-wedding_1200x800.jpg 和 http://parkerbennett.com/croptop/img/photo-wedding_600x400.jpg(chrome 加载两个图像)。它可能不是完全语义友好的,但可以减少一个请求。
您可以——而且您可以通过将 1 像素 gif 编码为数据 uri 来完全消除 http 请求
img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"
但是,除了语义不友好和用户不友好之外,它不能通过声明高度和宽度来设置纵横比——随着图像缩小,它会变成一个正方形。我在 选项三 CodePen 中添加了内容来演示这一点。(如果您需要保持纵横比,您可以创建具有匹配纵横比的透明 gif,例如 3 像素乘以 2 像素。)
嗨,Parker,
你说得对。我在发送评论后几秒钟就注意到了。对此表示歉意。因此,我立即创建了一个 JSFIDDLE 测试并将其发布在这里,但由于某种原因,它没有保存代码的最后一个版本。我再次将其放在那里,以防您想查看。但是,该修复程序仅适用于用于这些框的图像保持特定纵横比的情况。
Ps:我不确定您是否希望有人继续用额外的想法(就像我正在做的那样)来填充您的评论区域,但我只是喜欢与您的帖子相关的这个问题,所以我想看看我自己会怎么做。也许有人可以改进我给出的解决方案。
http://jsfiddle.net/gomidefabio/BVXGj/15/
嘿,这很棒,Fabio——这正是我希望得到的思想交流!
总结一下,Fabio 建议对选项一进行改进:当图像宽度与声明的高度成比例时,使用媒体查询将高度切换为自动。现在,图像将继续按比例缩小。聪明!
啊。我应该澄清一下,Fabio。您的方法有效,但它基本上是在复制
max-height:500px
的作用,而不需要媒体查询。这就是使用透明占位符 img 的优势——它提供了我们原本需要为背景图像显示而指定的 height,我们可以用 min-width、max-width、min-height 或 max-height 来限制它。很棒的文章 Chris——它出现在恰当的时候,因为我正在做类似的事情。我承认,我将使用这段代码,但会给予应得的赞誉 :-)
嘿,我忘了提到您可以使用百分比来微调使用
background-position
的裁剪,例如background-position: 30% 60%
。我修改了 选项三 CodePen 来演示。哦,天哪!非常感谢这篇文章!它节省了我大量工作。
background-size:cover
属性很棒。再次感谢!