Crop Images in Flexbox Div Assembly that Keeps a Browser Height Ratio - css

For the desktop landing page, I want this composition of images to maintain it's height in relation to the browser height (75vh), otherwise this landing collage will become too horizontal/skinny as someone shrinks the width of their browser.
As it changes proportion with the page getting wider or narrower, I want the images inside to be cropped, not stretched.
I figured out a way to crop them, but only if I set an actual px height to the images. I don't want that. I want the height to be in proportion to the browser height. If I make the divs they're in a ratio of the height of the browser, then the images just stretch inside to fit the div.
<div class="landing">
<div class="landing-side"><img src="landing-1.jpg" alt=""></div>
<div class="landing-side"><img src="landing-2.jpg" alt=""></div>
<div class="landing-center"><img src="landing-3.jpg" alt=""></div>
<div class="landing-side"><img src="landing-4.jpg" alt=""></div>
<div class="landing-side"><img src="landing-5.jpg" alt=""></div>
</div>
.landing {
position: relative;
width: 100%;
height: auto;
display: flex;
}
.landing img {
width: 100%;
height: auto;
display: block;
}
.landing-center,
.landing-side {
height: 75vh;
display: flex;
flex: 1 1 auto;
overflow: hidden;
justify-content: center;
}
.landing-center {width: 40%;}
.landing-side {width: 15%;}
Here is how I did it before - at a certain browser width, the height would be fixed in px, then the side images would start getting cropped*. This is OK, but then I'd have to do make it hop to various specific image heights at different widths. Whereas I want the height of the whole larger container of images to change as the browser changes proportions.
.landing {
position: relative;
width: 100%;
display: flex;
}
.landing img {
width: 100%;
height: auto;
display: block;
}
.landing-center,
.landing-side {
display: flex;
flex: 1 1 auto;
overflow: hidden;
justify-content: center;
}
#media screen and (max-width: 1536px) {
.landing-center {flex-shrink: 0;}
.landing-center img,
.landing-side img {
width: auto;
height: 400px;
}
}
*(Note: I'd prefer that only the side images get cropped in the first code example as well, but that may complicate things too much for this one question.)

To croping an image, you need to use overflow: hidden;
just like:
.croped-content {
position: relative;
width: 25vw;
height: 70vw;
border: 2px solid red;
overflow: hidden;
}
.croped-content img {
min-width: 100%;
min-height: 100%;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
<div class="croped-content">
<img src="https://cdn.pixabay.com/photo/2017/10/06/07/29/guava-2822182_1280.png" alt="guava">
</div>

All I had to do is put the vh here, instead of the px. This works now. I got all mixed up trying too many ways to make this work that I missed the fact that I had put the height attribute to the container instead of the image.
.landing-center {flex-shrink: 0;}
.landing-center img,
.landing-side img {
width: auto;
**height: 75vh;**
}

Related

How to maintain aspect ratio between 16:9 and 4:3 using CSS?

Goal is to render an object without letterboxing, as long as the aspect ratio is within given limits, such as between 16:9 and 4:3.
For example, when the available width of a 16:9 image is reduced below 16:9 aspect ratio, we want to clip the left and right side of the image. If the width is further reduced below 4:3 aspect ratio, we want to keep that aspect ratio and start scaling down.
In this example, you can see how the object scales. The problem with this approach is that scaling happens immediately, as soon as the available space is even one pixel off.
.iframe {
border: 1px solid black;
width: 350px;
height: 350px;
resize: both;
overflow: auto;
}
.wrapper {
background-color: #c05046;
height: 100%;
display: flex;
}
.image {
margin: 0 auto;
max-width: 100%;
max-height: 100%;
object-fit: contain;
}
<div class="iframe">
<div class="wrapper">
<img class="image" src="https://i.ytimg.com/vi/PX-0Nrg4Yhw/maxresdefault.jpg">
</div>
</div>
[An iframe is simulated in the examples and you can change its size for changing the available space.]
The fluid-ratio trick as explained at https://voormedia.com/blog/2012/11/responsive-background-images-with-fixed-or-fluid-aspect-ratios can somehow achieve scaling between 2 ratios, but has several shortcomings:
It works with a fixed height and only scales width, which makes it work horizontally, but not vertically.
The object is not an arbitrary object but rather a background-image, which means this trick probably won't work with video and other objects.
.iframe {
background-color: #c05046;
border: 1px solid black;
width: 350px;
height: 350px;
resize: both;
overflow: auto;
}
.column {
max-width: 640px;
}
figure.fluidratio {
margin: 0;
padding-top: 15%; /* slope */
height: 240px; /* start height */
background-image: url(https://i.ytimg.com/vi/PX-0Nrg4Yhw/maxresdefault.jpg);
background-size: cover;
-moz-background-size: cover; /* Firefox 3.6 */
background-position: center; /* Internet Explorer 7/8 */
}
<div class="iframe">
<div class="column">
<figure class="fluidratio"></figure>
</div>
</div>
I saw somebody suggest using embedded SVG, but didn't get the examples to work.
Any feedback appreciated.
If I understood the problem right, you want to achieve something like this:
.iframe {
border: 1px solid black;
width: 100%;
height: 100%;
}
.container {
width: 100%;
max-width: 130vh;
position: relative;
margin: 0 auto;
}
.wrapper {
background-color: #c05046;
height: 0;
padding-top: 75%;
position: relative;
width: 75%;
left: 50%;
transform: translateX(-50%);
max-width: 640px;
}
.image {
position: absolute;
top: 0;
left: 50%;
transform: translateX(-50%);
height: 100%;
}
<div class="iframe">
<div class="container">
<div class="wrapper">
<img class="image" src="https://i.ytimg.com/vi/PX-0Nrg4Yhw/maxresdefault.jpg">
</div>
</div>
</div>
*the resizing is disabled here, please check in full screen with responsive mode.
Using inner .wrapper, it keeps the part with ratio of 4/3 always visible, but it allows the content to overflow it boundaries. By max-height: 130vh its height keeps scaling also. As it is not based on background-image, it can be used with video as well as image.
The main disadvantage is using a vh unit what keeps it relative to view port size, to parent container height. -> see comment

Sidebar thumbnail image stretching

How to prevent my images from stretching on the sidebar in blogger? I've tried many different CSS for example:
.container {
max-height: 400px;
max-width: 400px;
}
The thumbnails are still stretched and I've tried the overflow:hidden; property as well, which works but cuts out too much of the image and I'd much rather them be resized.
Here's the HTML:
<div id="container">
<img src="http://2.bp.blogspot.com/-THybP4vxGMA/VpwN3LXD-jI/AAAAAAAAAcA/kpZkxwEH9P8/s1600/4afd422d987dac3041f33ffbf34f9367.jpg"/>
</div>
You have to add max-width: 100% and max-height: 100%; to the image in order to not overflow the container. You also have to change max-width and max-height in the #container to width and height. Finally, you used .container instead of #container.
#container {
height: 400px;
width: 400px;
}
#container img {
max-width: 100%;
max-height: 100%;
}
<div id="container"><img src="http://2.bp.blogspot.com/-THybP4vxGMA/VpwN3LXD-jI/AAAAAAAAAcA/kpZkxwEH9P8/s1600/4afd422d987dac3041f33ffbf34f9367.jpg"/></div>
I've figured a solution:
#container {
width: 150px;
height: 150px;
display: block;
position: relative;
overflow: hidden;
}
#container img {
position: absolute;
top: 0;
left: 0;
width: 100%;
}

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>

How can I set responsive image height to 100%?

I have the following HTML:
<article class="post clearfix">
<div class="post-img">
<img src="path/to/img"/>
</div>
<div class="post-details">
[content]
</div>
</article>
And the following CSS:
img {
max-width: 100%;
height: auto;
}
.post-img {
float: left;
width: 33.33%;
margin-right: 1.5em;
overflow: hidden;
}
I want the div.post-img to be 100% as tall as its parent article, and for the img inside it to be 100% tall as well. (It's OK if some of the image is clipped off from the left or right sides.)
The height of the article is unknown, so I can't hard code it.
Thanks in advance!
you can use this class:
.full-height{
height:100vh; /* 100% vertical view port height */
}
for example;
<img class="full-height" alt="" src="test.png" />
this best way for displaying a full height image.
Here is an option to do that http://jsfiddle.net/237u55q1/1/
.post{
display: table;
width: 100%;
table-layout: fixed;
overflow: hidden;
}
.post-img {
display: table-cell;
width: 33.33%;
margin-right: 1.5em;
overflow: hidden;
vertical-align: top;
position: relative;
}
.post-img img{
width: 100%;
height: auto;
position: absolute;
}
.post-details{
display: table-cell;
vertical-align: top;
width: 66.66%;
}
Add or remove content to see the image adopting to the height :)
Use background-image to set an image and background-size: 100% auto to the background image size.

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