简体   繁体   中英

Center an image and scale height/width to fit inside flexbox parent?

I'm trying to center and scale an image inside a container. In the following diagrams, the pink box is a 16:9 container and the blue box is the image.

在此输入图像描述 If the image is wider than the container, it will scale to fit.

在此输入图像描述 If the image is taller than the container, it will also scale to fit.

在此输入图像描述 If the image fits in the container, it will simply be centered.

As you can see in the diagrams, there is also a caption div aligned to the bottom left of the image, and a close icon aligned to the top right.

Here is the code I have now:

 /* 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> 

The following CodePen contains the above code, with some examples of different sized images.

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

This may not be a direct answer to your question but usually when I have to do something like this, I use a div with a background image instead of an img tag. Using a div with a bg image allows you to use styles like background-image , background-position and background-size which allow you to create the effect as described by you.

Sample:

 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> 

EDIT: You can change the image size in the styles and resize the window to see the scaling in action.

I also noticed the comment which mentioned that you do not want to use background image as it will clip the image. This will not happen if you use background-size:contain

EDIT 2: It turns out you can actually figure out what the coordinates of the image are and position other elements around it. Have created a dirty hack to demonstrate this (mixed jQuery and vanilla JS, no proper scoping etc).. But you should be able to get the main idea and implement a neater solution. The main idea is derived from this question on SO

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM