使用flexbox并保持纵横比,即使内容的大小不同。

17

在SO上有很多关于保持元素宽高比(使用flexbox或不使用)的问题。然而,我的问题略有不同,因为我想覆盖子图像元素的宽高比:

  1. 确保图像完全覆盖元素(object-fit: cover
  2. 确保元素是1:1的(即一个完美的圆形)
  3. 确保溢出的图像被隐藏

换句话说,图像必须表现得就像它是一个元素的背景一样(尽管我不能将它们用作背景图像),该元素的宽高比始终为1:1并且具有响应性。

在下面的示例中,除了元素根据它们的图像后代进行调整之外,一切都很正常。但是我希望它们保持1:1的比例,这样我就可以得到完美的圆形。(第一行的中间元素必须比其他元素大。)

HTML不能更改,但我可以使用现代CSS属性,例如object-fit和flexbox。(只要Chrome / Firefox的最新版本支持它。)

*,
*::before,
*::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.img-gallery {
  background: #fafafa;
  padding: 24px;
  min-width: 320px;
  width: 90%;
  margin: 0 auto;
}

.img-gallery .row {
  display: flex;
  flex-wrap: nowrap;
  justify-content: space-around;
  align-items: center;
}

.img-gallery a {
  display: block;
  text-decoration: none;
  background-image: linear-gradient(60deg, #004494 0%, #7db9e8 78%, #c2dfed 100%);
  overflow: hidden;
  border-radius: 50%;
  padding: 3px;
  flex: 1;
  margin: 0 24px;
  transition: padding 200ms;
}

.img-gallery a:hover,
#s_country .img-gallery .row:first-of-type a:nth-child(2):hover {
  padding: 0;
}

.img-gallery a:hover span {
  transform: scale(1.25);
}

.img-gallery .row:first-of-type a:not(:nth-child(2)) {
  width: 30%;
  width: calc((60% - 96px) / 2);
}

.img-gallery .row:first-of-type a:nth-child(2) {
  flex: 2;
  padding: 4px;
}

.img-gallery span {
  width: 100%;
  height: 100%;
  display: block;
  border-radius: 50%;
  position: relative;
  overflow: hidden;
  transition: transform 250ms;
  z-index: 2;
}

.img-gallery img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.img-gallery span::before {
  content: "";
  background-image: linear-gradient(60deg, transparent 48%, #ffc5e7 100%);
  width: 100%;
  height: 100%;
  position: absolute;
  z-index: 2;
  border-radius: 50%;
  opacity: .72;
}
<div class="img-gallery">
  <div class="row">
    <a href="#" title="Show large image"><span><img itemprop="image" src="https://s-media-cache-ak0.pinimg.com/originals/b3/9c/54/b39c54776074d07ee0b567826768730a.jpg" id="img-1-3"></span></a>
    <a href="#" title="Show large image"><span><img itemprop="image" src="https://s-media-cache-ak0.pinimg.com/originals/d6/df/51/d6df512a2f15f517767b4d82d2d97a4c.jpg" id="img-1-4"></span></a>
    <a href="#" title="Show large image"><span><img itemprop="image" src="https://s-media-cache-ak0.pinimg.com/originals/ec/a9/dd/eca9dd106a04cdbee399870252ef711f.jpg" id="img-1-5"></span></a>
  </div>
  <div class="row">
    <a href="#" title="Show large image"><span><img itemprop="image" src="https://s-media-cache-ak0.pinimg.com/originals/7d/01/19/7d0119a2fec989e208f288326c7cad0f.jpg" id="img-1-6"></span></a>
    <a href="#" title="Show large image"><span><img itemprop="image" src="https://s-media-cache-ak0.pinimg.com/originals/d8/c3/32/d8c332d09b03673845b2e92a48816233.jpg" id="img-1-7"></span></a>
    <a href="#" title="Show large image"><span><img itemprop="image" src="https://s-media-cache-ak0.pinimg.com/originals/88/3b/dd/883bddab14168f5f0807fec021002d8d.jpg" id="img-1-8"></span></a>
  </div>
  <div class="row">
    <a href="#" title="Show large image"><span><img itemprop="image" src="https://s-media-cache-ak0.pinimg.com/originals/8e/4f/bb/8e4fbb89b155d15521b80d1baf9290d1.jpg" id="img-1-9"></span></a>
  </div>
</div>

演示 Terry 的代码不能正常工作的示例:风景图片。

*,
*::before,
*::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.img-gallery {
  background: #fafafa;
  padding: 24px;
  min-width: 320px;
  width: 90%;
  margin: 0 auto;
}

.img-gallery .row {
  display: flex;
  flex-wrap: nowrap;
  justify-content: space-around;
  align-items: center;
}

.img-gallery a {
  display: block;
  text-decoration: none;
  background-image: linear-gradient(60deg, #004494 0%, #7db9e8 78%, #c2dfed 100%);
  overflow: hidden;
  border-radius: 50%;
  padding: 3px;
  flex: 1;
  margin: 0 24px;
  transition: padding 200ms;
}

.img-gallery .row:first-of-type a:not(:nth-child(2)) {
  width: 30%;
  width: calc((60% - 96px) / 2);
}

.img-gallery .row:first-of-type a:nth-child(2) {
  flex: 2;
  padding: 4px;
}

.img-gallery span {
  height: 0;
  display: block;
  border-radius: 50%;
  position: relative;
  padding-bottom: 100%;
  overflow: hidden;
  transition: transform 250ms;
  z-index: 2;
}

.img-gallery img {
  width: 100%;
  object-fit: cover;
  transition: transform 250ms;
}

.img-gallery a:hover img {
  transform: scale(1.25);
}

.img-gallery span::before {
  content: "";
  background-image: linear-gradient(60deg, transparent 48%, #ffc5e7 100%);
  width: 100%;
  height: 100%;
  position: absolute;
  z-index: 2;
  border-radius: 50%;
  opacity: .72;
}
<div class="img-gallery">
  <div class="row">
    <a href="#" title="Show large image"><span><img itemprop="image" src="https://s-media-cache-ak0.pinimg.com/originals/b3/9c/54/b39c54776074d07ee0b567826768730a.jpg" id="img-1-3"></span></a>
    <a href="#" title="Show large image"><span><img itemprop="image" src="https://s-media-cache-ak0.pinimg.com/originals/d6/df/51/d6df512a2f15f517767b4d82d2d97a4c.jpg" id="img-1-4"></span></a>
    <a href="#" title="Show large image"><span><img itemprop="image" src="https://s-media-cache-ak0.pinimg.com/originals/ec/a9/dd/eca9dd106a04cdbee399870252ef711f.jpg" id="img-1-5"></span></a>
  </div>
  <div class="row">
    <a href="#" title="Show large image"><span><img itemprop="image" src="https://s-media-cache-ak0.pinimg.com/originals/7d/01/19/7d0119a2fec989e208f288326c7cad0f.jpg" id="img-1-6"></span></a>
    <a href="#" title="Show large image"><span><img itemprop="image" src="https://s-media-cache-ak0.pinimg.com/originals/d8/c3/32/d8c332d09b03673845b2e92a48816233.jpg" id="img-1-7"></span></a>
    <a href="#" title="Show large image"><span><img itemprop="image" src="https://s-media-cache-ak0.pinimg.com/originals/13/7c/3d/137c3d3bd9f25aa9d2677136d9336d74.jpg" id="img-1-8"></span></a>
  </div>
  <div class="row">
    <a href="#" title="Show large image"><span><img itemprop="image" src="https://s-media-cache-ak0.pinimg.com/originals/8e/4f/bb/8e4fbb89b155d15521b80d1baf9290d1.jpg" id="img-1-9"></span></a>
  </div>
</div>


所有的图片都是竖屏模式吗?(即高度>宽度) - vals
1
@vals 不,尺寸无法提前知道。 - Bram Vanroy
2个回答

15
为了保持响应元素的纵横比,您可以使用填充技术
请注意,不应将百分比用于flex子元素的padding bottom/top,在此处查看更多信息
您可以制作响应式正方形网格并添加border-radius使它们成为圆形。
对于图片,object-fit: cover;属性完全符合您的需求:保持图像的原始纵横比并完全覆盖元素。
我将第一张图片更改为横向图片,以展示这种技术也适用于此类图片。
以下是如何实现您的目标的示例(我删除了一些CSS以使演示简单):

*,*::before,*::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.img-gallery {
  background: #fafafa;
  padding: 24px;
  min-width: 320px;
  width: 90%;
  margin: 0 auto;
}

.img-gallery .row {
  display: flex;
  flex-wrap: nowrap;
  justify-content: space-around;
  align-items: center;
}

.img-gallery a {
  display: block;
  position:relative;
  text-decoration: none;
  background-image: linear-gradient(60deg, #004494 0%, #7db9e8 78%, #c2dfed 100%);
  overflow: hidden;
  border-radius: 50%;
  flex: 1;
  margin: 24px;
}
.img-gallery a::before{
  content:'';
  display:block;
  padding-bottom:100%;
}


.img-gallery .row:first-of-type a:not(:nth-child(2)) {
  width: 30%;
  width: calc((60% - 96px) / 2);
}

.img-gallery .row:first-of-type a:nth-child(2) {
  flex: 2;
}

.img-gallery span {
  position:absolute;
  top:3px;left:3px;right:3px;bottom:3px;
  border-radius: 50%;
  overflow: hidden;
  transition: transform 250ms;
}

.img-gallery img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition:transform 0.5s;
}
.img-gallery a:hover img{
  transform:scale(1.25);
}
<div class="img-gallery">
  <div class="row">
    <a href="#" title="Show large image"><span><img itemprop="image" src="https://farm7.staticflickr.com/6217/6216951796_e50778255c.jpg" id="img-1-3"></span></a>
    <a href="#" title="Show large image"><span><img itemprop="image" src="https://s-media-cache-ak0.pinimg.com/originals/d6/df/51/d6df512a2f15f517767b4d82d2d97a4c.jpg" id="img-1-4"></span></a>
    <a href="#" title="Show large image"><span><img itemprop="image" src="https://s-media-cache-ak0.pinimg.com/originals/ec/a9/dd/eca9dd106a04cdbee399870252ef711f.jpg" id="img-1-5"></span></a>
  </div>
  <div class="row">
    <a href="#" title="Show large image"><span><img itemprop="image" src="https://s-media-cache-ak0.pinimg.com/originals/7d/01/19/7d0119a2fec989e208f288326c7cad0f.jpg" id="img-1-6"></span></a>
    <a href="#" title="Show large image"><span><img itemprop="image" src="https://s-media-cache-ak0.pinimg.com/originals/d8/c3/32/d8c332d09b03673845b2e92a48816233.jpg" id="img-1-7"></span></a>
    <a href="#" title="Show large image"><span><img itemprop="image" src="https://s-media-cache-ak0.pinimg.com/originals/88/3b/dd/883bddab14168f5f0807fec021002d8d.jpg" id="img-1-8"></span></a>
  </div>
  <div class="row">
    <a href="#" title="Show large image"><span><img itemprop="image" src="https://s-media-cache-ak0.pinimg.com/originals/8e/4f/bb/8e4fbb89b155d15521b80d1baf9290d1.jpg" id="img-1-9"></span></a>
  </div>
</div>

请注意,根据您需要支持的浏览器,您需要为过渡和转换属性添加供应商前缀。有关transformstransitions的详细信息,请参见canIuse。

2
这与 Terry 的答案之间的区别并不是立即明显的。提问者可能应该提供一些风景图片供使用,以便您可以展示它们是否与您的工作(这是提问者所要求的)。 - BoltClock
好观点@BoltClock。我将第一张图片更改为横向图片,以展示“object-fit:cover;”属性也适用于这些图片。 - web-tiki
哦,好东西。我也没有注意到提问者确实已经编辑添加了一张横向图片。 - BoltClock

1
很简单:你可以使用“padding-bottom: 100%”hack来强制实现1:1的宽高比。根据CSS规范,当以百分比声明垂直margin/padding时,会参考父元素的宽度。这背后的逻辑从未清楚地解释过,但我怀疑是为了防止循环计算。

无论如何,现在你知道可以使用“padding-bottom: <百分比>”来强制固定宽高比;)现在我们只需要将其应用于“.img-gallery span”。请记得将其高度设置为0,因为我们不再需要指定高度:

.img-gallery span {
  height: 0;
  display: block;
  border-radius: 50%;
  position: relative;
  padding-bottom: 100%;
  overflow: hidden;
  transition: transform 250ms;
  z-index: 2;
}

p/s: 我不太确定为什么你在鼠标悬停时将:nth-child(2n)元素的填充设置为0,所以我现在已经将其删除。

这是一个概念验证示例:

*,
*::before,
*::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.img-gallery {
  background: #fafafa;
  padding: 24px;
  min-width: 320px;
  width: 90%;
  margin: 0 auto;
}

.img-gallery .row {
  display: flex;
  flex-wrap: nowrap;
  justify-content: space-around;
  align-items: center;
}

.img-gallery a {
  display: block;
  text-decoration: none;
  background-image: linear-gradient(60deg, #004494 0%, #7db9e8 78%, #c2dfed 100%);
  overflow: hidden;
  border-radius: 50%;
  padding: 3px;
  flex: 1;
  margin: 0 24px;
  transition: padding 200ms;
}

.img-gallery .row:first-of-type a:not(:nth-child(2)) {
  width: 30%;
  width: calc((60% - 96px) / 2);
}

.img-gallery .row:first-of-type a:nth-child(2) {
  flex: 2;
  padding: 4px;
}

.img-gallery span {
  height: 0;
  display: block;
  border-radius: 50%;
  position: relative;
  padding-bottom: 100%;
  overflow: hidden;
  transition: transform 250ms;
  z-index: 2;
}

.img-gallery img {
  width: 100%;
  object-fit: cover;
  transition: transform 250ms;
}

.img-gallery a:hover img {
  transform: scale(1.25);
}

.img-gallery span::before {
  content: "";
  background-image: linear-gradient(60deg, transparent 48%, #ffc5e7 100%);
  width: 100%;
  height: 100%;
  position: absolute;
  z-index: 2;
  border-radius: 50%;
  opacity: .72;
}
<div class="img-gallery">
  <div class="row">
    <a href="#" title="Show large image"><span><img itemprop="image" src="https://s-media-cache-ak0.pinimg.com/originals/b3/9c/54/b39c54776074d07ee0b567826768730a.jpg" id="img-1-3"></span></a>
    <a href="#" title="Show large image"><span><img itemprop="image" src="https://s-media-cache-ak0.pinimg.com/originals/d6/df/51/d6df512a2f15f517767b4d82d2d97a4c.jpg" id="img-1-4"></span></a>
    <a href="#" title="Show large image"><span><img itemprop="image" src="https://s-media-cache-ak0.pinimg.com/originals/ec/a9/dd/eca9dd106a04cdbee399870252ef711f.jpg" id="img-1-5"></span></a>
  </div>
  <div class="row">
    <a href="#" title="Show large image"><span><img itemprop="image" src="https://s-media-cache-ak0.pinimg.com/originals/7d/01/19/7d0119a2fec989e208f288326c7cad0f.jpg" id="img-1-6"></span></a>
    <a href="#" title="Show large image"><span><img itemprop="image" src="https://s-media-cache-ak0.pinimg.com/originals/d8/c3/32/d8c332d09b03673845b2e92a48816233.jpg" id="img-1-7"></span></a>
    <a href="#" title="Show large image"><span><img itemprop="image" src="https://s-media-cache-ak0.pinimg.com/originals/88/3b/dd/883bddab14168f5f0807fec021002d8d.jpg" id="img-1-8"></span></a>
  </div>
  <div class="row">
    <a href="#" title="Show large image"><span><img itemprop="image" src="https://s-media-cache-ak0.pinimg.com/originals/8e/4f/bb/8e4fbb89b155d15521b80d1baf9290d1.jpg" id="img-1-9"></span></a>
  </div>
</div>


不幸的是,这遇到了我之前遇到的问题:只有当所有图片都是纵向方向时,它才能正常工作,而这恰好是我所有示例的情况。在我的 OP 中,我添加了一张横向图片的示例,显示这并不能按预期工作。(跨度未被图像“覆盖”)。 - Bram Vanroy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接