Reputation: 1235
I have a fairly specific setup of non-wrapping divs that are aligned next to each other horizontally and are (supposed to) flowing offscreen. Imagine one long row of divs flowing offscreen.
(Later the plan is to use JavaScript to implement some scroll functionality to scroll off-screen parts back on screen).
In each of this divs I have some text on top and an image on the bottom. Of the text on top I cannot know the exact height. The image on the bottom however should fill the remaining vertical space in each div. At the same time the original image aspect ratio should be maintained and the width of the image should determine the width of the containing div.
To clarify: images should not be cropped an not be squeezed or stretched in any way. They should just be scaled/displayed in a way that the fill the remaining vertical space in the div.
Well, I don't get this to work.
Here is what I currently have:
<div id="wrapper">
<div id="slider">
<div class="slide">
<p>Some text</p>
<img src="http://placekitten.com/200/300">
</div>
<div class="slide">
<p>Some text</p>
<img src="http://placekitten.com/600/500">
</div>
<div class="slide">
<p>Some text</p>
<img src="http://placekitten.com/600/200">
</div>
</div>
</div>
* {
margin: 0;
box-sizing: border-box;
overflow-x: hidden;
}
#wrapper {
height: 300px;
position: relative;
}
#slider {
height: 100%;
white-space: nowrap;
position: absolute;
font-size: 0;
background-color: lightgreen;
}
.slide {
height: 100%;
display: inline-block;
margin-right: 15px;
background-color: pink;
}
p {
font-size: 16px;
padding-bottom: 10px;
}
img {
height: 100%;
}
This obviously does not work, as using 100% height on the image makes it to large for its container, scrollbars appear in each div where they should not appear. I tried using flexbox with a flex-grow: 1;
on the image, but that distorts it, especially if I add some padding to the text above.
Here is a jsfiddle demonstrating the issue.
How can I solve this?
(In case this is relevant: we can assume that the text above the image is never wider than the image (as it is only gonna be numbers)).
Upvotes: 3
Views: 1681
Reputation: 1419
Edit
To get a perfect aspect ratio with different font sizes, you can use em
instead of px
.
In this jsfiddle https://jsfiddle.net/ormhukax/, I set the line height to 1.2 and used 1.2em in the CSS calc.
Final CSS:
* {
margin: 0;
box-sizing: border-box;
overflow-x: hidden;
}
#wrapper {
height: 300px;
position: relative;
}
#slider {
height: 100%;
font-size: 0;
background-color: lightgreen;
flex-wrap: nowrap;
display: flex;
}
.slide {
font-size: 48px;
line-height: 1.2;
height: 100%;
display: flex;
flex-direction: column;
align-items: flex-start;
margin-right: 15px;
background-color: pink;
overflow: initial;
}
p {
padding-bottom: 10px;
}
img {
flex: 1;
height: calc(100% - 1.2em - 10px);
}
Take a look at this fiddle: https://jsfiddle.net/4nw03vrd/2/
This is the CSS I used:
* {
margin: 0;
box-sizing: border-box;
overflow-x: hidden;
}
#wrapper {
height: 328px;
position: relative;
}
#slider {
height: 100%;
font-size: 0;
background-color: lightgreen;
flex-wrap: nowrap;
display: flex;
}
.slide {
height: 100%;
display: flex;
flex-direction: column;
align-items: flex-start;
margin-right: 15px;
background-color: pink;
overflow: initial;
}
p {
font-size: 16px;
padding-bottom: 10px;
}
img {
flex: 1;
height: calc(100% - 28px);
}
The calc() is needed to compensate a minor distortion in the aspect ratio, which is negligible if the image is larger enough than text height, and it is basically the font size + the bottom padding
Upvotes: 2
Reputation: 680
I Understand your issue.
Add following css and see if that works :)
* {
margin: 0;
box-sizing: border-box;
overflow-x: hidden;
}
#wrapper {
height: 300px;
position: relative;
}
#slider {
height: 100%;
white-space: nowrap;
position: absolute;
font-size: 0;
background-color: lightgreen;
}
.slide {
height: 100%;
display: inline-block;
margin-right: 15px;
background-color: pink;
}
p {
font-size: 16px;
height:10%;
padding:5px;
}
img {
height: 90%;
}
Upvotes: 0
Reputation: 1667
here is a working fiddle. The margin between the .slide-elements can be modified. Try to play with the value of padding-top property of img. You can see here how to make images scales to fit the allocated area. I used CSS Flexbox to layout the .slider and the .slide.
Here is my final code:
* {
margin: 0;
box-sizing: border-box;
overflow: hidden;
}
#wrapper {
height: 300px;
position: relative;
}
#slider {
display:flex;
flex-direction: row;
height: 100%;
position: absolute;
font-size: 0;
background-color: lightgreen;
overflow: hidden;
}
.slide {
display: flex;
width: auto;
/* border: 1px solid blue; */
flex-direction: column;
justify-content: space-between;
/*height: 100%; */
/* margin: auto;*/
text-align: center;
background-color: pink;
overflow: hidden;
}
..
img {
padding-top: 5%;
object-fit: contain; /* also try `contain` and `fill` */
height: auto;
max-width: 100%;
}
Upvotes: -1
Reputation: 356
Not sure i fully understood what you are trying to achieve, maybe a sketch can help.
However, if i got you well, try using a background-image
instead of an img
tag.
Here is working fiddle https://jsfiddle.net/umf9eh03/
<div id="wrapper">
<div id="slider">
<div class="slide">
<p>Some text and longer text as it goes and yet it is even longer</p>
<div class="img-wrapper" style="background-image: url('http://placekitten.com/200/300')"></div>
</div>
<div class="slide">
<p>Some text</p>
<div class="img-wrapper" style="background-image: url('http://placekitten.com/600/500')"></div>
</div>
<div class="slide">
<p>Some text</p>
<div class="img-wrapper" style="background-image: url('http://placekitten.com/600/200')"></div>
</div>
</div>
</div>
<style>
* {
margin: 0;
box-sizing: border-box;
overflow-x: hidden;
}
#wrapper {
height: 300px;
position: relative;
}
#slider {
height: 100%;
white-space: nowrap;
position: absolute;
font-size: 0;
background-color: lightgreen;
}
.slide {
height: 100%;
display: inline-block;
margin-right: 15px;
background-color: pink;
overflow: hidden;
}
.slide .img-wrapper {
width: 100%;
height: 100%;
background-size: cover;
background-position: center;
}
.slide p {
font-size: 16px;
padding-bottom: 10px;
}
</style>
Upvotes: 0
Reputation: 623
Here is an option that does not require using calc() on the image height.
I have wrapped the images in a div to ensure that flex does not skew their aspect ratio. The vertical alignment of the paragraphs can be controlled with the "align-self" property.
JS Fiddle example: https://jsfiddle.net/byronj/r42dx90g/31/
* {
margin: 0;
box-sizing: border-box;
}
#wrapper {
height: 300px;
position: relative;
}
#slider {
align-items: stretch;
display: flex;
font-size: 0;
background-color: lightgreen;
}
.slide {
display: flex;
flex: 1;
flex-wrap: wrap;
margin-right: 15px;
background-color: pink;
}
.slide div {
flex-basis: 100%;
align-self: flex-end;
}
p {
align-self: flex-end;
flex-basis: 100%;
font-size: 16px;
padding-bottom: 10px;
}
<div id="wrapper">
<div id="slider">
<div class="slide">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc placerat tristique pharetra. Nullam mollis et metus sit amet dictum. Interdum et malesuada fames ac ante ipsum primis in faucibus. Nulla imperdiet egestas mauris. </p>
<div>
<img src="http://placekitten.com/200/300">
</div>
</div>
<div class="slide">
<p>laoreet nec urna. Donec nisl lectus, varius in aliquet eget, dapibus sit amet nibh. Maecenas blandit ipsum eros, a convallis magna varius a.</p>
<div>
<img src="http://placekitten.com/600/300">
</div>
</div>
<div class="slide">
<p>Some text</p>
<div>
<img src="http://placekitten.com/200/300">
</div>
</div>
</div>
</div>
Upvotes: 0