I know that it is impossible to actually modify an image with CSS, which is why I put crop in quotes.
What I'd like to do is take rectangular images and use CSS to make them appear square without distorting the image at all.
I'd basically like to turn this:
Into this:
A pure CSS solution with no wrapper div or other useless code:
img {
object-fit: cover;
width: 230px;
height: 230px;
}
Assuming they do not have to be in IMG tags...
HTML:
<div class="thumb1">
</div>
CSS:
.thumb1 {
background: url(blah.jpg) 50% 50% no-repeat; /* 50% 50% centers image in div */
width: 250px;
height: 250px;
}
.thumb1:hover { YOUR HOVER STYLES HERE }
EDIT: If the div needs to link somewhere just adjust HTML and Styles like so:
HTML:
<div class="thumb1">
Link
</div>
CSS:
.thumb1 {
background: url(blah.jpg) 50% 50% no-repeat; /* 50% 50% centers image in div */
width: 250px;
height: 250px;
}
.thumb1 a {
display: block;
width: 250px;
height: 250px;
}
.thumb1 a:hover { YOUR HOVER STYLES HERE }
Note this could also be modified to be responsive, for example % widths and heights etc.
If the image is in a container with a responsive width:
.rect-img-container {
position: relative;
}
.rect-img-container::after {
content: "";
display: block;
padding-bottom: 100%;
}
.rect-img {
position: absolute;
width: 100%;
height: 100%;
object-fit: cover;
}
<div class="rect-img-container">
<img class="rect-img" src="https://picsum.photos/id/0/367/267" alt="">
</div>
(edit: updated from sass to plain css)
(edit: Added dummy image for reference)
Place your image in a div.
Give your div explicit square dimensions.
Set the CSS overflow property on the div to hidden (overflow:hidden).
Put your imagine inside the div.
Profit.
For example:
<div style="width:200px;height:200px;overflow:hidden">
<img src="foo.png" />
</div>
Using background-size:cover - http://codepen.io/anon/pen/RNyKzB
CSS:
.image-container {
background-image: url('http://i.stack.imgur.com/GA6bB.png');
background-size:cover;
background-repeat:no-repeat;
width:250px;
height:250px;
}
Markup:
<div class="image-container"></div>
I actually came across this same problem recently and ended up with a slightly different approach (I wasn't able to use background images). It does require a tiny bit of jQuery though to determine the orientation of the images (I' sure you could use plain JS instead though).
I wrote a blog post about it if you are interested in more explaination but the code is pretty simple:
HTML:
<ul class="cropped-images">
<li><img src="http://fredparke.com/sites/default/files/cat-portrait.jpg" /></li>
<li><img src="http://fredparke.com/sites/default/files/cat-landscape.jpg" /></li>
</ul>
CSS:
li {
width: 150px; // Or whatever you want.
height: 150px; // Or whatever you want.
overflow: hidden;
margin: 10px;
display: inline-block;
vertical-align: top;
}
li img {
max-width: 100%;
height: auto;
width: auto;
}
li img.landscape {
max-width: none;
max-height: 100%;
}
jQuery:
$( document ).ready(function() {
$('.cropped-images img').each(function() {
if ($(this).width() > $(this).height()) {
$(this).addClass('landscape');
}
});
});
Check out CSS aspect-ratio
https://developer.mozilla.org/en-US/docs/Web/CSS/aspect-ratio
.square-image{
width: 50%;
background-image: url('https://picsum.photos/id/0/367/267');
background-size: cover;
background-position: center;
aspect-ratio: 1/1;
}
<div class="square-image"></div>
You can also do this with a regular img tag as follows
.square-image{
width: 50%;
object-fit: cover; /* Required to prevent the image from stretching, use the object-position property to adjust the visible area */
aspect-ratio: 1/1;
}
<img src="https://picsum.photos/id/0/367/267" class="square-image"/>
Today you can use aspect-ratio:
img {
aspect-ratio: 1 / 1;
}
It has wide support amongst modern browsers as well:
https://caniuse.com/mdn-css_properties_aspect-ratio
object-fit: cover will do exactly what you need.
But it might not work on IE/Edge. Follow as shown below to fix it with just CSS to work on all browsers.
The approach I took was to position the image inside the container with absolute and then place it right at the centre using the combination:
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
Once it is in the centre, I give to the image,
// For vertical blocks (i.e., where height is greater than width)
height: 100%;
width: auto;
// For Horizontal blocks (i.e., where width is greater than height)
height: auto;
width: 100%;
This makes the image get the effect of Object-fit:cover.
Here is a demonstration of the above logic.
https://jsfiddle.net/furqan_694/s3xLe1gp/
This logic works in all browsers.
Original Image
Vertically Cropped
Horizontally Cropped
Square Container
I had a similar issue and could not "compromise" with background images.
I came up with this.
<div class="container">
<img src="http://lorempixel.com/800x600/nature">
</div>
.container {
position: relative;
width: 25%; /* whatever width you want. I was implementing this in a 4 tile grid pattern. I used javascript to set height equal to width */
border: 2px solid #fff; /* just to separate the images */
overflow: hidden; /* "crop" the image */
background: #000; /* incase the image is wider than tall/taller than wide */
}
.container img {
position: absolute;
display: block;
height: 100%; /* all images at least fill the height */
top: 50%; /* top, left, transform trick to vertically and horizontally center image */
left: 50%;
transform: translate3d(-50%,-50%,0);
}
//assuming you're using jQuery
var h = $('.container').outerWidth();
$('.container').css({height: h + 'px'});
Hope this helps!
Example:
https://jsfiddle.net/cfbuwxmr/1/
Use CSS: overflow:
.thumb {
width:230px;
height:230px;
overflow:hidden
}
Either use a div with square dimensions with the image inside with the .testimg class:
.test {
width: 307px;
height: 307px;
overflow:hidden
}
.testimg {
margin-left: -76px
}
or a square div with a background of the image.
.test2 {
width: 307px;
height: 307px;
background: url(http://i.stack.imgur.com/GA6bB.png) 50% 50%
}
Here's some examples: http://jsfiddle.net/QqCLC/1/
UPDATED SO THE IMAGE CENTRES
.test {
width: 307px;
height: 307px;
overflow: hidden
}
.testimg {
margin-left: -76px
}
.test2 {
width: 307px;
height: 307px;
background: url(http://i.stack.imgur.com/GA6bB.png) 50% 50%
}
<div class="test"><img src="http://i.stack.imgur.com/GA6bB.png" width="460" height="307" class="testimg" /></div>
<div class="test2"></div>
I came with a different approach. You basically have to crop the rectangular image to fit it inside the square is all there is to it. Best approach is if the image width is greater than the height, then you crop the image alittle from left and right side of the image. If the image height is greater than the image width then you crop the bottom of the image. Here is my solution. I needed a little help from PHP though.
<div style="position: relative; width: 154px; height: 154px; overflow: hidden;">
<?php
//get image dimmensions whichever way you like. I used imgaick
$image = new Imagick("myimage.png");
$width = $image->getImageWidth();
$height = $image->getImageHeight();
if($width > $height){
?>
<img src="myimage.png" style="display: block; position: absolute; top: 0px; left: 50%; transform: translateX(-50%); -ms-transform: translateX(-50%); -webkit-transform: translateX(-50%); height: 100%; " />
<?php
}else{
?>
<img src="myimage.png" style="display: block; position: absolute; top: 0px; left: 0px; width: 100%; " />
<?php
}
?>
</div>
Related
What I am trying to accomplish:
- create a pop-up div (fixed), centered in view
- this pop-up should be 60% height of the browser window
- the contents of the pop-up should be an image and a 'x' above the upper right corner of the image
- the height of the image should be maximal, considering it should be contained in the div together with the 'x'
- the aspect ratio of the image should be maintained
I tried the following code
<div class="pop-up">
<p class="exit-button">x</p>
<img class="image" src="safari.png" width="1200" height="630" alt="" title="" />
</div>
With CSS:
body {
background: #333;
}
.pop-up {
position: fixed;
height: 60%;
width: auto;
left:50%;
top:50%;
-webkit-transform:translate(-50%,-50%);
transform:translate(-50%,-50%);
background:yellow;
object-fit: contain;
}
.exit-button {
text-align: right;
margin: 0;
font-size: 300%;
}
.image {
height: 100%;
width: auto;
opacity:0.7;
}
This code is not solving the problem, the image is not contained in the (yellow) div, as can be seen in the following screen shot:
http://www.michielvisser.nl/tmp/screenshot.jpg
How to contain the image in the div with maximal height for the image in the div and maintain aspect ratio?
SOLUTION 1: Remove the height and width from .pop-up and change height:100% in .image to height:60vh. That works perfectly. Apparently the child (img) will not adjust to the parent (div), but the parent (div) will adjust to the child (img). Sounds like real life.
SOLUTION 2: Essentially the problem arises when the window is resized (except in firefox). The solution can be to redraw the image after a resize, this solves the problem:
$(window).resize(function(){
$('img').hide();
setTimeout(function(){ $('img').show(); }, 1);
});
Your problems are:
You have an inline width and height set on your image, which is overriding the CSS styles for width and height on that image
The margin from your X is pushing the image down since the X is wrapped in a <p> tag.
You don't need object-fit at all.
The simple way to solve #1 is to delete the inline width and height from the image tag and leave it to the stylesheet.
Number 2 can be solved by wrapping the X in a div instead of a p, or you can use a pseudo element for it. I have taken the latter approach in the snippet below.
To solve #3, just delete the style from the stylesheet. (Having this property set in Safari actually messed things up for me.)
This snippet is tested in Safari 10.1.1. Note how the placeholder image is quite large by default (1000x800), but it only displays as big as it can per the parent div.
Edit: Based on your comments, let's revise this further so that we dictate the size on the image, and just let the wrapper take up the size of the image.
So on our image, in order to get it to be 60% as tall as the screen, we can do:
img {
height: 60vh;
width: auto;
}
Then, in our parent, we won't specify a width or height at all, but we can do display: flex just to make sure it is big enough to fit its contents.
body {
background: #333;
}
.pop-up {
display: flex;
position: fixed;
left: 50%;
top: 50%;
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
background: yellow;
}
.exit {
color: black;
text-decoration: none;
text-align: center;
font-size: 300%;
display: block;
position: absolute;
top: -50px;
right: -40px;
width: 40px;
height: 50px;
}
.image {
height: 60vh;
width: auto;
opacity: 0.7;
}
<div class="pop-up">
X
<img class="image" src="http://placehold.it/1000x800" alt="" title="">
</div>
I put the image above the P tag and added some CSS to .exit-button and .image
From here you can adjust padding and sizing of the elements.
body {
background: #333;
}
.pop-up {
position: fixed;
height: 60%;
width: auto;
left:50%;
top:50%;
-webkit-transform:translate(-50%,-50%);
transform:translate(-50%,-50%);
background:yellow;
object-fit: contain;
}
.exit-button {
position: absolute;
text-align: right;
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: 0;
font-size: 300%;
}
.image {
height: 100%;
width: auto;
opacity:0.7;
}
<div class="pop-up">
<img class="image" src="http://icons.iconarchive.com/icons/johanchalibert/mac-osx-yosemite/1024/safari-icon.png" width="1200" height="630" alt="" title="" />
<p class="exit-button">x</p>
</div>
I copied your code and edited it. Please tell me whether this is the output you wanted or not.
body {
background: #333;
}
.pop-up {
position: fixed;
height: 60%;
width: auto;
left:50%;
top:50%;
padding-top: 30px;
-webkit-transform:translate(-50%,-50%);
transform:translate(-50%,-50%);
background:yellow;
object-fit: contain;
}
.exit-button {
margin-top: -50px;
text-align: right;
margin-right: 0;
font-size: 300%;
}
.image {
margin-top: -20px;
height: 100%;
width: auto;
opacity:0.7;
}
<div class="pop-up">
<p class="exit-button">x</p>
<img class="image" src="safari.png" alt="" title="" />
</div>
Because of either needing to hardcode in the alignment of the image given the size or deal with weird convolution, I believe this is the best way:
Create a fixed overlay occupying the entirety of the screen, create a container of 60% height, align it in the center with flexbox and stick the image inside making it occupy the entire height. The aspect ratio will update automatically (only happens with height).
As for the button – give it absolute positioning and a right position of 0, and manually give the parent relative positioning (this is necessary).
<div id="popup">
<div id="container">
X
<img src="https://i.redd.it/gelilvo30mgz.jpg">
</div>
</div>
html,
body {
height: 100%;
}
#popup {
position: fixed;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
#container {
position: relative; !important // has to be specified for the children (anchor) to find the bound
height: 60%;
background: #333;
}
a {
right: 0;
position: absolute;
}
img {
height: 100%;
}
https://jsfiddle.net/L2nLjjxc/1/
I believe that's the least amount of convolution if you want it to be dynamic.
As discussed here I am trying to get an image to be covered within a div. With just these simple lines I was able to achieve this via background-image:
div{
width: 172px;
height: 172px;
border-style: solid;
background-image: url('../images/img1.jpg');
background-size: cover;
background-repeat: no-repeat;
background-position: center;
}
In result the image was centered within the div and was resized so it would fit the width or the height of the div (depending if the image was wide or not).
Now I would like to achieve the same result with the image tag within the div.
<div>
<img src="images/img1.jpg"/>
</div>
Is there any way to get through this with plain CSS?
Use object-fit:cover to not lose ratio.
div {
border: black solid;
width: 400px;
height: 400px;
}
img {
width: 100%;
height: 100%;
object-fit: cover
}
<div>
<img src="//lorempixel.com/100/100" />
</div>
NOTE: this is not supported in IE
P.S. - For those who like to downvote (and are downvoting) just for the simple reason that "It doesn't work in IE" (by the way, it is an outdated browser, so please educate your clients to use at least the upgraded browser EDGE), there are a few object-fit polyfills out there that will make object-fit work.
Here are a few examples:
object-fit-images
constancecchen /object-fit-pollyfill
Polyfill for CSS object-fit property
Or if you think its an overkill using a polyfill just for that property, here is simple snippet that will make this work in IE.
You can use a simple JS snippet to detect if the object-fit is supported and then replace the img for a svg
//for browsers which doesn't support object-fit (you can use babel to transpile to ES5)
if ('objectFit' in document.documentElement.style === false) {
document.addEventListener('DOMContentLoaded', () => {
document.querySelectorAll('img[data-object-fit]').forEach(image => {
(image.runtimeStyle || image.style).background = `url("${image.src}") no-repeat 50%/${image.currentStyle ? image.currentStyle['object-fit'] : image.getAttribute('data-object-fit')}`
image.src = `data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='${image.width}' height='${image.height}'%3E%3C/svg%3E`
})
})
}
img {
display: inline-flex;
width: 175px;
height: 175px;
margin-right: 10px;
border: 1px solid red
}
/*for browsers which support object fit */
[data-object-fit='cover'] {
object-fit: cover
}
[data-object-fit='contain'] {
object-fit: contain
}
<img data-object-fit='cover' src='//picsum.photos/1200/600' />
<img data-object-fit='contain' src='//picsum.photos/1200/600' />
<img src='//picsum.photos/1200/600' />
If you want to recreate the background-size: cover; look without using a CSS background image, you can use the following to achieve the desired result. Keep in mind, however, that there will always need to be a container holding the image.
div {
position: relative;
overflow: hidden;
}
img {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
min-width: 100%;
min-height: 100%;
height: auto;
width: auto;
}
Depending on your additional CSS, you might want to use max-width and max-height.
Try this:
div {
position:relative;
}
img {
max-height: 100%;
max-width: 100%;
margin: auto;
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
}
This assumes you have given a size to the div.
I want to center an full screen image vertically.
I can't define image in CSS because the image depends on URL parameters.
<div>
<img src="photo.jpg">
</div>
div {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
If I define my image CSS like this:
div img {
width: 100%;
height: 100%;
}
My image will stretch and be deformed in height to fit on screen.
If I define my image CSS like this (just without defining height):
div img {
width: 100%;
}
My image will not stretch/be deformed, but it will start at top: 0 of the image. What I want is the image to be centered vertically and the overflow of it's height to be hidden.
Basically I want the same behaviour I would get in CSS with background centered:
background: url(photo.jpg) no-repeat center;
background-size: cover;
EDIT: I forgot to mention that CSS object-fit: cover works on this but I'm looking for a more cross-browser solution since this property does not work in every browsers.
Try this css
div {
position: fixed;
top: 50%;
left: 0;
width: 100%;
height: 100%;
-webkit-transform: translateY(-50%);
transform: translateY(-50%);
}
EDIT
also its a bad practice to give the image both height and width. this will always override the aspect ratio of the image and stretch it in some direction.
use this for img
div img {
width: 100%;
}
This will first position the division 50% form top. i.e. the image will now have its topmost part at 50% of the page height then the translate property will move the image upward by 50% of its height essentially centering the image
How about this:
div {
position:fixed;
top:0;
left:0;
width: 100px;
height: 100px;
border:1px solid red;
text-align:center;
line-height:100px;
overflow:hidden;
}
img {
vertical-align:middle;
border:1px solid black;
}
<div>
<img src="https://www.smallbusinesssaturdayuk.com/Images/Small-Business-Saturday-UK-Google-Plus.gif">
</div>
If you allow js, you can do this (assuming the image has id 'img'):
#img {
width: 100%;
position: absolute;
top: 50%;
}
A negative margin top needs to be set using js or jQuery (on resize):
$('#img').css('margin-top', '-'+($('#img').height()/2)+'px');
I am trying to create an image wall consisting of product photos. Unfortunately, all of them are of different height and width. How can I use css to make all images look the same size? preferably 100 x 100.
I was thinking of doing a div that has height and width of 100px and then some how filling it up. NOt sure how to do that.
How can I accomplish this?
Updated answer (No IE11 support)
img {
float: left;
width: 100px;
height: 100px;
object-fit: cover;
}
<img src="http://i.imgur.com/tI5jq2c.jpg">
<img src="http://i.imgur.com/37w80TG.jpg">
<img src="http://i.imgur.com/B1MCOtx.jpg">
Original answer
.img {
float: left;
width: 100px;
height: 100px;
background-size: cover;
}
<div class="img" style="background-image:url('http://i.imgur.com/tI5jq2c.jpg');"></div>
<div class="img" style="background-image:url('http://i.imgur.com/37w80TG.jpg');"></div>
<div class="img" style="background-image:url('http://i.imgur.com/B1MCOtx.jpg');"></div>
Simplest way - This will keep the image size as it is and fill the other area with space, this way all the images will take same specified space regardless of the image size without stretching
.img{
width:100px;
height:100px;
/*Scale down will take the necessary specified space that is 100px x 100px without stretching the image*/
object-fit:scale-down;
}
can i just throw in that if you distort your images too much, ie take them out of a ratio, they may not look right, - a tiny amount is fine, but one way to do this is put the images inside a 'container' and set the container to the 100 x 100, then set your image to overflow none, and set the smallest width to the maximum width of the container, this will crop a bit of your image though,
for example
<h4>Products</h4>
<ul class="products">
<li class="crop">
<img src="ipod.jpg" alt="iPod" />
</li>
</ul>
.crop {
height: 300px;
width: 400px;
overflow: hidden;
}
.crop img {
height: auto;
width: 400px;
}
This way the image will stay the size of its container, but will resize without breaking constraints
You can use the object-fit property to size the img elements:
cover stretches or shrinks the image proportionally to fill the container. The image is cropped horizontally -or- vertically if necessary.
contain stretches or shrinks the image proportionally to fit inside the container.
scale-down shrinks the image proportionally to fit inside the container.
.example {
margin: 1em 0;
text-align: center;
}
.example img {
width: 30vw;
height: 30vw;
}
.example-cover img {
object-fit: cover;
}
.example-contain img {
object-fit: contain;
}
<div class="example example-cover">
<img src="https://i.stack.imgur.com/B0EAo.png">
<img src="https://i.stack.imgur.com/iYkNH.png">
<img src="https://i.stack.imgur.com/gne9N.png">
</div>
<div class="example example-contain">
<img src="https://i.stack.imgur.com/B0EAo.png">
<img src="https://i.stack.imgur.com/iYkNH.png">
<img src="https://i.stack.imgur.com/gne9N.png">
</div>
In the above example: red is landscape, green is portrait and blue is square image. The checkered pattern consists of 16x16px squares.
For those using Bootstrap and not wanting to lose the responsivness just do not set the width of the container. The following code is based on gillytech post.
index.hmtl
<div id="image_preview" class="row">
<div class='crop col-xs-12 col-sm-6 col-md-6 '>
<img class="col-xs-12 col-sm-6 col-md-6"
id="preview0" src='img/preview_default.jpg'/>
</div>
<div class="col-xs-12 col-sm-6 col-md-6">
more stuff
</div>
</div> <!-- end image preview -->
style.css
/*images with the same width*/
.crop {
height: 300px;
/*width: 400px;*/
overflow: hidden;
}
.crop img {
height: auto;
width: 100%;
}
OR style.css
/*images with the same height*/
.crop {
height: 300px;
/*width: 400px;*/
overflow: hidden;
}
.crop img {
height: 100%;
width: auto;
}
You can do it this way:
.container{
position: relative;
width: 100px;
height: 100px;
overflow: hidden;
z-index: 1;
}
img{
left: 50%;
position: absolute;
top: 50%;
-ms-transform: translate(-50%, -50%);
-webkit-transform: translate(-50%, -50%);
-moz-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
max-width: 100%;
}
Set height and width parameters in CSS file
.ImageStyle{
max-height: 17vw;
min-height: 17vw;
max-width:17vw;
min-width: 17vw;
}
I was looking for a solution for this same problem, to create a list of logos.
I came up with this solution that uses a bit of flexbox, which works for us since we're not worried about old browsers.
This example assumes a 100x100px box but I'm pretty sure the size could be flexible/responsive.
.img__container {
display: flex;
padding: 15px 12px;
box-sizing: border-box;
width: 100px; height: 100px;
img {
margin: auto;
max-width: 100%;
max-height: 100%;
}
}
ps.: you may need to add some prefixes or use autoprefixer.
Without code this is difficult to help you but here's some practical advice for you:
I suspect that your "image wall" has some sort of container with an id or class to give it styles.
eg:
<body>
<div id="maincontainer">
<div id="header"></div>
<div id="content">
<div id="imagewall">
<img src"img.jpg">
<!-- code continues -->
Styling a size on all images for your image wall, while not affecting other images, like you logo, etc. is easy if your code is set up similar to the above.
#imagewall img {
width: 100px;
height: 100px; }
But if your images are not perfectly square they will be skewed using this method.
Based on Andi Wilkinson's answer (the second one), I improved a little, make sure the center of the image is shown (like the accepted answer did):
HTML:
<div class="crop">
<img src="img.png">
</div>
CSS:
.crop{
height: 150px;
width: 200px;
overflow: hidden;
}
.crop img{
width: 100%;
height: auto;
position: relative;
top: 50%;
-webkit-transform: translateY(-50%); /* Ch <36, Saf 5.1+, iOS < 9.2, An =<4.4.4 */
-ms-transform: translateY(-50%); /* IE 9 */
transform: translateY(-50%); /* IE 10, Fx 16+, Op 12.1+ */
}
.article-img img{
height: 100%;
width: 100%;
position: relative;
vertical-align: middle;
border-style: none;
}
You will make images size same as div and you can use bootstrap grid to manipulate div size accordingly
Image size is not depend on div height and width,
use img element in css
Here is css code that help you
div img{
width: 100px;
height:100px;
}
if you want to set size by div
use this
div {
width:100px;
height:100px;
overflow:hidden;
}
by this code your image show in original size but show first 100x100px overflow will hide
Go to your CSS file and resize all your images as follows
img {
width: 100px;
height: 100px;
}
Change your image tag with this CSS style.
img {
float: left;
width: 100px;
height: 100px;
object-fit: cover;
}
Is there a css-only solution to scale an image into a bounding box (keeping aspect-ratio)? This works if the image is bigger than the container:
img {
max-width: 100%;
max-height: 100%;
}
Example:
Use case 1 (works): http://jsfiddle.net/Jp5AQ/2/
Use case 2 (works): http://jsfiddle.net/Jp5AQ/3/
But I want to scale up the image until a dimension is 100% of the container.
Use case 3 (doesn't work): http://jsfiddle.net/Jp5AQ/4/
Thanks to CSS3 there is a solution !
The solution is to put the image as background-image and then set the background-size to contain.
HTML
<div class='bounding-box'>
</div>
CSS
.bounding-box {
background-image: url(...);
background-repeat: no-repeat;
background-size: contain;
}
Test it here: http://www.w3schools.com/cssref/playit.asp?filename=playcss_background-size&preval=contain
Full compatibility with latest browsers: http://caniuse.com/background-img-opts
To align the div in the center, you can use this variation:
.bounding-box {
background-image: url(...);
background-size: contain;
position: absolute;
background-position: center;
background-repeat: no-repeat;
height: 100%;
width: 100%;
}
Note: Even though this is the accepted answer, the answer below is more accurate and is currently supported in all browsers if you have the option of using a background image.
Edit 2: In the modern age, using object-fit might be an even better solution: https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit
No, there is no CSS only way to do this in both directions. You could add
.fillwidth {
min-width: 100%;
height: auto;
}
To the an element to always have it 100% width and automatically scale the height to the aspect ratio, or the inverse:
.fillheight {
min-height: 100%;
width: auto;
}
to always scale to max height and relative width. To do both, you will need to determine if the aspect ratio is higher or lower than it's container, and CSS can't do this.
The reason is that CSS does not know what the page looks like. It sets rules beforehand, but only after that it is that the elements get rendered and you know exactly what sizes and ratios you're dealing with. The only way to detect that is with JavaScript.
Although you're not looking for a JS solution I'll add one anyway if someone might need it. The easiest way to handle this with JavaScript is to add a class based on the difference in ratio. If the width-to-height ratio of the box is greater than that of the image, add the class "fillwidth", else add the class "fillheight".
$('div').each(function() {
var fillClass = ($(this).height() > $(this).width())
? 'fillheight'
: 'fillwidth';
$(this).find('img').addClass(fillClass);
});
.fillwidth {
width: 100%;
height: auto;
}
.fillheight {
height: 100%;
width: auto;
}
div {
border: 1px solid black;
overflow: hidden;
}
.tower {
width: 100px;
height: 200px;
}
.trailer {
width: 200px;
height: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="tower">
<img src="http://placekitten.com/150/150" />
</div>
<div class="trailer">
<img src="http://placekitten.com/150/150" />
</div>
Here's a hackish solution I discovered:
#image {
max-width: 10%;
max-height: 10%;
transform: scale(10);
}
This will enlarge the image tenfold, but restrict it to 10% of its final size - thus bounding it to the container.
Unlike the background-image solution, this will also work with <video> elements.
Interactive example:
function step(timestamp) {
var container = document.getElementById('container');
timestamp /= 1000;
container.style.left = (200 + 100 * Math.sin(timestamp * 1.0)) + 'px';
container.style.top = (200 + 100 * Math.sin(timestamp * 1.1)) + 'px';
container.style.width = (500 + 500 * Math.sin(timestamp * 1.2)) + 'px';
container.style.height = (500 + 500 * Math.sin(timestamp * 1.3)) + 'px';
window.requestAnimationFrame(step);
}
window.requestAnimationFrame(step);
#container {
outline: 1px solid black;
position: relative;
background-color: red;
}
#image {
display: block;
max-width: 10%;
max-height: 10%;
transform-origin: 0 0;
transform: scale(10);
}
<div id="container">
<img id="image" src="https://upload.wikimedia.org/wikipedia/en/7/7d/Lenna_%28test_image%29.png">
</div>
Today, just say object-fit: contain. Support is everything but IE: http://caniuse.com/#feat=object-fit
html:
<div class="container">
<img class="flowerImg" src="flower.jpg">
</div>
css:
.container{
width: 100px;
height: 100px;
}
.flowerImg{
width: 100px;
height: 100px;
object-fit: cover;
/*object-fit: contain;
object-fit: scale-down;
object-position: -10% 0;
object-fit: none;
object-fit: fill;*/
}
You can accomplish this with pure CSS and complete browser support, both for vertically-long and horizontally-long images at the same time.
Here's a snippet which works in Chrome, Firefox, and Safari (both using object-fit: scale-down, and without using it):
figure {
margin: 0;
}
.container {
display: table-cell;
vertical-align: middle;
width: 80px;
height: 80px;
border: 1px solid #aaa;
}
.container_image {
display: block;
max-width: 100%;
max-height: 100%;
margin-left: auto;
margin-right: auto;
}
.container2_image2 {
width: 80px;
height: 80px;
object-fit: scale-down;
border: 1px solid #aaa;
}
Without `object-fit: scale-down`:
<br>
<br>
<figure class="container">
<img class="container_image" src="https://i.imgur.com/EQgexUd.jpg">
</figure>
<br>
<figure class="container">
<img class="container_image" src="https://i.imgur.com/ptO8pGi.jpg">
</figure>
<br> Using `object-fit: scale-down`:
<br>
<br>
<figure>
<img class="container2_image2" src="https://i.imgur.com/EQgexUd.jpg">
</figure>
<br>
<figure>
<img class="container2_image2" src="https://i.imgur.com/ptO8pGi.jpg">
</figure>
Another solution without background image and without the need for a container (though the max sizes of the bounding box must be known):
img{
max-height: 100px;
max-width: 100px;
width: auto; /* These two are added only for clarity, */
height: auto; /* as the default is auto anyway */
}
If a container's use is required, then the max-width and max-height can be set to 100%:
img {
max-height: 100%;
max-width: 100%;
width: auto; /* These two are added only for clarity, */
height: auto; /* as the default is auto anyway */
}
div.container {
width: 100px;
height: 100px;
}
For this you would have something like:
<table>
<tr>
<td>Lorem</td>
<td>Ipsum<br />dolor</td>
<td>
<div class="container"><img src="image5.png" /></div>
</td>
</tr>
</table>
This example to stretch the image proportionally to fit the entire window.
An improvisation to the above correct code is to add $( window ).resize(function(){});
function stretchImg(){
$('div').each(function() {
($(this).height() > $(this).find('img').height())
? $(this).find('img').removeClass('fillwidth').addClass('fillheight')
: '';
($(this).width() > $(this).find('img').width())
? $(this).find('img').removeClass('fillheight').addClass('fillwidth')
: '';
});
}
stretchImg();
$( window ).resize(function() {
strechImg();
});
There are two if conditions. The first one keeps checking if the image height is less than the div and applies .fillheight class while the next checks for width and applies .fillwidth class.
In both cases the other class is removed using .removeClass()
Here is the CSS
.fillwidth {
width: 100%;
max-width: none;
height: auto;
}
.fillheight {
height: 100vh;
max-width: none;
width: auto;
}
You can replace 100vh by 100% if you want to stretch the image with in a div. This example to stretch the image proportionally to fit the entire window.
Are you looking to scale upwards but not downwards?
div {
border: solid 1px green;
width: 60px;
height: 70px;
}
div img {
width: 100%;
height: 100%;
min-height: 500px;
min-width: 500px;
outline: solid 1px red;
}
This however, does not lock aspect-ratio.
I have used table to center image inside the box. It keeps aspect ratio and scales image in a way that is totally inside the box. If the image is smaller than the box then it is shown as it is in the center. Below code uses 40px width and 40px height box. (Not quite sure how well it works because I removed it from another more complex code and simplified it little bit)
.SmallThumbnailContainer {
display: inline-block;
position: relative;
float: left;
width: 40px;
height: 40px;
border: 1px solid #ccc;
margin: 0px;
padding: 0px;
}
.SmallThumbnailContainer {
width: 40px;
margin: 0px 10px 0px 0px;
}
.SmallThumbnailContainer tr {
height: 40px;
text-align: center;
}
.SmallThumbnailContainer tr td {
vertical-align: middle;
position: relative;
width: 40px;
}
.SmallThumbnailContainer tr td img {
overflow: hidden;
max-height: 40px;
max-width: 40px;
vertical-align: middle;
margin: -1px -1px 1px -1px;
}
<table class="SmallThumbnailContainer" cellpadding="0" cellspacing="0">
<tr>
<td>
<img src="https://www.gravatar.com/avatar/bf7d39f4ed9c289feca7de38a0093250?s=32&d=identicon&r=PG" width="32" height="32" alt="OP's SO avatar image used as a sample jpg because it is hosted on SO, thus always available" />
</td>
</tr>
</table>
Note: the native thumbnail size in this snippet is 32px x 32px, which is smaller than its 40px x 40px container. If the container is instead sized smaller than the thumbnail in any dimension, say 40px x 20px, the image flows outside the container in the dimensions that are smaller than the corresponding image dimension. The container is marked by a gray 1px border.
Use Object Fit on both div and img to scale image
<div class="box"><img src="image.jpg"></div>
.box {height: auto;
object-fit: cover;}
img { height: 100%; object-fit: cover; }
This worked for my needs, doesn't flatten out the image while setting height limitation, it overflows instead.
.top-container{
width:50%;
}
.img-container {
display: flex;
justify-content: center;
align-items: center;
height: 40vh;
width: 100%;
overflow: hidden;
}
.img-container img {
max-width: 10%;
max-height: auto;
transform: scale(10);
}
<div class='top-container'>
<div class='img-container'>
<img src='image.jpg'>
</div>
</div>
First some CSS:
div.image-wrapper {
height: 230px; /* Suggestive number; pick your own height as desired */
position: relative;
overflow: hidden; /* This will do the magic */
width: 300px; /* Pick an appropriate width as desired, unless you already use a grid, in that case use 100% */
}
img {
width: 100%;
position: absolute;
left: 0;
top: 0;
height: auto;
}
The HTML:
<div class="image-wrapper">
<img src="yourSource.jpg">
</div>
.img-class {
width: <img width>;
height: <img height>;
content: url('/path/to/img.png');
}
Then on the element (you can use javascript or media queries to add responsiveness):
<div class='img-class' style='transform: scale(X);'></div>
.boundingbox {
width: 400px;
height: 500px;
border: 2px solid #F63;
}
img{
width:400px;
max-height: 500px;
height:auto;
}
With the styles set as shown above in css, now the following html div will show the image always fit width wise and will adjust hight aspect ratio to width. Thus image will scale to fit a bounding box as asked in the question.
<div class="boundingbox"><img src="image.jpg"/></div>