Reputation: 57316
I'm having a very peculiar problem that I've been trying to solve for the last 2 days to no avail. The page I'm building has the following structure:
I can easily achieve the A-B layout with the overall parent having display: flex; flex-direction: column; align-items: stretch
and setting A to be flex: 0 0 auto
and B to be flex: 1 1 0; min-height: 100px;
However I'm having real trouble layout out C and D inside B. I feel like the flex/row is the right approach for B, but I just can't get the specifics. So I'm trying:
.B {
display: flex;
flex-direction: row;
align-items: stretch;
justify-content: space-between;
}
.C {
flex: 1 1 0;
}
.D {
object-fit: scale-down;
}
But clearly this is not sufficient. The image either doesn't scale down at all, scales down but distorted or leaves a lot of space around if I set it to also have flex: 1 1 0
with min width.
Any ideas how I can achieve what I need here?
UPDATE: I tried putting jsfiddle together here - https://jsfiddle.net/2gsrzwwq/3/ - but for some reason it wouldn't even honour height:100%
on the parent. As far as the image fitting goes, I need the image to scale down to the height of the D div and then have the D block decrease in width to just contain the scaled down image - and for C block to occupy the remaining width.
Upvotes: 8
Views: 8523
Reputation: 4971
I was struggling with exactly the same problem myself:
Maximum possible size image and div expanding to fill the space
I came up with the following solution, which I've also provided as an answer to my own question. See https://jsfiddle.net/wwhyte/vjLps7qs/; replace the image with http://placekitten.com/1600/900 to see landscape behavior.
.container {
width: calc(100vw);
height: 100vh;
overflow: hidden;
}
.top {
height: 1.25em;
background: yellow;
}
.innerCtr {
height: 100%;
overflow: hidden;
}
.left {
height: 100%;
background: red;
overflow: hidden;
}
.right {
max-height: 100%;
max-width: 80%;
background: blue;
float: right;
object-fit: contain;
overflow: hidden;
position: relative;
top: 50%;
transform: translateY(-52%) scale(0.95);
}
<div class="container">
<div class="top">
</div>
<div class="innerCtr">
<img class="right" src="http://placekitten.com/1600/900">
<div class="left">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure
dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum</div>
</div>
</div>
What I think is happening is:
Even this isn't quite ideal. There's some weird interaction between the height of the top bar and the height of the image so that the bottom of the image is pushed out of the display. The amount pushed out is less than but related to the height of the top bar -- I haven't fully investigated. If you remove the top bar the CSS above behaves perfectly. I addressed this with the 95% scale and slight adjustment to the Y-transform, but this still doesn't behave exactly right at small window sizes -- the image isn't perfectly vertically centered. I had thought that setting height=calc(100vh-1.25em) on the container class might fix this, but in fact it breaks the vertical scaling of the image so it now only scales horizontally. This was completely unexpected behavior! But other than that, this meets my needs.
Upvotes: 0
Reputation: 57316
After a lot more struggle and another sleepless night, I came up with something sort-of working. The sacrifice I had to make is not adjusting the width of the image container and always settling on it being half the width of the screen (note that in the real app, there are no background colours, so it won't look as strange, rather there will be some extra white space). I'll have to discuss this with the client, but I think I'll be able to convince them. Here's what I came up with:
https://jsfiddle.net/2gsrzwwq/6/
HTML:
<div class="page">
<div class="A">
</div>
<div class="B">
<div class="C">
</div>
<div class="D">
<img src="http://res.freestockphotos.biz/pictures/10/10677-illustration-of-a-red-lobster-pv.png"/>
</div>
</div>
</div>
CSS:
div {
box-sizing: border-box;
}
.page {
width: 100%;
height: 250px;
border: solid 1px black;
margin: 5px;
background-color: lightYellow;
display: flex;
flex-direction: column;
align-items: stretch;
justify-content: flex-start;
}
.A {
background-color: lightPink;
margin: 5px;
flex: 0 0 50px;
}
.B {
background-color: lightBlue;
margin: 5px;
flex: 1 1 0;
min-height: 80px;
display: flex;
flex-direction: row;
align-items: stretch;
justify-content: space-between
}
.C {
background-color: lightGreen;
margin: 5px;
flex: 1 1 0;
min-width: 100px;
}
.D {
background-color: lightGrey;
margin: 5px;
flex: 1 1 0;
min-height: 50px;
display: flex;
justify-content: flex-end;
}
.D img {
flex: 1 1 0;
max-height: 100%;
max-width: 200px;
object-fit: scale-down;
object-position: top right;
}
Upvotes: 5