Why do flex-item images not scale height? - css

I'm learning Flexbox layout right now after having to take over a project after someone abandoned it and have run into a bug where flex-item images don't seem to scale their height at all w/ responsive design. Width scales fine, but the height never scales and remains fixed at original height.
I have a very simple set up of something like:
<div class="my-container">
<img src="..." />
<img src="..." />
<img src="..." />
</div>
CSS is very basic:
.my-container {
display: flex;
flex-direction: column;
flex-wrap: wrap;
justify-content: space-between;
}
.my-container img {
display: block;
flex-grow: 1;
flex-shrink: 1;
flex-basis: auto;
max-width: 100%;
}
Basically, a single column (the mobile view - iphone). The above works and looks great in Firefox. On Chrome (v 48.0) the image height is NOT scaling.
E.g. the 1st <img> is a 940px x 500px wide image which looks great on Desktop, but in Chrome it is 300px x 500px. Width is scaling but height is not? The 2nd and 3rd images ~460px and appear on a row next to each other.
Oddly, if I make flex-direction: row, then Chrome renders correctly and the image height appears to scale, but Firefox then breaks and has the same issue!
Am I out to lunch here?
Thankfully, everything RENDERS OKAY on mobile devices. This only seems to occur when resizing your browser window. :/

I believe this is a bug with the most recent production chrome (48). Does running this in console "resolve" your issue (assuming you have jquery running): $('img').css('min-height',0);
If so (or alternatively) you should be able to give your images a min-height of 0 in css. That should do the trick as a workaround until it's fixed.
Found this on: https://github.com/angular/material/issues/6841
Chrome is a great browser, but occasionally the flex-box support breaks with updates =/

Is this the desired output?
.container {
width: 600px;
margin: 10px auto;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-between;
}
<div class="container">
<div><img src="https://placehold.it/150x150/E8117F/FFFFFF"></div>
<div><img src="https://placehold.it/100x100/11E87F/000000"></div>
<div><img src="https://placehold.it/200x300/117FE8/FFFFFF"></div>
</div>

Related

Get item in flexbox to fill available space of the already-sized element

I have the following grid of thumbnails (links to other pages) and I'm displaying them using a flexbox.
As you can see on the left since one of the images doesn't have the same aspect ratio, it doesn't fit correctly. I want it to fill that whole available space (essentially scale so it fills it and "crop" the overflow.)
The container css is this
display: flex;
flex-direction: row;
flex-wrap: wrap;
And each element has
flex-basis: 20%;
What css can I add to get the behavior I want?
In case it's relevant I'm actually doing this in React where the elements are loaded dynamically, and the css is actually a CSSProperties object, but on the client side it's just rendered as normal css so I believe any css-based solution will still work. Thanks!
I think you are looking to stretch the height of any elements that do not fit the aspect ratio that are within the flex container correct?
If I am incorrect, or this does not work for your needs, let me know and I will remove this answer.
You could just add a max-width of 20% or a calculated percentage that does not exceed 1/5th the view width to the flex containers child element. Then add object-fit: fill.
body * {
padding: 0;
margin: 0;
box-sizing: border-box;
}
.flex-parent {
display: flex;
flex-wrap: wrap;
}
.flex-child {
max-width: 20%;
object-fit: fill;
}
<div class="flex-parent">
<img class="flex-child" src="https://picsum.photos/300/200">
<img class="flex-child" src="https://picsum.photos/200/200">
<img class="flex-child" src="https://picsum.photos/200/200">
<img class="flex-child" src="https://picsum.photos/200/200">
<img class="flex-child" src="https://picsum.photos/200/200">
<img class="flex-child" src="https://picsum.photos/300/200">
</div>

CSS height mysteries: Different on Chrome and Firefox

This codepen looks different on Chrome than on Firefox. The html and css is:
<div class="outer">
<div>header</div>
<div class="grid">
<div class="central">central</div>
</div>
</div>
.outer {
min-height: 200px;
background: lightsalmon;
display: flex;
flex-direction: column;
}
.grid {
display: grid;
flex: 1 1 0%;
}
.central {
/*height: 98%;*/
background: lightcoral;
}
On Chrome, even though the central element's height is always relative to the intermediate elements actual height (when placed with grid or when using a percentage height like the one in comments), but only if is grandparent's height was explicitly set (and even though that height is not what the central element's is calculated in relation to).
(Grid layout seems to have no such issue: If you change the outer element's display from flex to grid it works on Chrome too.)
Is this a bug or is the behaviour not clearly enough defined?
I can't say I understand that I understand's Mozilla's formal definition of percentage heights on this page anyway and I don't know if there's a more rigorous definition.

Sticky flexbox footer not fixed to bottom

I'm wanting to fit the entire UI on the screen onLoad but my footer is not fixing to the bottom of the view on mobile.
On a desktop web browser, it works perfectly. When I view this on a mobile web browser, the footer is further down the page which makes the page scrollable. It should not scroll, instead, it should fit perfectly inside the viewport.
I've made sure to use the correct meta viewport tag. Included prefixes where I use flexbox. I tried using relative positioning but still not getting the results I want.
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
html,
body {
font-family: 'Roboto', sans-serif;
}
.container {
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
height: 100%;
min-height: 100vh;
flex-direction: column;
max-width: 420px;
margin: 0 auto;
padding: 1rem 1rem 0 1rem;
}
header {
margin: 2rem 0;
}
main {
-webkit-box-flex: 1;
-moz-flex: 1;
-ms-flex: 1;
-webkit-flex: 1;
flex: 1;
}
footer .btn-group {
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
margin-bottom: 1rem;
margin-top: 0.5rem;
}
<head>
<meta charset="UTF-8">
<meta name='viewport' content='width=device-width, initial-scale=1.0'>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div class="container">
<header>
<h1 class="title">Title</h1>
</header>
<main>
<div class="list">
<input type="text">
<input type="text">
</div>
</main>
<footer>
<div class="btn-group">
<button class="btn-refresh">
Refresh
</button>
<button class="btn-add">
Add New
</button>
</div>
<button class="btn">Main Action</button>
</footer>
</div>
</body>
On mobile, I'd expect that the footer is fixed to the bottom of the browser viewport, however, the button group is a bit past and a user would need to scroll to see the full group of buttons.
When looking at my codepen version, this works fine. However, when I copy&paste the code to my server the footer does not stay at the bottom.
Is there anything that I am missing?
Note that on some mobile browsers, if an item's height is 100vh you will need to scroll down so see it in its entirety. This is intentional, and it has to do with the visible area changing as you scroll (for example in a lot of mobile browsers like Chrome, the toolbar at the top goes away when you scroll down):
This is completely intentional. It took quite a bit of work on our
part to achieve this effect. :)
The base problem is this: the visible area changes dynamically as you
scroll. If we update the CSS viewport height accordingly, we need to
update the layout during the scroll. Not only that looks like shit,
but doing that at 60 FPS is practically impossible in most pages (60
FPS is the baseline framerate on iOS).
It is hard to show you the “looks like shit” part, but imagine as you
scroll, the contents moves and what you want on screen is continuously
shifting.
Dynamically updating the height was not working, we had a few choices:
drop viewport units on iOS, match the document size like before iOS 8,
use the small view size, use the large view size.
From the data we had, using the larger view size was the best
compromise. Most website using viewport units were looking great most
of the time.
If you're looking for a way to circumvent this behavior, I suggest you read this: The trick to viewport units on mobile.
Try this
.container {
max-height: 100vh;
box-sizing: border-box;
}

Nested flexboxes: IE11 doesn't respect max-width: 100%

I'm working on a two column layout. Both columns will display an iframe, the width of both will be defined as inline-style / be set in the CMS. If the iframe is smaller than the column, it should center vertically. If its bigger than the column, it should shrink to the max width of the column, which is nearly 50% wide.
(Yes, this could probably be done without using flexbox twice. But I'm not interested in such answers, because I simplified the example and the use case.)
Example:
http://jsbin.com/logifu/2/
HTML:
<div class="content">
<div class="col">
<div class="media-wrapper">
<iframe src="http://www.jsbin.com/blog" frameborder="0" scrolling="no" style="width: 2000px; height: 2000px"></iframe>
</div>
</div>
<div class="col">
<div class="media-wrapper">
<iframe src="http://www.jsbin.com/blog" frameborder="0" scrolling="no" style="width:200px"></iframe>
</div>
</div>
</div>
SCSS:
.content {
display: flex;
justify-content: center;
flex-flow: row wrap;
}
.col {
display: flex;
justify-content: center;
align-items: flex-start;
flex: 1;
height: 100%;
min-width: 0; // this fixes the issue in FF 34
+ .col {
margin-left: 40px;
}
}
.media-wrapper {
box-sizing: border-box;
max-width: 100%;
padding: 15px;
background: lightblue;
}
iframe {
display: block;
margin: 0 auto;
max-width: 100%;
overflow: hidden;
}
This works as expected in Chrome 39. In Firefox 33 and in IE 10 this works, too. (I'm lazy, so I didn't add the IE10-flexbox syntax in the fiddle.)
In the new FF34 it behaved the same as in IE11, but this could be fixed with max-width: 100%. See How can I get FF 33.x Flexbox behavior in FF 34.x? for further explanation.
Unfortunately, this fix does not affect IE11. So how do I prevent IE11 displaying the iframe larger than the column? And why is this happening; is this a bug or is this another flexbox-feature that was reintroduced as mentioned in the linked question?
Ok, I found a way to prevent this in IE11: max-width: calc( 100% - 0.1px );. Therefore the max-width gets calculated and interpreted in pixel and not in percent, but is nearly 100%. So visually everything looks as expected.
Does anyone know a better solution or an explanation for this problem?

Why Does My Flexbox Sticky Footer Not Work in Safari?

I've been trying to learn something about CSS flexboxes, specifically to get a sticky footer working, based off this example.
The layout is 3 basic divs: a header, main content and footer. The main content div is supposed to expand vertically such that the footer is always at the bottom of the page. In Safari, the page loads as expected, but resizing the window vertically does not adjust the height of the layout (i.e. nothing's moving) — if I make the window taller, the extra space in the main content div doesn't change to keep the footer at the bottom, likewise . Resizing the window horizontally does reflow the page properly. Everything does work as expected in Chrome.
The example page works as I would expect, and I've followed the example CSS closely (using Autoprefixer's live demo). Comparing the pages in web inspector, the flexbox CSS appears to be consistent, and the only (seemingly) relevant difference is the live code on the example uses min-height: 100% for the flexbox container, whereas mine (and the example code given) uses min-height: 100vh (using 100% didn't work at all for me).
So my question: what is the example site doing differently that mine isn't, and why? Secondarily, why does min-height work in percentages for one, but only viewport units for another?
My code (also on jsfiddle):
<!DOCTYPE html>
<html>
<head>
<title>Flexbox Header Test</title>
<style type="text/css">
body {
font-family: Avenir, sans-serif;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
padding: 0;
margin: 0;
min-height: 100vh;
}
div {
width: 100%;
}
div p {
margin-left: 1em;
margin-right: 1em;
}
div.header {
background-color: orange;
text-align: center;
}
div.main {
background-color: grey;
-webkit-box-flex: 1;
-webkit-flex: 1;
-ms-flex: 1;
flex: 1;
}
div.footer {
color: white;
background-color: blue;
}
</style>
</head>
<body>
<div class="header">
<h1>Header</h1>
</div>
<div class="main">
<p>Lots of text here</p>
</div>
<div class="footer">
<p>Footer text here</p>
</div>
</body>
</html>
Thanks to some help from the developer of the site I took the example from, I discovered the cause of my problems: the html element didn't have any height set, thus the min-height on body didn't have any effect. Setting html { height: 100%; } resulted in the expected behaviour.
I admittedly still don't fully understand the why of what caused the initial layout and horizontal resizing to work, but vertical resizing not to, but this at least solves the problem. There was some suggestion from the developer that Safari has some bugginess related to using vh measurements, so that may be it. If anyone can shed some light on that issue, by all means go for it.

Resources