居中图像和缩放高度/宽度以适应Flexbox父级内部?

时间:2018-04-17 07:10:08

标签: javascript html css flexbox

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

enter image description here 如果图像比容器更宽,它将缩放以适合。

enter image description here 如果图像比容器更高,它也会缩放以适合。

enter image description here 如果图像适合容器,它将只是居中。

正如您在图表中看到的那样,还有一个标题 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>
&#13;
&#13;
&#13;

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

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

1 个答案:

答案 0 :(得分:1)

这可能不是您问题的直接答案,但通常在我必须执行此类操作时,我会使用带有背景图片的div代替img代码。使用带有bg图像的div可以使用background-imagebackground-positionbackground-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: 事实证明,你实际上可以弄清楚图像的坐标是什么,并在其周围放置其他元素。已经创建了一个肮脏的黑客来演示这个(混合的jQuery和vanilla JS,没有适当的范围等)。但是你应该能够获得主要想法并实现更简洁的解决方案。主要思想来自this question on SO