can someone explain to me this flexbox css problem? - html

demo: https://codesandbox.io/s/confident-bash-55v3z
I was following along some tutorial and I encountered this problem. the code is simple
I have flex container called images
<div class='images'>
<img src='imgs/787.jpg' class="main" />
<img src='imgs/sub1.jpg' class="sub1" />
<img src='imgs/sub2.jpg' class="sub2" />
</div>
and for the stylesheet I have
.images {
width: 234px;
display: flex;
flex-flow: row wrap;
justify-content: space-between;
border: 1px solid red;
}
.images > * {
padding: 1px;
height: 111px; <--- this seems like a magic number to me
}
img.main {
flex-basis: 99%;
}
img.sub1,
img.sub2 {
flex-basis: 49%;
}
the intended look is like this
However when I commented out the height: 111px;line, the layout is off
I am new to flexbox and css in general and I know that flex-basis is soft of like min-width. Without the height being 111px, the image will grow to occupy more space than its min-width(or flex-basis).
So my question is, to achieve the correct layout we want, how did the original author of the style sheet know that the height needs to be 111px? Can we achieve this layout using 'max-width' or other techniques which would make more sense to me?

First, about the magic number.
You have a container that is 234px wide, and two smaller images that have natural dimensions of 150px by 150px. Their combined width is 300px, which is larger than the container width, so they don't fit in the same row.
We can fix this by making them smaller. But how small do they need to be? There's a 1px padding around each image, for two images that's 4 pixels. We need to subtract that from the container width. Which leaves 234 - 4 = 230 pixels for two images, or 230 / 2 = 115 pixels for each image.
In your example the size of images is controlled using height and flex-basis. Using both at the same time can lead to distorted proportions. This actually happens to the top image in your 'intended look' example. If you compare it to the original image you can see that it's squashed vertically.
Also the interaction of height and flex-basis is quite unintuitive. To achieve the desired layout we don't actually need both, so let's put flex-basis aside.
When you set height of the image without setting its width, the image will automatically scale proportionally. Since our images are square, by setting the height to 111px we implicitly set the width to 111px as well. And since 111 is less than 115 both images fit in the same row. There's nothing magic about the number 111, any number below 115 will work.
We can simplify the code a little:
.images {
width: 234px;
display: flex;
flex-wrap: wrap; /* allow wrapping, otherwise all 3 images would be in the same row */
border: 1px solid red;
}
.images > * {
align-self: flex-start; /* prevent flexbox from stretching items vertically to fill the row */
box-sizing: border-box; /* include padding into the image width */
padding: 1px;
}
img.main {
width: 100%; /* occupy entire row */
}
img.sub1,
img.sub2 {
width: 50%; /* occupy half of the row */
}
Demo: https://codesandbox.io/embed/focused-faraday-bsd88
Try changing the width of the container to 500px or 100px. The images will scale automatically and will keep their proportions.

Instead of flex-basis, try adding width. This will keep 2 images in one line. flex-basis on the other hand, is for initial image size.
img.sub1, img.sub2 {
width: 50%;
padding: 0;
}

You are not setting any width or height to your images, so by default they take their true dimensions. In this case your "sub" images are wider than the width you define to your container, thus, by flex-flow: row wrap; the images can't be on the same line. you should set 50% width to your sub images, or set a bigger width to the container.
I fixed it here

Related

Unlimited images, responsiveness, fluid square/grid gallery, with a min and max size of images, but always less than 10px container margin

Here is my goal:
- full width of container no matter the screen size (meaning, the image size is dynamic where image size always fits a full row of images)
- the images will ALWAYS be squares, but no smaller than 150px and no larger than 200px
- a 10px margin between images and rows
So basically, how to change or add to this codepen, where there isn't the big right/left margin depending your screen size?
https://codepen.io/trynn/pen/WNbjOJq
You need to calculate the screen to image size, right?
thanks
This css doesn't adjust the size of the images, but it needs too? Then by doing so, it would/could adjust the image size and make sure only a 10px margin is left, no matter the screen size? Isn't that correct?
.container{
display: flex;
flex-wrap: wrap;
justify-content: center;
}
img{
margin: 5px;
}
Images can scale with one side set to auto but the other side needs to be set to an exact size. Strangely enough, when I worked with this, the images were able to be fluid despite being set to an exact size.
CSS
.container {
display: flex;
flex-wrap: wrap;
justify-content: center;
}
img {
flex: 1;
margin: 5px;
width: 200px;
height: auto;
}

Image fill fixed height div

I'm stuck on a cssproblem.
I have a div with fixed height, 400px and inside that div there is some variable text. And an image, I need the image to fill the space of the div. The text will change so the space always is different and all must be inside the height bounds.
I found a solution, using display: flex and setting image on background of a div.
You can see code here: https://jsfiddle.net/ckryvuzm/
I tried using display: table but the fixed height of 400px grows when content changes.
Define the Width of the div to 100% that contains the height of 400px and display: flex and flex-direction: column.
Inside it make Image div to the flex-grow: 1.
And put all of your content inside one div, and make overflow: auto, as there will be less content it will not have scroll and if the content grows in size the content will get a scroll-bar.
Here made a fiddle which I think exactly solve your Issue: https://jsfiddle.net/ABhimsaria/vj7bgzpb/2/
#container {
position: relative;
font-size: 20px;
height: 400px;
width:100%;
border:1px solid black;
height: 400px;
display: flex;
flex-flow: column;
}

How to keep the height of a containing div element?

I'm trying to draw three rectangles in a page. The top rectangle has to be much smaller than the other two. You can see the top rectangle has a flex-grow: 1 (compared with 5 for other rectangles).
However, once I put three images inside the top rectangle, it gets taller, so it becomes bigger than other rectangles.
What can I do to prevent the top rectangle from getting taller? I just want the pictures' size to be adjusted to fit in the original container size.
I'll be glad for a solution using flexbox features (because I'm trying to learn it).
html,
body {
width: 100%;
height: 100%;
flex-flow: column wrap;
display: flex;
}
div {
flex-grow: 5;
display: flex;
border: solid;
margin: 1em;
}
#top {
flex-grow: 1
}
<div id="top">
<img src="http://i164.photobucket.com/albums/u8/hemi1hemi/COLOR/COL9-6.jpg">
<img src="http://i164.photobucket.com/albums/u8/hemi1hemi/COLOR/COL9-6.jpg">
<img src="http://i164.photobucket.com/albums/u8/hemi1hemi/COLOR/COL9-6.jpg">
</div>
<div id="middle"></div>
<div id="bottom"></div>
http://codepen.io/CrazySynthax/pen/ZBPXry
Your max-height of 30% is bigger than the rectangles initial size. Try setting fixed height for it or lower the max-height to match the initial size. On the code pen I used max-height: 20%; and got the result you are looking for, however to be consistent on all displays I would just set the height to a fixed percentage. ex: height: 20%. Also there is no point of using max-height if you don't want your div's height to change.

Responsive images, without being 100% width if the container is bigger - containers are flexbox

I have a two column layout - fixed right column width, an scalable content in the left column.
The layout scales great with different screen sizes until I add images to the scalable column. If the container goes down to the size of the image it pushes the column too wide, squashing my 300px right column.
I set
width:100%;
on the images, which solves the responsiveness issue, but when the container is full screen again the images scale to fill it, which is not what I want because it looks rubbish. I've added
max-width:100%;
which hasn't helped.
In short, I want the image behaviour to be "Be your real size, unless the container is smaller, in which case shrink."
(I should mention that my two-column layout is done with flexbox)
Edit:
After playing around with this for ages, it turns out to be a difference in behaviour between broswers - Chrome scales the container, shrinking the image (as per max-width) but Firefox just pushes all the content out. Open this in each: https://jsfiddle.net/andyg1/sb7zefr5/
Remove width:100%; and keep max-width:100%;. This will keep images at their original size but shrink them to 100% width if the container is smaller.
Here's an example https://jsfiddle.net/v4kL409v/
You can use width: 100% and the real size if the image or the maximum size of the conainer as max-width, for example
my_image {
width: 100%;
max-width: 320px;
}
That way it will shrink with the container, but not grow above a set size.
You can use an image as a background to your flex-item.
background-image, background-repeat, background-position, and most importantly background-size
* {
margin: 0;
padding: 0;
}
body {
width: 100vw;
height: 100vh;
}
.flex {
display: flex;
justify-content: center;
width: 100%;
height: 100%;
}
.bg {
width: 50vw;
height: 50vh;
background: url(https://upload.wikimedia.org/wikipedia/en/2/24/Lenna.png) no-repeat center;
background-size: contain;
outline: 3px dashed red;
flex: 1 0 50%;
}
.rt {
width: 300px;
height: 50vh;
outline: 3px dashed blue;
}
<div class="flex">
<figure class="bg"></figure>
<figure class="rt"></figure>
</div>
After identifying that the problem is different between Firefox and Chrome I did some research to find out that the problem can be fixed by adding:
min-width:0;
to the element containing the responsive. As discussed here: Firefox flexbox image width
Add display:block to image.
.my_image {
display:block;
max-width:100%;
height:auto;
}

In a flexbox layout, is there a `flex-shrink: 0` declaration for the cross axis?

I want to prevent elements in a flex container from shrinking in the dimension that is not the flex-direction. The following example has <article> elements side by side in a row. When the available vertical space is reduced, these elements do not force their flex container to display a scrollbar; instead the content overflows the element boundary.
Screenshot 1 - there is enough horizontal and vertical space to display everything:
Screenshot 2 - the reduced vertical space pushes the element border up:
Screenshot 3 - vertical space further reduced, container finally gets a scrollbar:
Screenshot 4 - without flex-shrink:0, the element widths (main flex axis) will also be reduced:
flex-shrink:0 can prevent horizontal shrinking, but how can I prevent the elements from shrinking vertically?
Giving the <article> elements overflow: auto or something similar does not give the desired result (= scrollbar on the container). Ideally, the display would look like this montage:
If I knew the elements' height in advance, I could give them a min-height, but that is not always the case.
FIDDLE: http://jsfiddle.net/twdan8u8/
HTML:
<main>
<article>article<br>article<br>article</article>
<article>article<br>article<br>article</article>
</main>
CSS:
* {
box-sizing: border-box; /* not the culprit */
}
html {
height: 100%;
}
body {
position: relative;
height: 100%;
margin: 0;
background: #999;
}
main {
overflow: auto;
background: gold;
display: flex;
height: 80%;
padding: 50px 30px;
}
article {
flex-shrink: 0;
font-size: 28px;
border: 2px solid red;
margin-right: 30px;
padding: 10px;
}
As is so often the case, I found the (or rather a) solution just when I finished writing the question. Since this might help somebody else, here's what I found out:
If the flex container is given the style align-items: flex-start, element heights are not reduced and the container gets a scrollbar when necessary (assuming a suitable overflow value).
The default for this property is "stretch". It can also be set on individual flex elements using align-self. The drawback is that the elements are now no longer equally high (i.e., they don't stretch to the full available height anymore).