如何使用 flexbox 和 object-fit 属性 强制图像覆盖布局单元的尺寸?
How to force images to cover the dimensions of a layout unit using flexbox and the object-fit property?
我正在开发响应式图库布局,其中所有图像都应覆盖其容器的尺寸。为了保持每个图像的纵横比,我想我可以使用相当新的 CSS 属性 object-fit
。
实施的解决方案使用 flexbox
模块强制画廊的每一列高度相等。每列中的单元格都被拉伸以适合其父级的总和高度。每个单元格的实际高度由flexbox
模块使用flex: 1 0 auto
确定,不一定相同。
这是我的问题:每个单元格中包含的图像现在应该与其容器的尺寸相匹配(使用 object-fit: cover; width: 100%; height: 100%
)。在 Firefox 和 Internet Explorer(使用 object-fit
polyfill)中,这些样式会产生预期的布局,但在 Chrome 或 Safari 等 webkit 浏览器中则不会。在这些浏览器中,每个单元格的尺寸都是正确的,但图像的尺寸不是。
我找不到相关的错误报告,也找不到解决我的问题的灵活方法。我希望有人能帮助我,因为我目前 运行 没有想法。
已在最新版本的 Chrome、Safari、Firefox 以及 IE 10 和 11
中进行测试
// Object Fit Polyfill
// @see <https://github.com/bfred-it/object-fit-images>
objectFitImages();
/* Reset */
body {
font: 100%/26px Lato, sans-serif;
padding: 5%;
}
figure {
margin: 0;
}
blockquote {
margin-left: 0;
}
img {
vertical-align: middle;
max-width: 100%;
height: auto;
font-style: italic;
}
/* Gallery */
.c-gallery {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-flow: wrap row;
-ms-flex-flow: wrap row;
flex-flow: wrap row;
-webkit-box-pack: justify;
-webkit-justify-content: space-between;
-ms-flex-pack: justify;
justify-content: space-between;
}
.c-gallery__column {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-flow: wrap column;
-ms-flex-flow: wrap column;
flex-flow: wrap column;
-webkit-box-flex: 1;
-webkit-flex: 1 0 33%;
-ms-flex: 1 0 33%;
flex: 1 0 33%;
}
.c-gallery__item {
-webkit-box-flex: 1;
-webkit-flex: 1 0 auto;
-ms-flex: 1 0 auto;
flex: 1 0 auto;
}
.c-gallery__item img {
width: 100%;
height: 100%;
-o-object-fit: cover;
object-fit: cover;
}
<div class="c-gallery">
<div class="c-gallery__column">
<figure class="c-gallery__item">
<a href="#"><img src="http://placehold.it/640x1080" alt="Product A" /></a>
</figure>
</div>
<div class="c-gallery__column">
<div class="c-gallery__item">
<figure>
<blockquote>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Officiis architecto voluptatum numquam totam quos neque incidunt!</p>
</blockquote>
<figcaption>
<cite>John Doe</cite>
</figcaption>
</figure>
</div>
<figure class="c-gallery__item">
<img src="http://placehold.it/640x720" alt="John Doe" />
</figure>
</div>
<div class="c-gallery__column">
<figure class="c-gallery__item">
<a href="#"><img src="http://placehold.it/640x360" alt="Product B" /></a>
</figure>
<figure class="c-gallery__item">
<a href="#"><img src="http://placehold.it/640x360" alt="Product C" /></a>
</figure>
<figure class="c-gallery__item">
<a href="#"><img src="http://placehold.it/640x360" alt="Product D" /></a>
</figure>
</div>
</div>
<script src="http://bfred-it.github.io/object-fit-images/dist/ofi.browser.js"></script>
如果你更喜欢 CodePen,我创建了一个我正在做的演示:
变化
- 删除了适合对象的多边形
- 按照现代标准清理 flexbox 属性
- 删除了所有 img,来自网站的图像,例如具有固定尺寸的占位符宿主图像,因此它们不会拉伸。
- 在每个
<figure>
上使用 background
shorthand,具有以下属性:
background-image
background-repeat
background-position
- 每个图都用了
background-size: cover
,效果和object-fit: cover
一样。有关背景缩放的详细信息,请参阅此 article
- 使用此模式设置每个弹性列的弹性项目尺寸:
- 最小宽度:Xvw;
- 最大宽度:Xem;
- 最小宽度:Yvh;
- 最大高度:是的;
vw
and vh
are viewport units.
em
测量值基于从原始 <img>
观察到的尺寸
flex-wrap: [row/column] [wrap/nowrap]
是正确的语法
- 您需要在此网格布局中
nowrap
。如果由于某种原因超出了 flexboxes 的限制,wrap
会扭曲布局,盒子相互堆叠。有关 flexbox 的 当前 详细信息,请阅读此 article
- 在
<figure>
中放置了 <a>
锚点,并在锚点中设置了 <div>
以在 <figure>
中从边到边传播它。这很丑陋,可能有更好的方法。查看源代码并查找 .space
类 了解详细信息。
支持
IE sux,它有很多问题,所以请保持简单。
完全支持,除非您的客户使用 opera-mini(不到 .1% 的用户?)
这个演示总体上看起来非常兼容,所以希望不需要多边形。
它并不完美,但我认为您可以自己调整其余部分的长度、边距等。
CODEPEN
我找到了适合我的解决方案。问题似乎是锚元素上缺少尺寸。虽然我试图绝对定位链接以强制它们覆盖它们的容器,但我应该更彻底地尝试将它们设置为 flexbox
-container。我的解决方案包括以下添加内容:
- 强制锚元素也充当
flexbox
容器,就像画廊项目一样。
- 强制每个图库项目使用其父列高度的
100%
。 flex-module 将计算用于元素的实际高度,并允许项目根据需要增大或缩小 (flex: 1 1 auto
)。
- 使用 flex 模块(使用
flex: 1 1 auto;
)拉伸每个图像元素以覆盖其容器的尺寸。 object-fit
语句将确保纵横比保持不变。
- 新的 css class 允许
blockquote
-容器使用内容所需的 space(flex-shrink: 0; flex-grow: 0; height: auto;
)。
生成的布局正是我想要的——至少在 Chrome、Firefox 和 IE10+ 中是这样。不幸的是,在 Safari 中,结果有点不同。在 Safari 中,blockquote
元素及其内容决定了整个画廊的高度。结果,每列的高度在每个子项之间进行划分,从而产生小的缩略图。我认为原因是,没有元素具有明确的高度和基于百分比的高度在这里不起作用(虽然想知道为什么它适用于其他浏览器)。适用于我的用例的修复是在图库容器上应用 min-height
。
这里是当前的解决方案:
// Object Fit Polyfill
// @see <https://github.com/bfred-it/object-fit-images>
objectFitImages();
/* #Base:Reset */
body {
font: 100%/26px Lato, sans-serif;
padding: 5%;
}
figure {
margin: 0;
}
blockquote {
margin-left: 0;
}
img {
vertical-align: middle;
max-width: 100%;
height: auto;
font-style: italic;
}
/* #Component:Gallery */
.c-gallery {
display: flex;
flex-flow: row nowrap;
justify-content: space-between;
min-height: 100vh; /* Prevents collapsing items in Safari */
max-height: 1080px;
}
.c-gallery__column {
display: flex;
flex-flow: column nowrap;
flex: 1 1 auto;
width: 33.33333%;
}
.c-gallery__item,
.c-gallery__item > a {
display: flex;
flex-flow: column nowrap;
flex: 1 1 auto;
height: 100%;
}
.c-gallery__item--fit-content {
flex-grow: 0;
flex-shrink: 0;
height: auto;
}
.c-gallery__item img {
flex: 1 1 auto;
width: 100%;
max-width: none;
height: 100%;
object-fit: cover;
}
<div class="c-gallery">
<div class="c-gallery__column">
<figure class="c-gallery__item">
<a href="#"><img src="http://placehold.it/640x1080" alt="Product A" /></a>
</figure>
</div>
<div class="c-gallery__column">
<div class="c-gallery__item c-gallery__item--fit-content">
<figure>
<blockquote>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Officiis architecto voluptatum numquam totam quos neque incidunt!</p>
</blockquote>
<figcaption>
<cite>John Doe</cite>
</figcaption>
</figure>
</div>
<figure class="c-gallery__item">
<a href="#"><img src="http://placehold.it/640x720" alt="John Doe" /></a>
</figure>
</div>
<div class="c-gallery__column">
<figure class="c-gallery__item">
<a href="#"><img src="http://placehold.it/640x360" alt="Product B" /></a>
</figure>
<figure class="c-gallery__item">
<a href="#"><img src="http://placehold.it/640x360" alt="Product C" /></a>
</figure>
<figure class="c-gallery__item">
<a href="#"><img src="http://placehold.it/640x360" alt="Product D" /></a>
</figure>
</div>
</div>
<script src="http://bfred-it.github.io/object-fit-images/dist/ofi.browser.js"></script>
您可以在 CodePen
上再次看到原始演示的分支
注意:我在回答中遗漏了供应商前缀,运行 如果您使用不支持 flexbox 的浏览器。
我正在开发响应式图库布局,其中所有图像都应覆盖其容器的尺寸。为了保持每个图像的纵横比,我想我可以使用相当新的 CSS 属性 object-fit
。
实施的解决方案使用 flexbox
模块强制画廊的每一列高度相等。每列中的单元格都被拉伸以适合其父级的总和高度。每个单元格的实际高度由flexbox
模块使用flex: 1 0 auto
确定,不一定相同。
这是我的问题:每个单元格中包含的图像现在应该与其容器的尺寸相匹配(使用 object-fit: cover; width: 100%; height: 100%
)。在 Firefox 和 Internet Explorer(使用 object-fit
polyfill)中,这些样式会产生预期的布局,但在 Chrome 或 Safari 等 webkit 浏览器中则不会。在这些浏览器中,每个单元格的尺寸都是正确的,但图像的尺寸不是。
我找不到相关的错误报告,也找不到解决我的问题的灵活方法。我希望有人能帮助我,因为我目前 运行 没有想法。
已在最新版本的 Chrome、Safari、Firefox 以及 IE 10 和 11
中进行测试// Object Fit Polyfill
// @see <https://github.com/bfred-it/object-fit-images>
objectFitImages();
/* Reset */
body {
font: 100%/26px Lato, sans-serif;
padding: 5%;
}
figure {
margin: 0;
}
blockquote {
margin-left: 0;
}
img {
vertical-align: middle;
max-width: 100%;
height: auto;
font-style: italic;
}
/* Gallery */
.c-gallery {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-flow: wrap row;
-ms-flex-flow: wrap row;
flex-flow: wrap row;
-webkit-box-pack: justify;
-webkit-justify-content: space-between;
-ms-flex-pack: justify;
justify-content: space-between;
}
.c-gallery__column {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-flow: wrap column;
-ms-flex-flow: wrap column;
flex-flow: wrap column;
-webkit-box-flex: 1;
-webkit-flex: 1 0 33%;
-ms-flex: 1 0 33%;
flex: 1 0 33%;
}
.c-gallery__item {
-webkit-box-flex: 1;
-webkit-flex: 1 0 auto;
-ms-flex: 1 0 auto;
flex: 1 0 auto;
}
.c-gallery__item img {
width: 100%;
height: 100%;
-o-object-fit: cover;
object-fit: cover;
}
<div class="c-gallery">
<div class="c-gallery__column">
<figure class="c-gallery__item">
<a href="#"><img src="http://placehold.it/640x1080" alt="Product A" /></a>
</figure>
</div>
<div class="c-gallery__column">
<div class="c-gallery__item">
<figure>
<blockquote>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Officiis architecto voluptatum numquam totam quos neque incidunt!</p>
</blockquote>
<figcaption>
<cite>John Doe</cite>
</figcaption>
</figure>
</div>
<figure class="c-gallery__item">
<img src="http://placehold.it/640x720" alt="John Doe" />
</figure>
</div>
<div class="c-gallery__column">
<figure class="c-gallery__item">
<a href="#"><img src="http://placehold.it/640x360" alt="Product B" /></a>
</figure>
<figure class="c-gallery__item">
<a href="#"><img src="http://placehold.it/640x360" alt="Product C" /></a>
</figure>
<figure class="c-gallery__item">
<a href="#"><img src="http://placehold.it/640x360" alt="Product D" /></a>
</figure>
</div>
</div>
<script src="http://bfred-it.github.io/object-fit-images/dist/ofi.browser.js"></script>
如果你更喜欢 CodePen,我创建了一个我正在做的演示:
变化
- 删除了适合对象的多边形
- 按照现代标准清理 flexbox 属性
- 删除了所有 img,来自网站的图像,例如具有固定尺寸的占位符宿主图像,因此它们不会拉伸。
- 在每个
<figure>
上使用background
shorthand,具有以下属性:background-image
background-repeat
background-position
- 每个图都用了
background-size: cover
,效果和object-fit: cover
一样。有关背景缩放的详细信息,请参阅此 article - 使用此模式设置每个弹性列的弹性项目尺寸:
- 最小宽度:Xvw;
- 最大宽度:Xem;
- 最小宽度:Yvh;
- 最大高度:是的;
vw
andvh
are viewport units.em
测量值基于从原始<img>
观察到的尺寸
flex-wrap: [row/column] [wrap/nowrap]
是正确的语法- 您需要在此网格布局中
nowrap
。如果由于某种原因超出了 flexboxes 的限制,wrap
会扭曲布局,盒子相互堆叠。有关 flexbox 的 当前 详细信息,请阅读此 article
- 您需要在此网格布局中
- 在
<figure>
中放置了<a>
锚点,并在锚点中设置了<div>
以在<figure>
中从边到边传播它。这很丑陋,可能有更好的方法。查看源代码并查找.space
类 了解详细信息。
支持
IE sux,它有很多问题,所以请保持简单。
完全支持,除非您的客户使用 opera-mini(不到 .1% 的用户?)
这个演示总体上看起来非常兼容,所以希望不需要多边形。 它并不完美,但我认为您可以自己调整其余部分的长度、边距等。
CODEPEN
我找到了适合我的解决方案。问题似乎是锚元素上缺少尺寸。虽然我试图绝对定位链接以强制它们覆盖它们的容器,但我应该更彻底地尝试将它们设置为 flexbox
-container。我的解决方案包括以下添加内容:
- 强制锚元素也充当
flexbox
容器,就像画廊项目一样。 - 强制每个图库项目使用其父列高度的
100%
。 flex-module 将计算用于元素的实际高度,并允许项目根据需要增大或缩小 (flex: 1 1 auto
)。 - 使用 flex 模块(使用
flex: 1 1 auto;
)拉伸每个图像元素以覆盖其容器的尺寸。object-fit
语句将确保纵横比保持不变。 - 新的 css class 允许
blockquote
-容器使用内容所需的 space(flex-shrink: 0; flex-grow: 0; height: auto;
)。
生成的布局正是我想要的——至少在 Chrome、Firefox 和 IE10+ 中是这样。不幸的是,在 Safari 中,结果有点不同。在 Safari 中,blockquote
元素及其内容决定了整个画廊的高度。结果,每列的高度在每个子项之间进行划分,从而产生小的缩略图。我认为原因是,没有元素具有明确的高度和基于百分比的高度在这里不起作用(虽然想知道为什么它适用于其他浏览器)。适用于我的用例的修复是在图库容器上应用 min-height
。
这里是当前的解决方案:
// Object Fit Polyfill
// @see <https://github.com/bfred-it/object-fit-images>
objectFitImages();
/* #Base:Reset */
body {
font: 100%/26px Lato, sans-serif;
padding: 5%;
}
figure {
margin: 0;
}
blockquote {
margin-left: 0;
}
img {
vertical-align: middle;
max-width: 100%;
height: auto;
font-style: italic;
}
/* #Component:Gallery */
.c-gallery {
display: flex;
flex-flow: row nowrap;
justify-content: space-between;
min-height: 100vh; /* Prevents collapsing items in Safari */
max-height: 1080px;
}
.c-gallery__column {
display: flex;
flex-flow: column nowrap;
flex: 1 1 auto;
width: 33.33333%;
}
.c-gallery__item,
.c-gallery__item > a {
display: flex;
flex-flow: column nowrap;
flex: 1 1 auto;
height: 100%;
}
.c-gallery__item--fit-content {
flex-grow: 0;
flex-shrink: 0;
height: auto;
}
.c-gallery__item img {
flex: 1 1 auto;
width: 100%;
max-width: none;
height: 100%;
object-fit: cover;
}
<div class="c-gallery">
<div class="c-gallery__column">
<figure class="c-gallery__item">
<a href="#"><img src="http://placehold.it/640x1080" alt="Product A" /></a>
</figure>
</div>
<div class="c-gallery__column">
<div class="c-gallery__item c-gallery__item--fit-content">
<figure>
<blockquote>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Officiis architecto voluptatum numquam totam quos neque incidunt!</p>
</blockquote>
<figcaption>
<cite>John Doe</cite>
</figcaption>
</figure>
</div>
<figure class="c-gallery__item">
<a href="#"><img src="http://placehold.it/640x720" alt="John Doe" /></a>
</figure>
</div>
<div class="c-gallery__column">
<figure class="c-gallery__item">
<a href="#"><img src="http://placehold.it/640x360" alt="Product B" /></a>
</figure>
<figure class="c-gallery__item">
<a href="#"><img src="http://placehold.it/640x360" alt="Product C" /></a>
</figure>
<figure class="c-gallery__item">
<a href="#"><img src="http://placehold.it/640x360" alt="Product D" /></a>
</figure>
</div>
</div>
<script src="http://bfred-it.github.io/object-fit-images/dist/ofi.browser.js"></script>
您可以在 CodePen
上再次看到原始演示的分支注意:我在回答中遗漏了供应商前缀,运行 如果您使用不支持 flexbox 的浏览器。