Adapt div to image size and proportion, constrained by maximum dimensions - css

I have some images in divs.
<div class="container">
<img src="http://placehold.it/200x400">
</div>
<div class="container">
<img src="http://placehold.it/300x150">
</div>
I can't find the combination of CSS that fulfils all 3 conditions:
Maximum length of any dimension: 5em
Minimum length of at least 1 dimension: 5em (i.e. either height or width should be 5em) (this is where I think I may need javascript for the boolean OR)
div to completely enclose the img with no excess space (so, the div should have the same aspect ratio as the img)
I'm trying to do the CSS sizing stuff on the divs and then just set the image to width: 100%, height: auto, because I do other sizing functionality on the divs too (resize, move, etc).
Here's the fiddle http://jsfiddle.net/1zvq1rg6/

Use display: inline-block for your divs as you are trying to modify the default display of a div here (size adapting to content).
For the image maximum width/height, the OR you are describing here can be written with max-height and max-width.
Then, if you want no space in your div, just set the padding to 0.
.container {
display: inline-block;
padding: 0;
}
.container > img {
max-width: 5em;
max-height: 5em;
}
http://jsfiddle.net/a1bec8zd

Related

Wrapping Flexbox Without Extra Width

I'm trying to display a bunch of boxes in a container, such that they fill a row then wrap around when they reach the container's maximum width.
I can make the basic layout easily by putting the following styles on the container <div>:
border: 1px solid black;
display: flex;
flex-wrap: wrap;
max-width: calc(100vw - 500px);
That gets me what I want, but the problem is ... let's say each inner box takes up 300px, and on my screen the container has a width of 800px. I'll get two boxes per row.
However, the flexbox and its border won't stop at 600px. It will keep going to the full 800px, even though there's nothing in the remaining 200px.
I've tried playing with the width and max-width properties, but nothing (eg. fit-content, max-content, 100%) made the container constrain itself to the size of its boxes (ie. 600px).
Is it possible to have a wrapping flexbox where the flexbox's width doesn't extend past the boxes inside of it (when there is leftover space)?
Is it possible to have a wrapping flexbox where the flexbox's width doesn't extend past the boxes inside of it (when there is leftover space)?
Yes, though not in the way envisioned in this question.
A parent of dynamic width containing children with explicit width will result in remainder width.
The standard approach is to divide the remainder width among children, growing them dynamically until enough remainder width exists to fit another child.
Drag the bottom right corner to resize this parent horizontally and get a feel for how this approach attacks the problem.
.parent {
background-color: navy;
display: flex;
flex-wrap: wrap;
gap: 2px;
padding: 2px;
width: 400px;
overflow: scroll;
resize: horizontal;
}
.child {
flex-basis: 150px; /* Desired width */
flex-grow: 1; /* Fill up remaning space at a rate of 1 */
background-color: crimson;
height: 75px;
}
<div class="parent">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
There are also many good solutions to this problem using Grid layout.
The approach in dealing with remainder width envisioned in this question appears to be removing it from the parent entirely, which is not possible.
I've tried playing with the width and max-width properties, but nothing (eg. fit-content, max-content, 100%) made the container constrain itself to the size of its boxes (ie. 600px).
In order to calculate how many children can fit at the dynamic width, said width has to be set on the parent, at which point the parent is committed and can't then re-adjust its width. This is the issue with any container and not just Flexbox.

Image border to remain 120x120 while image maintains aspect ratio

The goal I'm trying to achieve on my drupal 7 website is keeping an article image's border a certain size for all images (120x120) while the actual image themselves adjust according to the image style (100x100) and are middle aligned.
(I'm unable to provide example images because I don't have 10 reputation points...)
So for a portrait image the height would be capped at say 100px and the width will be whatever is the aspect ratio is.
Same thing in reverse with a landscape image, with the width being capped at 100px and the height being whatever the aspect ratio is.
All while the grey border stays a 120x120 block, and not changing according the image size.
Let me know if you need any code from my website to help with solving this.
The simplest way to achieve your goal is to use table-cell display property with vertical-align: middle on the parent div, with desired border, height and width set. Than your img should have set max-width and max-height properties to 100%. So having the HTML structure like this:
<div class="img-container">
<img src="..." />
</div>
Your CSS could be:
.img-container {
width: 120px;
height: 120px;
display: table-cell;
vertical-align: middle;
}
.img-container > img {
max-width: 100%;
max-height: 100%;
margin: 0 auto;
display: block;
}
Codepen showing the result: http://codepen.io/anon/pen/BpeOzG

Why does the actual width of a scaled image inside a flex item affect item's width?

I was trying to achieve a header with a height proportional to the screen and containing an image with a title. The attempted solution used a row flex layout. The intention is to have the header a proportion of the viewport/parent height (20%). The width of the image and its parent should match the scaled image width according to the image's aspect ratio. The title's parent div should occupy the remaining width and grow to fill any available horizontal space.
The container is using fixed positioning with a proportional height.
The actual behaviour in Chrome 54 and Firefox 50 is that the image's parent element occupies most of the container width and this width is dictated by the image's actual width (not the scaled width of the image). I don't understand this when the image is scaled down to a fraction of that width.
Example reproducing this behaviour here: https://jsfiddle.net/uy66as8k/
HTML:
<div class="container">
<div class="img-view">
<img src="http://lorempixel.com/800/600/"></img>
</div>
<div class="title-view">
<h1>This is the Title</h1>
</div>
</div
CSS:
.container {
display: flex;
flex-direction: row;
width: 100%;
height: 20%;
margin: 0;
position: fixed;
left: 0;
top: 0;
}
.img-view {
background-color: salmon;
flex: 0 0 auto;
}
.title-view {
background-color: cyan;
flex: 1 0 auto;
}
img {
max-height: 100%;
max-width: 100%;
}
Desired result:
Actual result:
Just set your image container to have a height of 100%.
.img-view {
height: 100%;
...
}
Explanation: Okay so first and foremost you have your container set at 20% of whatever its parent is. In this case its the body. You're pulling in images with random dimensions so you're encountering a situation where their dimensions are exceed their parent containers (.container, .image-view).
The max-height/max-width properties that are assigned to all the images won't know its max until you explicitly set a height on its parent (.image-view). Once that's done it'll constrain itself properly as seen in the fiddle below.
https://jsfiddle.net/uy66as8k/3/

Image takes all the space in flexbox div (100%) without deforming the div

Image takes all the space in flexbox div (100%) without deforming the div. So not the div adjusts to contain an image, but image adjusts to fullfill a div.
I know that in flexbox inner div that contain an image will adjust to size of teh image if you say:
img {height : 100%; width : 100%;}
I need an image in flex div to take all the space of the div. So 100% height and 100% width without affecting the div itself. So whatever is the size of a div I need an image in it to strech and occupy all the avalable space without changing the div itself. How do I do it?
note: if it is not possible with flexbox - then how can I achieve the result using different technic?
Here is the html:
<div class='box-wrap'>
<div class='box'>
<div>
<img src="http://placehold.it/400x400"/>
</div>
</div>
</div>
Here is the css :
.row {
margin-top : 10px;
display : flex;
flex-direction : row;
flex-wrap : wrap;
border : 1px solid silver;
}
.box,.box-wrap {
background : white;
flex : 1 1 8%;
border : 1px solid #aaa;
margin : 10px;
justify-content : space-between;
letter-spacing : 1px;
box-sizing : border-box;
}
.box-wrap {
padding : 0.5em 10px;
background : white;
}
Here is the corresponding codepen : http://codepen.io/anon/pen/WwYeJX
Try using object-fit property for the img :
.box img {
width: 100%;
height: 100%;
object-fit: cover;
object-position: 50% 50%;
}
First of all, to make the img fill the entire height of its container, you can set its container to flex (this then makes the image stop keeping its aspect ration fixed).
Then set the width and height of the container to whichever values you desire:
.box div {
display:flex;
height:600px;
width:100%;
}
And to fill out its full width do this:
.box div img {
width:100%;
}
In this particular case, it resizes the width according to the window and has a fixed height: https://jsfiddle.net/ (demo here)
COMMENT: Also unless there's a very specific reason you need all those nested divs, you could easily remove the innermost (3rd level) div and apply these values to the 2nd level div.

max-height overriding height

As a beginner front-end developer, I find it hard to understand when to use height, min-height and max-height.
I was reading through the docs on MDN about the max-height property and its use in conjunction with height.
According to the docs,
max-height overrides height, but min-height overrides max-height.
But what I don't get is that if we have a div, set a height and max-height, the height seems to take precedence.
For example:
HTML:
<div class="wrapper">
A text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text
</div>
CSS:
.wrapper {
width: 100px; background-color:red; height: 100px; max-height: 1000px;
}
JSBin: https://jsbin.com/kovama/13/edit?html,css,output .
Why doesn't the max-height override height ?
The div only seems to grow as large as the content when I remove the height property.
Moreover, when it is stated that min-height overrides max-height it is only when min-height is actually larger than max-height, is that correct? I find the wording a bit confusing.
Think of min-height and max-height as the minimum and maximum valid calculated value for height.
So if you set min-height:100px; and max-height: 1000px; the element will always have a height between 100 and 1000px. So if you set the height to 500px, then that value is in the allowed range, and that is used as the real height.
But if you set height to 2000px, then than is not within the allowed range, so the height will be reduced to 1000px, so it comes within the allowed range.
But setting both max-height and height in px, don't make a lot of sense. Because then the smallest of max-height and height will always be used.
The normal use is to combine % and px.
if you set something like width:100%; max-width:700px; Then you have set the width to 100% of the available space, but it should still newer be more then 700 pixel.
You can also do it the other way:
width:50%; min-width:500px; This will use half the available space, but always at least 500 pixels.
To better illustrate this here are some examples:
.box {
width: 50px;
height: 50px;
background: red;
display: inline-block;
}
/* box1 will have the height 50px because it doesn't exceed 400px */
.box1 {
max-height: 400px;
}
/* box2 will have the height 40px,
so in this case max-height overrides the height property
This happended because the height of the div was exeeding the maximum allowed
*/
.box2 {
max-height: 40px;
}
/* box3 will have the height 80px
This happens because we said that the minimum should be 80px
so the height and max-height properties are ignored
*/
.box3 {
max-height: 40px;
min-height: 80px;
}
<div class="box box1"></div>
<div class="box box2"></div>
<div class="box box3"></div>
if you set min-height you will apply a minimum limit of height on the div, the height of the div cannot go below that minimum height. Similarly, max-height limits the height of the div to not go more than what set on max-height. Take an example :
div {
min-height: 500px;
max-height: 1000px;
}
from the above css, the height of the div can be anything between 500px and 1000px (both inclusive), the actual height (visible height) will be auto adjusted between this range according to the contents it holds. Now see this css -
div {
height: 600px;
min-height: 500px;
max-height: 1000px;
}
by using the above css, div height is by default set to 600px if content is short then space will appear at the bottom of the div because the height has been fixed to 600px, in case the content wants to expand the div, it will do that, but it will expand to 1000px only.

Resources