I’m looking to implement a full height (no-scroll) layout which contains a square image.
Depending on the available height of the container the image should scale accordingly in width.
So far I’ve attempted to implement the layout using both — floats and flexbox — but any solution (including anything responded to similar questions here) either leads to an overlap between image/container and the additional content to the right or doesn’t calculate 100% as intended (e.g. by including the height of the header).
My most recent attempt looks like this:
body,
html {
padding: 0;
margin: 0;
height: 100%;
}
.page {
height: 100%;
display: flex;
flex-direction: column;
align-items: stretch;
overflow: hidden;
background: #D8D8D8;
}
.header {
background: #FF9C9C;
padding: 5px;
}
.content {
display: flex;
height: 100%;
}
.image-container {
border: 1px solid #7100FF;
height: 100%;
}
img {
display: block;
height: 100%;
width: auto;
}
.aside {
background: #B6F0C7;
flex: 1 1 auto;
}
<div class="page">
<div class="header">
Header
</div>
<div class="content">
<div class="image-container">
<img src="http://placehold.it/100x100" alt="Card image">
</div>
<div class="aside">
<p>Other content</p>
</div>
</div>
</div>
https://jsfiddle.net/s0846ozy/
It’s been a few years since I have worked with CSS. Looking forward to having a rather obvious flaw in my approach pointed out. Thanks!
EDIT:
It seems this issue is browser-specific. I’m using the latest Firefox.
object-fit won't solve the issue as far as I can tell and is something I’ve already explored.
I’ve added a JSFiddle for easier experimentation.
Chrome (expected):
Firefox (actual):
use this:
img {
object-fit: cover;
}
for preserving the aspect-ratio!!
Related
I'd like to know how to shrink a row of images so that they all fit within a div with an unspecified height. The images should never scale up beyond their native height, and they must maintain their aspect ratio. Also, I'd like the height of the containing div to be limited to the native height of the tallest image. The image tags have no height or width attributes.
Here's a fiddle with what I have so far. I approached this using flexbox and object-fit: scale-down. The row of images in question are gray and are in the div with the green background. They currently do not scale at all, but they are at least centered vertically and horizontally how I'd like them to be. Here are before and after images of the effect I'd like to achieve (sorry for switching the green background to yellow in the images). Additional details below the code snippet, but that about sums up the basic question.
body {
font-family: arial;
font-size: 26px;
text-align: center;
color: black;
background-color: white;
}
.smallhint {
font-size: 16px;
color: #8c8c8c;
}
img {
padding: 0;
margin: 0;
font-size: 0;
display: block;
object-fit: scale-down;
min-height: 0;
}
.flex-column {
display: flex;
flex-direction: column;
padding: 0px;
margin: 0px;
height: 90vh;
flex-grow: 0;
min-width: 0;
min-height: 0;
}
.flex-row {
display: flex;
flex-direction: row;
flex: 0 1.5 auto;
justify-content: center;
align-items: center;
background-color: green;
}
.context {
display: flex;
flex-direction: column;
max-height: 100%;
background-color: blue;
}
.primary {
position: relative;
z-index: 0;
right: 0;
bottom: 0;
padding: 0;
font-size: 0;
min-height: 0;
align-items: end;
background-color: orange;
}
.primary img {
margin-left: auto;
margin-right: auto;
border-style: solid;
border-width: 3px;
border-color: black;
height: calc(100% - 2*3px);
}
.mask {
position: absolute;
z-index: 1;
top: 0;
right: 0;
width: 100%;
height: 100%;
font-size: 0;
}
.nonimage {
padding-top: 5px;
display: inline;
background-color: pink;
}
<div class="flex-column">
<div class="primary">
<img src="https://via.placeholder.com/200">
<div class="mask">
<img src="https://via.placeholder.com/200/FF000">
</div>
</div>
<div class="flex-row">
<div class="context">
<img src="https://via.placeholder.com/75x150">
</div>
<div class="context">
<img src="https://via.placeholder.com/150x75">
</div>
</div>
<div class="nonimage">
<div class="smallhint">Some Text<br>Other Text</div>
</div>
</div>
I'm working on a (fixed-height) interface styled with CSS and will likely be asking a series of questions. I'm not great at CSS, so I'm open to approaches that are very different from my failed attempt!
At the top is a single centered image ("primary image"), below that are two other images ("secondary images") in a row, and below that is some text. Eventually, I'd like both sets of images to be responsive to changes in the height and width of the browser. However, I'd like to preferentially scale down the secondary images more than the primary image when the browser is too short to contain everything at native dimensions. For this, it seemed like flexbox containers with various flex-grow values would work here; it seems to work with the primary image somewhat, but the secondary images refuse to scale.
Also, I'm aware that, even if my current approach worked, the object-fit: scale-down strategy would leave behind some unwanted "padding" that will result in visual space between the secondary images. I have a feeling a very different approach may be required to get the effect that I want in the end, since I want the images to sit adjacent to each other without extra space around them. Furthermore, there also seems to be an issue with the container itself when the browser becomes very thin, since a scrollbar appears but it should always be 90vh.
Thank you all for the input!
Add a min-height: 0; rule for .flex-row. I guess that means it was pretty close to working when I asked the question.
This solution retains the issue I mention in my question about the additional "padding" created around images when object-fit: scale-down (or cover) is used. So, that means I'll be asking another question about that topic!
UPDATE:
I don't know why I was downvoted, if someone could tell me what I did wrong it would be cool, If you are sure about your answer I could accept a No or yes as answer and a simple idea of how to do it.
.gallery {
display: inline-flex;
align-items: center;
justify-content: center;
text-align: center;
}
.gallery img {
min-width: 33%;
max-width: 33%;
min-height: 120px;
max-height: 120px;
}
<div class="gallery">
<!--Images users provide examples:-->
<img src="https://unsplash.it/200">
<img src="https://unsplash.it/200/100">
<img src="https://unsplash.it/100/300">
<!--etc...-->
</div>
That's ok but I noticed that some images look ugly because they are horizontal images or vertical and I'm giving them a squared shape (I don't like how they look when I give them width/height auto because they all together look disordered and bad).
What I recently did was In another part of the web was to do something like:
.image-cool {
min-width: 230px;
max-width: 230px;
min-height: 280px;
max-height: 280px;
/*Has a rectangle shape*/
background: #eee;
}
.image-cool img {
max-width: 230px;
max-height: 230px;
}
<div class="image-cool">
<img src="https://unsplash.it/200">
</div>
That last code works in the next way:
If you put multiple divs with images inside all will be aligned in the screen and the images will adjust its width and height limited by their container and images don't look bad anymore.
The question here is if I could achieve the same result of the second code in the first code using CSS and without adding more HTML like a div or container.
Why would I not want another div?
Because the current HTML of the first part is essential in that way for some long scripts, Yeah I could modify it all but It will take time and I'm just asking to see if I can save some time.
Thanks a lot for your time! :)
Instead of using img tag, you can use background-image and background-size: cover on a div therefore any image size can fit into the element.
.gallery {
display: flex;
justify-content: center;
align-items: center;
flex-wrap: wrap;
text-align: center;
}
.gallery-image {
width: 33%;
height: 120px;
background-repeat: no-repeat;
background-position: center center;
background-size: cover;
}
<div class="gallery">
<div class="gallery-image" style="background-image:url(https://unsplash.it/100/300)"></div>
<div class="gallery-image" style="background-image:url(https://unsplash.it/200/100)"></div>
<div class="gallery-image" style="background-image:url(https://unsplash.it/200)"></div>
</div>
I have a img that resizes to the footer height (10vh) with max-height: 100%. In Dev tools the size of each element seems to be OK but somehow the page is overflowing and I can`t figure out where the extra px height comes from.
Here is my code:
* {
margin: 0 !important;
padding: 0 !important;
}
body {
background-color: yellow;
}
.header {
height: 10vh;
background-color: red;
}
.content {
height: 80vh;
background-color: green;
}
.footer {
height: 10vh;
background-color: blue;
}
img {
max-height: 100%;
max-width: 100%;
}
<div class="header">
</div>
<div class="content">
</div>
<div class="footer">
<img src="https://pixabay.com/static/uploads/photo/2016/01/19/18/00/city-1150026_960_720.jpg" alt="" />
</div>
Why does this happen and how can I avoid it?
UPDATE: I had no idea that the default display: inline of <img> was causing this. Now that I know it is much easier to find other answers to my question (I just didn`t know what to search for). For those who may be searching for this issue and find my question here is a complete answer: https://stackoverflow.com/a/31445364/6453726
SOLUTION: Add vertical-align: top to the <img>.
Add display:block; to your img selector
img {
max-height: 100%;
max-width: 100%;
display: block;
}
I am working with flex items so I think it could be the problem of why my code is making a strange behaviour.
I have .flexContainer class that has a max-width property. After I resize the window, I want to change this max-width property to a higher value but if I set my media query as:
#media screen and (max-width: 850px){
.flexContainer{
max-width: 60%;
}
}
the max-width of the element is changing at 835px instead of 850px.
Here is my code:
HTML:
<div id="container">
<div id="left" class="block">Left</div>
<div id="center" class="block">
<div class="flexContainer">
<div class="flexDiv"></div>
</div>
<div class="flexContainer">
<div class="flexDiv"></div>
</div>
<div class="flexContainer">
<div class="flexDiv"></div>
</div>
</div>
<div id="right" class="block">Right</div>
</div>
CSS:
html, body{
width: 100%;
height: 100%;
}
#container{
display: flex;
height: 100%;
background-color: blue;
}
.block{
flex: 1;
}
#left{
background-color: green;
}
#center{
display: flex;
flex: 1;
flex-wrap: wrap;
align-content: flex-start;
}
#right{
background-color: orange;
}
.flexContainer{
flex: 1;
min-width: 100px;
max-width: 50%;
box-sizing: border-box;
height: 150px;
background-color: red;
padding: 10px;
}
.flexDiv{
width: 100%;
height: 100%;
background-color: yellow;
}
#media screen and (max-width: 850px){
.flexContainer{
max-width: 60%;
}
}
JSFiddle in which you can see that the max-width property changes at 835px instead of 850px.
EDIT: I add two screenshots so you can see it:
Why the media query is being executed after it should?
I found my problem here. Just I had to remove the margin of the body tag.
I will try to reproduce the effect that I am having on my real project (in which I have body tag fixed) and edit the question again.
EDIT: It seems that it was a bug or something similar of Google Chrome because I cannot reproduce the error anymore.
The error that I was getting is that when I looked at html tag on my Google Chrome inspector, it gave to me the wrong values for the webpage (around 30px less, and I do not have any padding/margin around it) so I thought that the media queries were being executed in the wrong width of the screen.
I know this is a "stupid" solution but it worked again when I closed and re-opened Google Chrome. Now it works like normal behaviour.
I'm having an issue with flexbox on IE11 and while I'm aware there's lots of known issue, I haven't been able to find a solution...
<div class="latest-posts">
<article class="post-grid">
<img src="http://lorempixel.com/image_output/cats-q-c-640-480-4.jpg" alt="" />
<div class="article-content">
<h2>THIS IS POST TITLE</h2>
<p>BLAH</p>
</div>
</article>
</div>
And the CSS...
img {
max-width: 100%;
}
.latest-posts {
margin: 30px auto;
}
article.post-grid {
width: 375px;
float: left;
margin: 0 25px 100px 0;
padding-bottom: 20px;
background-color: #fff;
border: 1px solid #f3f3f3;
border-radius: 2px;
font-size: 14px;
line-height: 26px;
display: flex;
flex: 1 0 auto;
flex-direction: column;
justify-content: flex-start;
align-content: flex-start;
}
.article-content {
padding: 20px 35px;
}
Images are getting stretched within a flex container.
Applying align-items: flex-start (I figured, since "stretched" is the default value...) or justify-content: flex-start doesn't seem to work.
Codepen: example of what I mean
What am I doing wrong?
to avoid this funny behavior, you may reset the flex-shrink property.
This looks like a bug, despite what Microsoft says:
<'flex-shrink'>
Sets the flex shrink factor or negative flexibility for the flex item. The flex shrink factor determines how much a flex item will shrink relative to the other items in the flex container.
If omitted, the element's negative flexibility is "0". A negative value is not valid.
Source: https://msdn.microsoft.com/en-us/library/jj127297%28v=vs.85%29.aspx https://msdn.microsoft.com/en-us//library/hh772069%28v=vs.85%29.aspx
img {
max-width: 100%;
flex-shrink: 0;
}
img {
max-width: 100%;
flex-shrink: 0;
}
.latest-posts {
margin: 30px auto;
}
article.post-grid {
width: 375px;
float: left;
margin: 0 25px 100px 0;
padding-bottom: 20px;
background-color: #fff;
border: 1px solid #f3f3f3;
border-radius: 2px;
font-size: 14px;
line-height: 26px;
display: flex;
flex: 1 0 auto;
flex-direction: column;
justify-content: flex-start;
align-content: flex-start;
}
article.post-grid .article-content {
padding: 20px 35px;
}
<div class="latest-posts">
<article class="post-grid">
<img src="http://lorempixel.com/image_output/cats-q-c-640-480-4.jpg" alt="" />
<div class="article-content">
<h2>THIS IS POST TITLE</h2>
<p>Society excited by cottage private an it esteems. Fully begin on by wound an. Girl rich in do up or both. At declared in as rejoiced of together.</p>
</div>
</article>
<article class="post-grid">
<img src="http://lorempixel.com/image_output/cats-q-c-640-480-4.jpg" alt="" />
<div class="article-content">
<h2>MUCH LONGER POST TITLE TO ILLUSTRATE HEIGHTS</h2>
<p>Recommend new contented intention improving bed performed age.</p>
</div>
</article>
<article class="post-grid">
<img src="http://lorempixel.com/image_output/cats-q-c-640-480-4.jpg" alt="" />
<div class="article-content">
<h2>SHORT TITLE</h2>
<p>Merry alone do it burst me songs. Sorry equal charm joy her those folly ham. In they no is many both. Recommend new contented intention improving bed performed age. Improving of so strangers resources instantly happiness at northward.</p>
</div>
</article>
</div>
http://codepen.io/anon/pen/KzBOvq
I had image stretch on the cross-axis (stretch in height, using flex-direction: row).
This Stack Overflow Q/A helped me solve it:
Link here
I had to set the following CSS on my img:
align-self: flex-start;
You might need another value than flex-start of course, depending on your goal. Mine is to have my image be at the top of the row.
I had a similar bug in IE11.
The styles were taken from Bootstrap 4.1, so for the fluid images I had:
.img-fluid {
border: none;
height: auto;
max-width: 100%;
}
In my case it appeared that the reason was in max-width: 100% so when I changed it to width: 100% the bug disappeared:
.img-fluid {
border: none;
height: auto;
width: 100%;
}
This solution is not for everyone's case but I hope it would be helpful.
in my case combination of "flex-shrink: 0" suggested by G-Cyr and "align-self: flex-begin" suggested by Rick Schoonbeek did the trick. I had a wrapper which was using flex box to center the image with a "justify-content: center;"
All was good in IE 11, Chrome, Safari except IE Edge was not able to display correctly. adding the two attributes on image resolved the problem with IE Edge.
I tried every solution here but nothing worked. The only thing I was using flexbox for was to vertically center an image shown when hovering another image. So I just used a more classic solution à la top: 50%; transform: translateY(-50%) and then it was ok. So essentially not using flexbox at all then.. #hateIE
I had an issue with stretched product images in IE11, and I did some research and tried different things.
This was my code:
.productImage {
position: relative;
overflow: hidden;
img {
position: absolute;
display: block;
height: 100%;
object-fit: contain;
top: 0;
}
}
I then realized that my image height: 100% was the culprit of the stretched image, and I simply removed my height, but then my image was at the top of my .productImage container instead of being centered vertically. I introduced flex here and positioned it through a simple align-items: center, but this of course didn't work in IE11. I also tried the flex-shrink: 0 but that didn't work either.
I then went ahead to skip using flex and tried the classic top: 50%; left: 50%; transform: translate(-50%, -50%); but this wasn't good either since I already had a transform in use for my zoom on hover effect on the image.
I ended up with this solution instead:
.productImage {
position: relative;
overflow: hidden;
img {
position: absolute;
display: block;
top: 0;
right: 0;
bottom: 0;
left: 0;
margin: auto;
}
}
It worked like a charm