【问题标题】:Center an image and scale height/width to fit inside flexbox parent?将图像居中并缩放高度/宽度以适应 flexbox 父级?
【发布时间】:2018-09-27 01:20:51
【问题描述】:

我正在尝试将容器内的图像居中并缩放。在下图中,粉色框是 16:9 的容器,蓝色框是图像。

如果图片比容器宽,它将缩放以适应。

如果图片比容器高,它也会缩放以适应。

如果图像适合容器,它将简单地居中。

正如您在图表中看到的,还有一个 caption div 与图像的左下方对齐,一个 关闭图标 与右上方对齐。

这是我现在拥有的代码:

/* The page */
.container {
  width: 100%;
  height: 100%;
}

/* 16:9 container */
.imageWrapper {
  padding-bottom: 56.25%;
  position: relative;
  width: 100%;
  border: 1px solid red;
}

.imageInnerWrapper {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* The image, footer and close button all need to fit inside the container */
.imageAndFooterWrapper {
  display: inline-flex;
  flex-direction: column;
  position: relative;
  border: 1px solid lightblue;
}

.image {
  max-height: 100%;
  object-fit: contain;
}

.footer {
  text-align: left;
}

.closeButton {
  position: absolute;
  top: -30px;
  right: -30px;
}
<div class="container">
  <div class="imageWrapper">
    <div class="imageInnerWrapper">
      <div class="imageAndFooterWrapper">
        <img class="image" src="https://images.theconversation.com/files/204986/original/file-20180206-14104-1hyhea9.jpg?ixlib=rb-1.1.0&rect=0%2C1212%2C5550%2C2775&q=45&auto=format&w=1356&h=668&fit=crop">
        <div class="footer">
          Caption
        </div>
        <div class="closeButton">X</div>
      </div>
    </div>
  </div>
</div>

以下 CodePen 包含上述代码,以及一些不同大小图像的示例。

https://codepen.io/anon/pen/NMKxxm

【问题讨论】:

  • 这可能与此重复:stackoverflow.com/questions/12991351/… -- 如果不是完全重复,那里仍有信息可以帮助您。
  • @Zephyr 为什么不删除 标签并使用带有背景大小的 background-image 属性?
  • @kshetline 谢谢,但我的问题非常不同和具体,我不仅要处理单个图像,还要处理特定大小的容器和绝对定位的关闭图标和页脚。实际上,我确实已经合并了该答案,我的图像具有max-height: 100%; object-fit: contain; 以将比例和大小保持在imageAndFooterWrapper 内。
  • @user6016913 我不能使用background-image,因为它不知道图像的宽度,并且页脚和关闭按钮都需要知道图像的尺寸才能进行绝对定位。 (对不起,我之前发布了一个错误的评论,说问题是它裁剪了图像)
  • @Zephyr 你得到你的答案还是你仍然陷入设计问题,如果是,那么我会尽力给你一个答案。其实我一直在关注问题,但由于时间不够,我无法给你答案,但现在我可以了,所以先问你

标签: javascript html css flexbox


【解决方案1】:

这可能不是您问题的直接答案,但通常当我必须做这样的事情时,我使用带有背景图像的div 而不是img 标签。使用带有 bg 图像的 div 允许您使用 background-image、background-position 和 background-size 等样式,这些样式允许您创建您所描述的效果。

示例:

var imgDiv = $('.image')[0];
var closeButton = $('.fixed-el')[0];
var img = document.createElement('img');
img.src = getComputedStyle(imgDiv).backgroundImage.split('"')[1];

var calculate_positions = {
  img_width: img.naturalWidth,
  img_height: img.naturalHeight,
  img_ratio: function() {
    return calculate_positions.img_width / calculate_positions.img_height;
  },
  elm_ratio: function(elm) {
    return $(elm).width() / $(elm).height();
  },
  img_offset: function(elm) {
    var offset = []; //[x,y]

    if (calculate_positions.elm_ratio(elm) > calculate_positions.img_ratio()) {
      //centered x height 100%
      var scale_percent = $(elm).height() / calculate_positions.img_height;
      var scaled_width = calculate_positions.img_width * scale_percent;
      var x_offset = ($(elm).width() - scaled_width) / 2;
      offset = [x_offset, 0];
    } else {
      //centered y width 100%
      var scale_percent = $(elm).width() / calculate_positions.img_width;
      var scaled_height = calculate_positions.img_height * scale_percent;
      var y_offset = ($(elm).height() - scaled_height) / 2;
      offset = [0, y_offset];
    }
    return offset;
  }
}

function updatePosition() {
  var offset = calculate_positions.img_offset($('div.image'));
  closeButton.style.top = offset[1] + 'px';
  closeButton.style.left = offset[0] + 'px';
}
$(window).resize(updatePosition)
$(img).load(function() {
  updatePosition();
});
div.image {
  width: 100%;
  background-image: url('http://via.placeholder.com/100x100');
  background-position: center;
  background-size: contain;
  background-repeat: no-repeat;
  flex: 1;
}

html,
body,
div.container {
  width: 100%;
  height: 100%
}

div.container {
  display: flex;
  position: relative;
  flex-direction: column;
}

div.fixed-el {
  position: absolute;
  width: 20px;
  height: 20px;
  background: red;
}

div.caption {
  text-align: center;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
  <div class="image"></div>
  <div class="caption">Some caption here</div>
  <div class="fixed-el"></div>
</div>

编辑: 您可以在样式中更改图像大小并调整窗口大小以查看缩放效果。

我还注意到评论中提到您不想使用背景图像,因为它会剪切图像。如果您使用background-size:contain,则不会发生这种情况

编辑 2: 事实证明,您实际上可以弄清楚图像的坐标是什么,并在其周围放置其他元素。已经创建了一个肮脏的 hack 来证明这一点(混合 jQuery 和 vanilla JS,没有适当的范围等)。但是你应该能够理解主要思想并实现一个更简洁的解决方案。主要思想来源于this question on SO

【讨论】:

  • 感谢您的回复。我又试了一次,并记得为什么它对我不起作用(我在上面的评论中说它裁剪了图像,但这是错误的原因)。我需要将页脚和关闭按钮绝对定位在图像旁边,并且 background-image 它不知道图像的宽度。结果是页脚位于页面的最左下角,关闭按钮位于页面的右上角,而图像可能是页面中心的小图像。
  • @Zephyr 啊。这就说得通了。抱歉,这没有帮助。我找到了this question on SO,它解释了如何计算图像的坐标,但这需要我们事先知道图像的大小,这在这种情况下可能是不可能的。
  • @Zephyr 已使用固定 div 更新了我的答案,该 div 绝对定位以匹配图像的左上角。
猜你喜欢
  • 2013-11-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多