Filling <img> in flexbox and retaining aspect ratio without JavaScript - css

Title says it all. I'm looking for a solution to make img tag fill parent (image and parent are of unknown size) while respecting aspect ratio, also without using background-size or any other workaround. I need the block with the image to have size of that picture (which background-size does not). I tried many things, like min-width and min-height, some strange things with zoom, many combinations of width/height: 100%/auto/0.
EDIT: I should have stated it in original text. I want to show whole image, not just crop a part from it. So correct result will have free space on left&right or top&bottom (this free space is not occupied by said image, only by the container).
html, body{
height: 100%;
width: 100%;
}
#container {
border: 2px solid darkblue;
height: 95%;
width: 97%;
}
#pic {
width: 100%;
height: 100%;
}
<div id="container">
<img src="http://i.imgur.com/CtHGCLF.jpg?1" id="pic">
</div>

If I understand correctly, this would solve the problem.
html, body{
height: 100%;
width: 100%;
}
#container {
border: 2px solid darkblue;
height: 95%;
width: 97%;
text-align: center;
}
#pic {
max-width: 100%;
max-height: 100%;
}
<div id="container">
<img src="http://i.imgur.com/CtHGCLF.jpg?1" id="pic">
</div>

height:auto should do the magic:
html, body{
height: 100%;
width: 100%;
}
#container {
border: 2px solid darkblue;
width: 97%;
}
#pic {
width: 100%;
max-width: max-content;
height: auto;
}
<div id="container">
<img src="http://i.imgur.com/CtHGCLF.jpg?1" id="pic">
</div>

Related

How to resize images inside a flexbox without using a background image?

I know there are a LOT of examples of this, and I have tried all of them to no avail. I am trying to create a carousel component that resizes images according to its boundary. I am using it in a myriad of places, in a myriad of different ways, so it MUST be responsive. I also need the images to be clickable as normal images for a11y and customers (managing expectations).
Here is my fiddle so far: https://codepen.io/skamansam/pen/NWvroeY?editors=1100
I can get all of the elements to resize accordingly (using max-width/height). when I use an image that is wider than taller, all works well. When I use an image that is taller than wider and exceeds the height of the box, the image overflows instead of respecting the max-width/height properties.
The most common answer involves wrapping the image in an html element and setting the width/height there, which I have done, but it doesn't solve the problem. Another common answer involves using combinations of position values, which didn't give any better results than I already have. Using the inspector, you can clearly see that all the elements EXCEPT the image are correctly sized, and the image overflows the container.
Is there any other way to get the img tag to respect height: 100% in the same way it respects width: 100%?
you are using image with a very high resolution (500x800) , you have use little lower resolution otherwise you have to use overflow:hidden; on your wrapping div.Using max-width:100%; the image is already resizing itself but cannot resize further more, inspect the element to get a better understanding.
I made three changes:
Your slide needs width: auto; and height: 100%;
Your image needs width: 100%; and height: 100%;
Your image needs object-fit: contain; (not cover)
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.jumbotron {
display: block;
width: 100%;
margin: 0;
padding: 0;
background-color: #aaa;
/* overflow: hidden; */
height: 150px;
}
.jumbotron .container {
width: 100%;
height: 100%;
}
.my-carousel {
background-color: #77f;
max-height: 100%;
max-width: 100%;
height: 100%;
width: 100%;
display: flex;
flex-direction: row;
// overflow: hidden;
}
.my-carousel .previous-btn, .my-carousel .next-btn {
font-size: 200%;
padding: 0px 10px;
display: flex;
flex-direction: column;
justify-content: center;
}
.my-carousel .content {
max-height: 100%;
max-width: 100%;
align-self: center;
flex-grow: 1;
position: relative;
width: 100%;
height: 100%;
}
.my-carousel .content .slide {
height: 100%;
//max-width: 100%;
display: none;
position: relative;
// width: 100%;
vertical-align: middle;
padding: 0px;
margin: 0px;
overflow: visible;
}
.my-carousel .content .slide.active {
display: block;
}
.my-carousel .content .slide img {
//position: relative;
// margin: 0px auto;
// box-sizing: border-box;
// vertical-align: middle;
height: 100%;
width: 100%;
// max-width: 100%;
// max-height: 100%;
object-fit: contain;
object-position: center;
overflow: hidden;
}
.my-carousel .content .slide .caption {
position: absolute;
background-color: rgba(0,0,0,.4);
text-shadow: 2px 2px 4px #fff, -2px -2px 4px #fff;
stroke: 2px #fff;
padding: 10px;
bottom: 0px;
width: 100%;
font-size: 150%;
// color: #000;
// -webkit-text-stroke-width: 1px;
// -webkit-text-stroke-color: #fff;
}
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#6.3.95/css/materialdesignicons.min.css" rel="stylesheet"/>
<main role="main">
<section class="jumbotron text-center">
<div class="container">
<div class="my-carousel">
<div class="previous-btn">
<span class="mdi mdi-transfer-left"></span>
</div>
<div class="content">
<div class="slide active">
<img src="https://picsum.photos/500/800?random=1" />
<div class="caption">This is only a WIP to figure out how to style this carousel properly.</div>
</div>
<div class="slide">
<img src="https://picsum.photos/1000/400?random=1" />
</div>
</div>
<div class="next-btn">
<span class="mdi mdi-transfer-right" />
</div>
</div>
</div>
</section>
</main>
luckily, the answer is inside "picksum" itself, it allows you to choose the resolution of the image you want, you chose (500x800) that is way too large, you can use the following reduced resolutions >(50x80), (100x160), (180x288), (190x304), (200x320). I am sure you will get your desired result by using (180x288) or (190x304)
for example:<img src="https://picsum.photos/190/304?random=1" />
Use max-width and max-height
Like this
.slide {
width: 100px;
height: 100px;
max-width: 100%;
max-height: 100%;
overflow: hidden;
}
.slide .img {
max-width: 100%;
max-height: 100%;
}

How to add blackbars on image and must stay on image ratio

how to add the black bars on my div with 400x400 div size.
if the picture is portrait, it would add black bars on left and right,
and when the picture is widescreen the black bars will be added on top and bottom.
<div>
<img src="image.png" class="img-responsive" />
</div>
I have no sleep for almost 2 days because of this.
I don't understand on this.
this is the sample picture:
please help me
EDIT1:
hello, can you check my html... it should be perfect align, but the picture have different size the alignment broken... look at this.. http://codepen.io/anon/pen/MaorKq
EDIT2
It's already but when the width higher the image pass through
check here: http://codepen.io/anon/pen/EVXMee
Is this what you're looking for?
I've made a pure CSS solution that should work up to IE8. :)
Also, it should work with any width/height.
.image-background {
background: #000;
display: table;
width: 100%;
height: 100%;
position: relative;
}
.image-container {
display: table-cell;
vertical-align: middle;
text-align: center;
margin: auto;
max-height: 100%;
max-width: 100%;
}
img {
display: block;
max-height: 100%;
max-width: 100%;
margin: auto;
}
http://codepen.io/anon/pen/vNZJwe
Good luck!
Your div is 400*400, but your image is small, When you have used img-responsive that means img max-size : 100 %. But here you want to see min-size:100%.
You can try below code
<img src="image.png" class="img-responsive full-width" /> <!--add class full-width-->
in your css file
.full-width{
width:100%;
}
Use below CSS,JS and HTML markup to achive this:
<style>
.img-container {
width: 400px;
height: 400px;
background-color: black;
position:relative;
}
.img-container img {
position:absolute;
top: 50%;
left: 50%;
}
</style>
<script>
$(document).ready(function() {
debugger;
var img = $('.img-container img');
img.css('margin-top', - ($('.img-container img').height() / 2) + 'px');
img.css('margin-left', - ($('.img-container img').width() / 2) + 'px');
});
</script>
<div class="img-container">
<img src="http://www.gstatic.com/webp/gallery/1.jpg" class="img-responsive" />
</div>
Here is a stripped-down version of what #Himechi90 wrote.
If you only need one image instead of a row, basically all you need is:
.image-full-view {
float: none;
padding: 0;
background: #000;
display: table;
width: 100%;
height: 100%;
}
.image-full-view img {
display: block;
max-height: 80vh;
max-width: 100%;
margin: auto;
}
<div class="image-full-view">
<img src="https://media.usfcvast.org/images/cvast-arches/projects/la_mancha/la_motilla_del_azuer/la_motilla_del_azuer_aerial.jpg" alt="" />
</div>
You can use object-fit: contain;
css:
.image-container {
overflow: hidden;
height: 16rem;
background-color: black;
width: auto;
}
.image-item {
object-fit: contain;
height: 100%;
width: 100%;
}
html:
<div class="image-container">
<img class="image-item" src="images/Screenshot(1).jpg">
</div>

css less - is it possible to check for element size?

I have few thumbnail image of users and their image can be portrait or wide.
I wish the thumbnails to be in a circle without lose the aspect ratio of it.
So I created a container for each image like that:
<div class='container'>
<img src='' ... />
</div>
With this css:
.container {
border-radius: 50%;
overflow: hidden;
position: relative;
width: 50px;
height: 50px;
img {
width: inherit;
}
}
it works fine with portrait images because the image width inherit from the container.
The problem now is to adapt the same to wide images... I should replace the width with height in order to let in work as expected.
There is a better solution of mine?
Or there is a way with Less to achieve at this?
You should leave the width/height unset and set the max-width/max-height to 100%.
img {
max-width: 100%;
max-height: 100%;
}
This will only downscale images though, not upscale.
width: fit-content; height: fit-content;
.container{
width: 50px;
height: 50px;
border: 1px solid black;
border-radius: 50%;
overflow: hidden;
}
.container > img{
object-fit: cover;
width: 100%;
height: 100%;
}
<div class='container'>
<img src='http://searchengineland.com/figz/wp-content/seloads/2015/12/duckduckgo-logo-wordmark4-1920.png' alt='duck power'>
</div>

make position:fixed DIV fit its parent container without javascript

Here is the code. I want the DIV.fixed-nav (position:fixed) to completely fit its parent DIV.container of which width may change. Is there a pure CSS solution for this?
CSS:
body {
margin: 0;
padding: 0;
}
.container {
border: 1px solid #000000;
margin: 0 auto;
max-width: 600px;
min-width: 400px;
}
.fixed-nav {
background-color: red;
height: 20px;
position: fixed;
width: 100%;
top: 0;
z-index: 99;
}
.content {
background-color: green;
height: 100px;
margin-top: 20px;
}
HTML:
<div class="container">
<div class="fixed-nav">
</div>
<div class="content">
</div>
</div>
Please check the DEMO.
The problem with fixed is that it will always be relative to the browser window. So if you set 100% height on your fixed container it will be 100% of the browser window.
The only way I could think of to achieve this is to use jQuery. Or if you don't need the menu to be fixed and it could be absolute then height 100% will work.

Child with max-height: 100% overflows parent

I'm trying to understand what appears to be unexpected behaviour to me:
I have an element with a max-height of 100% inside a container that also uses a max-height but, unexpectedly, the child overflows the parent:
.container {
background: blue;
padding: 10px;
max-height: 200px;
max-width: 200px;
}
img {
display: block;
max-height: 100%;
max-width: 100%;
}
<div class="container">
<img src="http://placekitten.com/400/500" />
</div>
This is fixed, however, if the parent is given an explicit height:
.container {
background: blue;
padding: 10px;
max-height: 200px;
max-width: 200px;
height: 200px;
}
img {
display: block;
max-height: 100%;
max-width: 100%;
}
<div class="container">
<img src="http://placekitten.com/400/500" />
</div>
Does anyone know why the child would not honour the max-height of its parent in the first example? Why is an explicit height required?
When you specify a percentage for max-height on a child, it is a percentage of the parent's actual height, not the parent's max-height, oddly enough. The same applies to max-width.
So, when you don't specify an explicit height on the parent, then there's no base height for the child's max-height to be calculated from, so max-height computes to none, allowing the child to be as tall as possible. The only other constraint acting on the child now is the max-width of its parent, and since the image itself is taller than it is wide, it overflows the container's height downwards, in order to maintain its aspect ratio while still being as large as possible overall.
When you do specify an explicit height for the parent, then the child knows it has to be at most 100% of that explicit height. That allows it to be constrained to the parent's height (while still maintaining its aspect ratio).
.container {
background: blue;
padding: 10px;
max-height: 200px;
max-width: 200px;
float: left;
margin-right: 20px;
}
.img1 {
display: block;
max-height: 100%;
max-width: 100%;
}
.img2 {
display: block;
max-height: inherit;
max-width: inherit;
}
<!-- example 1 -->
<div class="container">
<img class='img1' src="http://via.placeholder.com/350x450" />
</div>
<!-- example 2 -->
<div class="container">
<img class='img2' src="http://via.placeholder.com/350x450" />
</div>
I played around a little. On a larger image in firefox, I got a good result with using the inherit property value. Will this help you?
.container {
background: blue;
padding: 10px;
max-height: 100px;
max-width: 100px;
text-align:center;
}
img {
max-height: inherit;
max-width: inherit;
}
Instead of going with max-height: 100%/100%, an alternative approach of filling up all the space would be using position: absolute with top/bottom/left/right set to 0.
In other words, the HTML would look like the following:
<div class="flex-content">
<div class="scrollable-content-wrapper">
<div class="scrollable-content">
1, 2, 3
</div>
</div>
</div>
.flex-content {
flex-grow: 1;
position: relative;
width: 100%;
height: 100%;
}
.scrollable-content-wrapper {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
overflow: auto;
}
.scrollable-content {
/* Add styling here */
}
Try it below:
.flex-content {
flex-grow: 1;
position: relative;
width: 100%;
height: 100%;
}
.scrollable-content-wrapper {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
overflow: auto;
}
html {
height: 50%;
width: 50%;
}
body {
height: 100%;
width: 100%;
}
.parent {
height: 100%;
outline: 1px solid red;
}
<html>
<body>
<div class="parent">
<div class="flex-content">
<div class="scrollable-content-wrapper">
<div class="scrollable-content" id="scrollable">
1, 2, 3
</div>
</div>
</div>
</div>
<button onClick="scrollable.innerText += '\nSome more text'" style="margin-top: 1rem;">Add Line</button>
<p>
The red outline represents the parent. Click above to add a line until overflow occurs to see that the size of the parent is not increased.
</p>
</body>
</html>
I found a solution here:
http://www.sitepoint.com/maintain-image-aspect-ratios-responsive-web-design/
The trick is possible because it exists a relation between WIDTH and PADDING-BOTTOM of an element. So:
parent:
container {
height: 0;
padding-bottom: 66%; /* for a 4:3 container size */
}
child (remove all css related to width, i.e. width:100%):
img {
max-height: 100%;
max-width: 100%;
position: absolute;
display:block;
margin:0 auto; /* center */
left:0; /* center */
right:0; /* center */
}
You can use the property object-fit
.cover {
object-fit: cover;
width: 150px;
height: 100px;
}
Like suggested here
A full explanation of this property by Chris Mills in Dev.Opera
And an even better one in CSS-Tricks
It's supported in
Chrome 31+
Safari 7.1+
Firefox 36+
Opera 26+
Android 4.4.4+
iOS 8+
I just checked that vivaldi and chromium support it as well (no surprise here)
It's currently not supported on IE, but... who cares ? Also, iOS supports object-fit, but not object-position, but it will soon.
Here is a solution for a recently opened question marked as a duplicate of this question. The <img> tag was exceeding the max-height of the parent <div>.
Broken: Fiddle
Working: Fiddle
In this case, adding display:flex to the 2 parent <div> tags was the answer
Maybe someone else can explain the reasons behind your problem but you can solve it by specifying the height of the container and then setting the height of the image to be 100%. It is important that the width of the image appears before the height.
<html>
<head>
<style>
.container {
background: blue;
padding: 10px;
height: 100%;
max-height: 200px;
max-width: 300px;
}
.container img {
width: 100%;
height: 100%
}
</style>
</head>
<body>
<div class="container">
<img src="http://placekitten.com/400/500" />
</div>
</body>
</html>
The closest I can get to this is this example:
http://jsfiddle.net/YRFJQ/1/
or
.container {
background: blue;
border: 10px solid blue;
max-height: 200px;
max-width: 200px;
overflow:hidden;
box-sizing:border-box;
}
img {
display: block;
max-height: 100%;
max-width: 100%;
}
The main problem is that the height takes the percentage of the containers height, so it is looking for an explicitly set height in the parent container, not it's max-height.
The only way round this to some extent I can see is the fiddle above where you can hide the overflow, but then the padding still acts as visible space for the image to flow into, and so replacing with a solid border works instead (and then adding border-box to make it 200px if that's the width you need)
Not sure if this would fit with what you need it for, but the best I can seem to get to.
A good solution is to not use height on the parent and use it just on the child with View Port :
Fiddle Example: https://jsfiddle.net/voan3v13/1/
body, html {
width: 100%;
height: 100%;
}
.parent {
width: 400px;
background: green;
}
.child {
max-height: 40vh;
background: blue;
overflow-y: scroll;
}
Containers will already generally wrap their content nicely. It often doesn't work as well the other way around: children don't fill their ancestors nicely. So, set your width/height values on the inner-most element rather than the outer-most element, and let the outer elements wrap their contents.
.container {
background: blue;
padding: 10px;
}
img {
display: block;
max-height: 200px;
max-width: 200px;
}
http://jsfiddle.net/mpalpha/71Lhcb5q/
.container {
display: flex;
background: blue;
padding: 10px;
max-height: 200px;
max-width: 200px;
}
img {
object-fit: contain;
max-height: 100%;
max-width: 100%;
}
<div class="container">
<img src="http://placekitten.com/400/500" />
</div>

Resources