Make img in flexbox height 100% & responsive, inconsistent flexbox rendering result - html

I'm trying to put 4 images in a flexbox div in a parent flexbox, with total height 100%, without stretching out of the parent flexbox. I've searched a lot, but I didn't found something useful.
I have made a minimum example:
html {
height: 100%;
}
body {
height: 100%;
margin: 0;
display: flex;
}
main {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
background-color: yellowgreen;
}
.imgs {
flex: 1;
display: flex;
justify-content: center;
align-items: center;
}
.img100 {
max-width: 100%;
max-height: 100%;
vertical-align: middle;
}
<main>
<!--
Weird. Chromium (Chrome & new Edge) usually renders height 100%,
but not height-responsive; sometimes renders scroll bar.
Firefox always renders the scroll bar result.
-->
<div class="imgs">
<img class="img100" src="https://imgur.com/ruE1EBV.jpg">
</div>
<div class="imgs">
<img class="img100" src="https://imgur.com/ruE1EBV.jpg">
</div>
<div class="imgs">
<img class="img100" src="https://imgur.com/ruE1EBV.jpg">
</div>
<div class="imgs">
<img class="img100" src="https://imgur.com/ruE1EBV.jpg">
</div>
</main>
When opening this example, chromium-based browsers(Chrome, new Edge) usually render height 100%, the desired result, but it is not "height-responsive": the max height of the images remains fixed once the page is fully loaded.
What even worse is, sometimes they give the stretched result with scrollbar; and Firefox always give me the stretched result with scrollbar, which is not what I want.
Try opening this S.O. page in Chromium & Firefox, and run the snippet. The results are different, too.
Chromium (almost always left, rarely right):
Firefox (always):
Any way to achieve what I want? The wrapping div and parent div may be something other than flexbox. I just want the images staying in the div, with width-responsive & height-responsive.
Also, any reason why Chromium browsers' rendering results are not consistent? Is my example missing something?
I know I can use the background image technique, so I can put image in div without changing layout at all. But I want only the image part clickable, so there must be an image element there corresponding to the clickable area.
background-image example:
html {
height: 100%;
}
body {
height: 100%;
margin: 0;
display: flex;
}
main {
flex: 1;
display: flex;
flex-direction: column;
background-color: yellowgreen;
}
a {
flex: 1;
background-image: url('https://imgur.com/ruE1EBV.jpg');
background-repeat: no-repeat;
background-size: contain;
background-position: center;
border: 5px solid red;
}
<main>
</main>
Edit:
Equal row heights in flex-direction: column is okay when the content inside doesn't contain any images. I think the tricky part is the images. They just stretch...
html {
height: 100%;
}
body {
height: 100%;
margin: 0;
display: flex;
}
main {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
background-color: yellowgreen;
}
.imgs {
flex: 1;
display: flex;
justify-content: center;
align-items: center;
border: 5px solid red;
}
.img100 {
max-width: 100%;
max-height: 100%;
vertical-align: middle;
}
<main>
<div class="imgs">
hello
</div>
<div class="imgs">
hello
</div>
<div class="imgs">
hello
</div>
<div class="imgs">
hello
</div>
</main>

Well, I found an easy answer to fix this simple minimum example.
Just add overflow: hidden to .imgs, so images don't grow out of main.
html {
height: 100%;
}
body {
height: 100%;
margin: 0;
display: flex;
}
main {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
background-color: yellowgreen;
}
.imgs {
flex: 1;
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
}
.img100 {
max-width: 100%;
max-height: 100%;
vertical-align: middle;
}
<main>
<div class="imgs">
<img class="img100" src="https://imgur.com/ruE1EBV.jpg">
</div>
<div class="imgs">
<img class="img100" src="https://imgur.com/ruE1EBV.jpg">
</div>
<div class="imgs">
<img class="img100" src="https://imgur.com/ruE1EBV.jpg">
</div>
<div class="imgs">
<img class="img100" src="https://imgur.com/ruE1EBV.jpg">
</div>
</main>
Applying this to my actual, much more huge layout did fix my layout.
So all I need to do is to carefully inspect my overflows.
Why Chromium behaves differently: stackoverflow: Why do Chrome and Firefox show different flex layout results?

Related

How to make this image move to the right?

So, I was doing this Frontend Mentor challenge (at https://www.frontendmentor.io/challenges/notifications-page-DqK5QAmKbC) while I had run into this problem - I couldn't align the "Chess" image in the "Kimberly Smith" notification to the right.
Here is all the code I have written related to the notification:
The HTML:
<div class="notification">
<div class="notification__container">
<img src="assets\images\avatar-kimberly-smith.webp" class="image" />
<div class="notification-formatting">
<div class="align-right">
<div><strong>Kimberly Smith</strong> commented on your picture
<br /><time>1 week ago</time>
</div>
<div class="img-container"><img src="assets/images/image-chess.webp" alt="Chess" class="image chess"></div>
</div>
</div>
</div>
</div>
The CSS:
img,
picture,
svg,
video {
display: block;
max-width: 100%;
}
.notification {
background-color: #f6fafd;
display: flex;
align-items: center;
}
.notification__container {
display: flex;
align-items: center;
}
.image {
display: flex;
align-items: center;
width: 50px;
margin-right: 5px;
}
.notification_image--main-message-content {
display: flex;
}
.align-right {
display: flex;
}
Here is the Output
Here is the Expected Output
Here are the solutions I have tried:
display: block;
margin-left: auto;
float: right;
text-align: right;
display: flex;
justify-content: right;
Here is the live website: https://prismatic-capybara-4ba8da.netlify.app/
Here is the GitHub Repository for deeper reference: https://github.com/vishalscodes/frontendmentor-notifications-page
Thank You.
It's possible to massively simplify your markup as follows:
Class notification. This is a flex box so items will try to fit side by side on one line. As the user's image, the main text and the 'chess' image are all on one line we don't need to add any more divs to this. We can just insert them directly, especially as you've made all img elements as blocks (this is always a good move imho).
Class notification-formatting is used to isolate the text so that the text and time stack on top of each other. As this is a flex item, this will try to shrink to fit the content.
We don't need a wrapper around the image with the chess class as that's already a block level element so to get that to move to the right I've added an align-right class. That simply has an inline-margin of auto 0. This is a fairly standard way of moving elements to the right of the page.
Some good resources here:
Complete guide to flexbox on css tricks
Margin on css tricks
Useful css reset by Kevin Powell (e.g. setting img to block)
Any questions just drop me a comment and I'll try help out.
img,
picture,
svg,
video {
display: block;
max-width: 100%;
}
.notification {
background-color: #f6fafd;
display: flex;
gap: 5px; /* I've removed the margin-right from your image and set the gap on the parent element so your 'chess' image moves all the way to the right */
}
.image {
width: 50px;
border-radius: 5px;
}
.align-right {
margin-inline: auto 0; /* if we set the right margin to 0 then setting the left margin to 'auto' causes it to expand to fit the available width */
}
.round {
border-radius: 100vw; /* make the radius massive so it defaults to a circle */
}
<div class="notification">
<img src="https://picsum.photos/id/64/50/50" class="image round" />
<div class="notification-formatting">
<strong>Kimberly Smith</strong> commented on your picture
<br /><time>1 week ago</time>
</div>
<img src="https://picsum.photos/id/237/50/50" alt="Chess" class="image align-right">
</div>
Base on your code you can set to
.align-right {justify-content: space-between; width: 100%; display: flex;}
and set 100% width to all parents divs you can see code bellow
img,
picture,
svg,
video {
display: block;
max-width: 100%;
}
.notification {
width: 100%;
background-color: #f6fafd;
display: flex;
align-items: center;
}
.notification-formatting {
width: 100%;
}
.notification__container {
display: flex;
align-items: center;
width: 100%;
}
.image {
display: flex;
align-items: center;
width: 50px;
margin-right: 5px;
}
.notification_image--main-message-content {
display: flex;
}
.align-right {
display: flex;
justify-content: space-between;
width: 100%;
}
<div class="notification">
<div class="notification__container">
<img src="assets\images\avatar-kimberly-smith.webp" class="image" />
<div class="notification-formatting">
<div class="align-right">
<div><strong>Kimberly Smith</strong> commented on your picture
<br /><time>1 week ago</time></div>
<div class="img-container"><img src="assets/images/image-chess.webp" alt="Chess" class="image chess"></div>
</div>
</div>
</div>
</div>

Images inside a display:flex item partially distorted or cut off

I am currently building a horizontal scroller for an image gallery.
The scroller works so far, but unfortunately the images are partially distorted or part of it is cut off.
I suspect that it has something to do with Flexbox ...
Here you can see the code of the scroll slider (markup + scss)
https://jsfiddle.net/3cdkxbvm/
.scroll-slider-title {
display: flex;
justify-content: center;
flex-direction: column;
align-items: flex-start;
margin-bottom: 0.5em;
font-weight: 700;
}
.scroll-slider-title svg {
margin-right: 1rem;
font-size: 1.5em;
}
.scroll-slider-title a {
color: inherit;
}
.scroll-slider {
width: 100%;
overflow: hidden;
position: relative;
margin-bottom: 4rem;
}
.scroll-slider .scroll-slider-pane {
width: 100%;
overflow: auto;
padding: 2rem 0 3rem;
box-sizing: border-box;
-webkit-overflow-scrolling: touch;
scroll-behavior: smooth;
}
.scroll-slider .scroll-slider-track {
display: inline-block;
padding: 0;
margin: 0;
}
.image-gallery {
display: flex;
}
.image-gallery .image-gallery-item {
margin-right: 1rem;
overflow: hidden;
flex-shrink: 0;
width: auto;
}
.image-gallery .image-gallery-item img {
height: 100%;
width: auto;
}
<div class="scroll-slider" id="js_image_gallery">
<div class="scroll-slider-pane">
<div class="scroll-slider-track">
<div class="image-gallery">
<div class="image-gallery-item">
<img src="https://s1.waazz.com/thumbs/l800/83/1083_af8cbfd999d37bbac86691e9c5ffb76f">
</div>
<div class="image-gallery-item">
<img src="https://s1.waazz.com/thumbs/p800/84/1084_72a6840640a8650cc01f41d55346973c">
</div>
<div class="image-gallery-item">
<img src="https://s1.waazz.com/thumbs/p800/85/1085_5f18260d83ea0790be5a8029b7638872">
</div>
<div class="image-gallery-item">
<img src="https://s1.waazz.com/thumbs/p800/86/1086_66daf815df8570e11564f3426c074f3c">
</div>
</div>
</div>
</div>
</div>
Now the all-important question:
Why are my images partially distorted or part of it is cut off.? And how can I solve this?
It is important that the pictures always have the same height. However, the width may vary depending on the picture.
Here you can find a working fiddle where you can see the problem with the images. I have tested it in the latest Chrome version.
https://jsfiddle.net/3cdkxbvm/
Thanks in advance for your help
You probably need something like this:
HTML
<div class="scroll-slider-track">
<div class="image-gallery">
<div class="image-gallery-item">
<img src="https://s1.waazz.com/thumbs/l800/83/1083_af8cbfd999d37bbac86691e9c5ffb76f">
</div>
<div class="image-gallery-item">
<img src="https://s1.waazz.com/thumbs/p800/84/1084_72a6840640a8650cc01f41d55346973c">
</div>
<div class="image-gallery-item">
<img src="https://s1.waazz.com/thumbs/p800/85/1085_5f18260d83ea0790be5a8029b7638872">
</div>
<div class="image-gallery-item">
<img src="https://s1.waazz.com/thumbs/p800/86/1086_66daf815df8570e11564f3426c074f3c">
</div>
</div>
</div>
SCSS
.scroll-slider-track {
// do not set a height for this container
// because the horizontal scroller also needs
// space and this varies in every browser
width: 800px; // set the width you need
overflow: auto;
}
.image-gallery {
height: 300px; // height of the gallery images, set one you like best
display: flex;
flex-flow: row nowrap;
}
.image-gallery-item {
flex: 0 0 auto; // turn off shrink and grow behavior
// needed, so the img element can calculate its height
// using a value in percent:
height: 100%;
&:not(:first-child) { // addressing all items except the first one
margin-left: 1rem;
}
img {
height: 100%;
width: auto; // this will keep the image ratio intact
flex: 0 0 auto; // turn off shrink and grow behavior
display: block; // making sure, no whitespace or line-height issues occur
}
}
Remove margin-right or add margin-right more than 1rem

Responsive CSS Image size effects row sizes

I know this sounds like it's been asked before but I've played around with a lot of techniques I've found from other questions and nothing seems to get the desired effect I need.
I'm trying to make something that will be responsive like this:
Responsive Example gif
I basically need an image to be centered, where the image is at 100% size.
Here is what I tried to get this effect:
I first made a div containing three child divs for "columns". Then inside the center column I made three child divs for "rows". Now I need the image to fill the max width it's allowed while still maintain that square aspect ratio. As well the height of the image should determine the height of the top and bottom rows.
Then it should just be a matter of having the text inside the top and bottom row align to the bottom and top of their divs respectively.
This would look something like this:
HTML Visualization of columns
HTML Visualization of center rows
The issue I'm running into is I can't seem to get the center image to determine the heights of the rows above and below it.
I've tried...
Flexbox
using vh (view height)
and a bit of using calc() but to no luck
Setting aspect ration with padding-top: 100%
What the code looks like
/* .row & .col from materialize.css */
.full {
height: 100vh;
}
.art_top {
height: 10vh;
/* I Don't actually want this fixed though */
padding-bottom: 10px;
display: flex;
}
.art_center {
height: 80vh;
/* I Don't actually want this fixed though */
}
.art_bottom {
height: 10vh;
/* I Don't actually want this fixed though */
padding-top: 10px;
display: flex;
}
#cover_art {
width: 100%;
height: 100%;
background: center / cover no-repeat;
}
#song_name {
align-self: flex-end;
}
#artist_name {
align-self: flex-start;
}
<div class="row">
<div class="col s2 m3 full"></div>
<div class="col s8 m6 full">
<div class="row art_top">
<a id="song_name" class="bold-title"></a>
</div>
<div class="row art_center">
<div id="cover_art"></div>
</div>
<div class="row art_bottom">
<a id="artist_name" class="bold-title"></a>
</div>
</div>
<div class="col s2 m3 full"></div>
</div>
Flexbox makes this kind of layout very straightforward. The trick is selectively allowing items to flex or shrink.
The flex property shorthand takes 3 values for flex-grow, flex-shrink, and flex-basis (the initial width or height depending on flex direction). Just keep clear which divs are serving as flex containers as you get into the details in the layout. It is very common to have divs that are both flex containers and flex items themselves too.
I also recommend using an img element instead of applying the image as a background so you dont have trouble with the aspect ratio in responsive window sizes.
A very nice resource: https://css-tricks.com/snippets/css/a-guide-to-flexbox/
/* .row & .col from materialize.css */
body {
margin: 0;
}
.full {
height: 100vh;
}
.row {
display: flex;
}
.column {
flex: 1 1 auto;
}
.column2 {
background: #b4c2cf;
display: flex;
flex-direction: column;
}
.column1 {
background: #cbb3cc;
}
.column3 {
background: #cbb2b2;
display: flex;
align-items: center;
justify-content: center;
}
.art_top {
flex: 1 0 10vh;
display: flex;
justify-content: flex-start
align-self: flex-end;
}
.art_center {
flex: 1 1 auto;
display: flex;
align-items: center;
justify-content: center;
}
.art_bottom {
flex: 1 0 10vh;
text-align: right;
}
#cover_art {
max-width: 100%;
max-height: 100%;
width: auto;
height: auto;
}
#song_name {
align-self: flex-end;
}
#artist_name {
align-self: flex-start;
}
.bold-title {
display: block;
font-weight: bold;
padding: 10px;
}
.small-box {
background: #8f588c;
height: 100%;
max-height: 70px;
width: 100%;
max-width: 70px;
}
<div class="row full">
<div class="column column1"></div>
<div class="column column2">
<div class="art_top">
<a id="song_name" class="bold-title">My Album Title</a>
</div>
<div class="art_center">
<img id="cover_art" src="https://picsum.photos/400" />
</div>
<div class="art_bottom">
<a id="artist_name" class="bold-title">Artist Name</a>
</div>
</div>
<div class="column column3">
<div class="small-box"></div>
</div>
</div>

Overflow difference between Chrome and Edge

I notice a difference between Chrome and Edge concerning overflow behavior.
As you can see running the following code, in Chrome this shows only the vertical scrollbar (rightly, in my opinion), while in Edge there are both scrollbars.
Is there a reason for this? How can I make Edge behave in the same way as Chrome does?
Thanks!
.container1 {
display: flex;
flex-flow: column;
align-items: flex-start;
}
.container2 {
display: flex;
flex-flow: column;
align-items: flex-start;
}
.container3 {
max-height: 150px;
overflow: auto;
}
.content {
width: 500px;
height: 200px;
background-color: blue;
}
<div class="container1">
<div class="container2">
<div class="container3">
<div class="content"></div>
</div>
</div>
</div>
Here's what I think is happening:
When the overflow is triggered (because height: 200px on the .content element is taller than the max-height: 150px on the parent), a vertical scrollbar is generated.
This scrollbar actually takes up width. The .content element is set to width: 500px. But once the scrollbar is generated, the width increases to 517px in Chrome. Note that scrollbar width varies among browsers.
Chrome appears to factor in or just ignore the vertical scrollbar width. It refrains from launching a horizontal scrollbar. Edge seems to consider the vertical scrollbar width as an overflow, and therefore launches the horizontal scrollbar.
There could be any number of reasons for this difference in behavior, including a different order of rendering elements and objects.
One thing is clear, if you move the width: 500px from the .content to the parent, the horizontal scroll problem is solved.
.container1 {
display: flex;
flex-flow: column;
align-items: flex-start;
}
.container2 {
display: flex;
flex-flow: column;
align-items: flex-start;
}
.container3 {
max-height: 150px;
overflow: auto;
width: 500px; /* new */
}
.content {
/* width: 500px; */
height: 200px;
background-color: blue;
}
<div class="container1">
<div class="container2">
<div class="container3">
<div class="content"></div>
</div>
</div>
</div>
jsFiddle demo
Try this : overflow-y: auto;
Link : https://www.w3schools.com/cssref/css3_pr_overflow-y.asp
After many attempts I have found a workaround by removing align-items: flex-start and replacing display: flex with display: inline-flex. Here's the new code:
.container1 {
display: inline-flex;
flex-flow: column;
}
.container2 {
display: inline-flex;
flex-flow: column;
}
.container3 {
max-height: 150px;
overflow: auto;
}
.content {
width: 500px;
height: 200px;
background-color: blue;
}
<div class="container1">
<div class="container2">
<div class="container3">
<div class="content"></div>
</div>
</div>
</div>
Hope it will help someone.

IE 11: Image doesn't scale down correctly within flexbox

I'm trying to use flexbox to place two images in a column. In this case, the width of the div container is smaller than the width of the image. In Chrome the image perfectly fits into the div container, but it doesn't in IE, and I don't know why.
div.outer {
width: 400px;
display: flex;
flex-direction: column;
justify-content: space-around;
}
div.inner {
width: 100%;
border: 1px solid red;
}
img {
width: 100%;
height: auto;
}
<div class="outer">
<div class="inner">
<img src="http://placehold.it/480x360">
</div>
<div class="inner">
<img src="http://placehold.it/480x360">
</div>
</div>
https://jsfiddle.net/Yifei/16cpckqk/
This is what I've got in IE 11:
IE11 seems to have some trouble with the initial value of the flex-shrink property. If you set it to zero (it is initially set to 1), it should work:
div.outer {
width: 400px;
display: flex;
flex-direction: column;
justify-content: space-around;
}
div.inner {
flex-shrink: 0;
width: 100%;
border: 1px solid red;
}
img {
width: 100%;
height: auto;
}
<div class="outer">
<div class="inner">
<img src="http://placehold.it/480x360">
</div>
<div class="inner">
<img src="http://placehold.it/480x360">
</div>
</div>
The accepted solution destroyed my sticky footers in ie. So I solved this disturbing issue with the following non satisfying "only for ie JS"... . The px value instead the "height:auto" did the trick for me.
if(fuBrowser =='ie'){
var img = $("#teaser img");
img.each(function() {
$( this ).css({height: $( this ).height()});
});
}