The impact of the width property used with flex-grow? - html

Please see the code below:
ul {
display: flex;
list-style-type: none;
flex-wrap: wrap;
}
li {
flex-grow: 1;
border: 1px solid;
width: 1000px;
}
<header>
<ul class="child">
<li>Monday</li>
<li>Tuesday</li>
<li>Wednesday</li>
<li>Thursday</li>
<li>Friday</li>
</ul>
</header>
Notice the width of 1000px. When I load the page there are five rows as I would expect. If I remove the width property, then the boxes appear on one row as expected.
Now if I add a width of 1px, then the only change is that all boxes are the same size i.e. 372.28 pixels (not 1px). It appears to me that the behaviour is as follows:
If any width is added to the flex items that means they can all fit on one row then make sure all boxes are the same size.
If a width is added to the flex items meaning they cannot all fit on one row then honour the width.
If a width is not added then the boxes can be any size i.e. the Wednesday box is biggest in this case because Wednesday is the longest word.
Have I understood this correctly and why does the width effect the flex items like this?
I have done my own research and found questions like this: What are the differences between flex-grow and width?. However, I have not found an answer to my question. I have also read about the flex grow property here: https://www.w3.org/TR/2018/CR-css-flexbox-1-20181119/#flex-grow-property

It's important to note that width, height and flex-basis in a flex container represent the initial size of the item.
Once that size are determined, then flex-grow and flex-shrink enter into the picture and do their work, if possible. That can change the initial size.
Now, let's break down your question into the main points:
Notice the width of 1000px. When I load the page there are five rows as I would expect. If I remove the width property, then the boxes appear on one row as expected.
OK
Now if I add a width of 1px, then the only change is that all boxes are the same size i.e. 372.28 pixels (not 1px).
Do you mean "e.g., 372.28 pixels (not 1px)", not "i.e.", because the size of the item will vary depending on the size of the viewport. In other words, the size of each item will scale as you resize the window. But this is not an essential point.
All boxes are indeed equal length. This happens because the width is set to 1px.
If you were to remove the width rule, then the boxes would vary in length based on their content length. This is because the default width / flex-basis is auto.
If any width is added to the flex items that means they can all fit on one row then make sure all boxes are the same size.
Not necessarily.
The width property doesn't always relate to items all fitting on one row. That behavior is controlled by the flex-wrap and flex-direction properties.
Also, the width property doesn't always relate to items all having equal length. Other factors, such as flex-grow, can have an impact.
If a width is added to the flex items meaning they cannot all fit on one row then honour the width.
Not necessarily.
flex-grow, flex-shrink and flex-wrap can all have an impact.
If you want the width / flex-basis of an item to remain fixed, set both flex-shrink and flex-grow to 0 (which disables those functions).
If a width is not added then the boxes can be any size i.e. the Wednesday box is biggest in this case because Wednesday is the longest word.
Not necessarily.
flex-grow, flex-shrink and flex-wrap can all have an impact.
More details:
Make flex-grow expand items based on their original size
Flex items are shrinking below flex-basis

Related

flexbox min-width failing in IE and Edge

I have some table that set width for elements so some columns will have at least some percent of a width of the container.
I want to use flexbox to center this table and set the minimum-width for it.
The goal is to have centered table with some minimum width for which some columns will have the same width (same ratio).
If some cells have longer texts then I don't care if ratio will broke (width of this column will be bigger then other). I just care that it has nice and same width of columns for common case (small amount of text data in cells)
I was able to came up with solution that works on Firefox and Chrome (link).
But for Edge and IE11 the table stretch as if it was not in flex container (try to comment display: flex; on Firefox or Chrome and the result is stretched table like on Edge.
Also it looks that sometime setting columns work (link2). But I don't see the pattern of when it break in Edge/IE11.
Here is more production example that I want to achieve (works in Chrome/Firefox, stretch in Edge/IE11): "production" table example.
Any ideas how to achieve what I want on Edge/IE11? (I put in bold what I want to achieve).
It would be good if I could keep using flexbox container (it might require more changes in my codebase) but I think I will be fine with deleting style=width:p% from <col> if that's necessary.
The min-width rule is apparently being ignored in Edge / IE11.
There's an equivalent command that seems to work.
Instead of:
.inner {
min-width: 800px
}
Use:
.inner {
flex-basis: 800px; /* 1 */
flex-shrink: 0; /* 2 */
}
revised codepen
notes:
flex-basis is a substitute for width, in this case (see: flex-basis vs width)
flex-shrink: 0 ensures flex-basis / width cannot decrease below 800px (hence, both rules together emulate min-width)

ionic 3 auto adjust layout on the grid

I have built a dashboard using ion-grid and just one ion-row. the ion-row contains 10-12 ion-col. So basically, as soon as the screen width is hit the columns starts to flow down.
This all is good and as expected. However, the problem starts when these columns are of varying width and heights. I have defined the col of 3 width types: 200px, 400px and 600px. The height is also of 3 variations 200px, 400px and 600px. So overall each col can be either a 1*1, 2*1, 1*2, 2*2, 3*1 and 3*2 size.
I am using dragula to be able to drag and drop the titles to adjust the layout as desired. However, initial layout always renders with some holes though they can be filled by manual drag drop.
So, what should be the right way to handle it at the initial time to avoid the holes in the layout.
You probably could use css flex grow. Use one parent div for each row and set css as
.row {
display: flex;
justify-content: center;
align-items: center
}
for each column use flex grow to define their sizes.
eg. flex-grow: 1 - for normal, flex-grow: 2 for bigger width.
here I have attached what I have did. In my case, the column numbers should be dynamic, but having the same with.

Why does width and height of a flex item affect how a flex item is rendered?

An image in a flexbox that has a max-height style appears to render differently depending on whether it has its height and width attributes set.
The one with the attributes, set to the true width/height of the image, renders with its aspect ratio preserved, but the ones without the attributes respects the max-height and appear squashed.
.flex-parent {
display: flex;
max-height: 10vh;
}
<div class="flex-parent">
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/be/Red_eyed_tree_frog_edit2.jpg/320px-Red_eyed_tree_frog_edit2.jpg">
<img width="320" height="240" src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/be/Red_eyed_tree_frog_edit2.jpg/320px-Red_eyed_tree_frog_edit2.jpg">
</div>
This is how is appears in Chrome 58 (and it appears similarly in Firefox 54).
Why do they render differently? What are the rules that govern this behaviour?
My (obviously incorrect) understanding is that height and width attributes overwrite the intrinsic height and width that is found when the image loads, and if the height and width attributes equal the dimensions of the image, there should be no difference in rendering once the image has loaded.
The context is making a page with responsive images, where each image
can have unique original dimensions
does not cause a reflow when it's loaded, i.e. the correct space is reserved on initial render (hence using height and width attributes)
can fit all on screen at once (hence me messing with vh in the CSS)
The frog image is from https://en.wikipedia.org/wiki/File:Red_eyed_tree_frog_edit2.jpg
An initial setting of a flex container is align-items: stretch.
That means that flex items will expand across the cross axis of the container.
In a row-direction container, like in the question, the cross axis is vertical.
That means the items (images, in this case) will cover the full height of the container.
However, when a flex item has a defined cross size, that overrides the stretch default.
From the spec:
8.3. Cross-axis Alignment: the align-items and align-self
properties
Flex items can be aligned in the cross axis of the current line of the
flex container, similar to justify-content but in the perpendicular
direction.
stretch
If the cross size property of the flex item computes to auto, and
neither of the cross-axis margins are auto, the flex item is
stretched.
This is the key language:
If the cross size property of the flex item computes to auto
And this is how the spec defines "cross size property":
The width or height of a flex item, whichever is in the cross
dimension, is the item’s cross size. The cross size property is
whichever of width or height that is in the cross dimension.
https://www.w3.org/TR/css-flexbox-1/#cross-size-property
So your code appears to be playing out as defined in the spec.
This is what you have:
.flex-parent {
display: flex;
max-height: 10vh;
}
<div class="flex-parent">
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/be/Red_eyed_tree_frog_edit2.jpg/320px-Red_eyed_tree_frog_edit2.jpg">
<img width="320" height="240" src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/be/Red_eyed_tree_frog_edit2.jpg/320px-Red_eyed_tree_frog_edit2.jpg">
</div>
The first image has no defined width (main size) or height (cross size), either in the CSS or the HTML. Its cross size, therefore, computes to auto.
This statement:
If the cross size property of the flex item computes to auto
... is true, and align-items: stretch goes into effect.
The image expands across the height of the container, which is 10px.
The second image, however, has explicit sizing. The cross size is defined in the HTML (height="240").
Now this statement:
If the cross size property of the flex item computes to auto
... is false, and align-items: stretch is overridden. The HTML height attribute prevails.
Two notes about the second image:
The image ignores the max-height limit on the container because an initial setting in CSS is overflow: visible.
The HTML width and height attributes map to their respective CSS properties. Hence, height="240" overrides the height: auto default. See below for the spec references.*
There are two other issues to consider when rendering images in a flex container.
The default minimum size of flex items. This setting prevents flex items from shrinking below the size of their content. Read this post for full details:
Why doesn't flex item shrink past content size?
Varying behavior among major browsers. Firefox, Chrome, Safari, Edge and IE11 don't always render images as flex items in the same way. Read this post for more details:
Flex in Firefox shrinks images automatically, but not in Chrome
Considering all factors above, here's my suggested solution:
.flex-parent {
display: flex;
max-height: 50vh; /* adjusted for demo */
}
.flex-parent {
min-width: 0;
}
img {
width: 100%;
height: auto;
}
<div class="flex-parent">
<div>
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/be/Red_eyed_tree_frog_edit2.jpg/320px-Red_eyed_tree_frog_edit2.jpg">
</div>
<div>
<img width="320" height="240" src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/be/Red_eyed_tree_frog_edit2.jpg/320px-Red_eyed_tree_frog_edit2.jpg">
</div>
</div>
*The HTML width and height attributes map to their respective CSS properties. Hence, when specified, they override the CSS defaults. From the HTML5 spec:
10.4.3 Attributes for embedded content and
images
The width and height attributes on applet, embed, iframe,
object or video elements, and input elements with a type
attribute in the Image Button state and that either represents an
image or that the user expects will eventually represent an image,
map to the dimension properties width and height on the element respectively.
10.2 The CSS user agent style sheet and presentational
hints
When the text below says that an attribute on an element maps to the
dimension property (or properties), it means that if the element has
an attribute set, and parsing that attribute's value using the rules
for parsing dimension
values doesn't generate an error, then the user agent is expected to use the
parsed dimension as the value for a presentational hint for
properties, with the value given as a pixel length if the dimension
was an integer, and with the value given as a percentage if the
dimension was a percentage.
Tried reading the w3c flexbox specs and stumbled onto this. It says that
For each dimension, if that dimension of the flex container’s content
box is a definite size, use that; if that dimension of the flex
container is being sized under a min or max-content constraint, the
available space in that dimension is that constraint.
Otherwise, subtract the flex container’s margin, border, and padding from the space available to the flex container in that dimension and use that value which might result in an infinite value.
Hope this helps.
Here you have written max-height:10vh, vh does not support in any browsers except the very latest iOS 6. This goes for all the viewport related length units.
use other values instead of Vh this will work fine.
Please Read this blog https://css-tricks.com/the-lengths-of-css/.
.flex-parent {
display: flex;
max-height: max-content;
}
<div class="flex-parent">
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/be/Red_eyed_tree_frog_edit2.jpg/320px-Red_eyed_tree_frog_edit2.jpg">
<img width="320" height="240" src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/be/Red_eyed_tree_frog_edit2.jpg/320px-Red_eyed_tree_frog_edit2.jpg">
</div>
The problem is where you set max-height. The css property max-height is not inherited by default. Your css declaration creates a div that is 10% of the viewport height. The image with no dimensions set shrunk based on it's parent dimensions. The image you set the implicit dimensions on is always going to be those dimensions. Depending on the size of the div, it may overflow. If you put the max-height property on the first image, it should resize keeping the aspect ratio the same.

img max-width with percentage how does it work?

I am new to responsive web design and was looking at an answer.
It doesn't really explain much but provides a solution.
If an img is set as width: 100% I understand that it will occupy 100% of the browser window or its containing element.
The max-width property states that it is used to set the max width of an element.
If I set an img tag to max-width: 100% to what element/context is the percent calculated against?
All I see is when max-width is used the image scales down but never up.
Max-width example: http://jsfiddle.net/ErNeT/1445/
Width example:http://jsfiddle.net/ErNeT/1446/
If I set an img tag to max-width: 100% to what element/context is the
percent calculated against?
By default an img tag has no dimension set on it. So whatever happens, that image will never resize. However, applying max-width will make it behave like it has 100% width. It will resize based on the parent container BUT will stop at the maximum width the image has. For example: if the image was sliced to have 100px width, it will resize up to 100px width.
On the other hand, by applying width (and no max-width property) it will disregard all other width properties of the image and the parent container.
If you set max-width to img then it will be the max-width of its parent. If you don't specify a width for the img then it will not exceed it's native size.
When you set percentage values, both width and max-width are relative to the containing block. However, if the width of the containing block depends on the width of the element, the resulting layout is undefined.
From the specification,
https://www.w3.org/TR/CSS2/visudet.html#the-width-property
Specifies a percentage width. The percentage is
calculated with respect to the width of the generated box's containing
block. If the containing block's width depends on this element's
width, then the resulting layout is undefined in CSS 2.1. Note: For
absolutely positioned elements whose containing block is based on a
block container element, the percentage is calculated with respect to
the width of the padding box of that element. This is a change from
CSS1, where the percentage width was always calculated with respect to
the content box of the parent element.
https://www.w3.org/TR/CSS2/visudet.html#min-max-widths
Specifies a percentage for determining the used value.
The percentage is calculated with respect to the width of the
generated box's containing block. If the containing block's width is
negative, the used value is zero. If the containing block's width
depends on this element's width, then the resulting layout is
undefined in CSS 2.1.
From my point of view
if width > max-width use max-width
Example: Let's say you have 1 div box or Image which is you set the size of the box width > 1000px and max-width 500px. It still follow the max-width.
Example 2 - Using percentage : Let's say that div of your width set 500px, and max-width :100%; what is the result you will get ? The box div will turn 500px that is your starting point. Try shrink it. What is the result you will get next? It's turn responsive.
DEMO
this is what i understand about the difference between width and max-width.
Based on your question and fiddle, I think this is the answer what you're looking for.
Max-width example: DEMO2
- When you start use max-width and set 100%. let say your images size is width is 300px. Meaning that your images starting point are 300px. You aren't override the original image width.
Width example: DEMO3
- When you start use width and set 100%. Meaning that your image are override the original image width.

Div is jumping down to second row? Why?

Open this page : http://jsfiddle.net/dwDZx/6/
Resize until red
Continue make the browser smaller
<div id="container">
<div id="div1"><div class="content">one</div></div>
<div id="div2"><div class="content">two</div></div>
​
Why does div2 jump down a row instead of resizing? How can I solve this?
You are adding margins for the smaller screen size. Set the margins to a percentage and subtract the percentage of the width for the smaller screen size.
So do not set a margin in pixels. but in percentages.
Updated your code at //jsfiddle.net/dwDZx/9/
When the divs are red, there are two relevant constraints that the divs try to follow: width: 48% and margin-right: 10px. If the div is jumping down a row instead of resizing, that means there isn’t enough space for both of them on that row – they are trying to take up more space than is available. Thus, the second div makes a new row for itself so both divs can be as wide as they want. So let’s look at the numbers and see why the divs are asking for too much space.
Load http://jsfiddle.net/roryokane/kZZCh/, which dynamically displays the width of the page and each div, and make the Result panel exactly 400px wide, so the bug shows itself. Now the two divs are 192px wide. That makes sense – 48% of 400px is 192px. The width does not include the margin, which is 10px for each div. So the total width the divs are asking for is (192+10)*2 = (202)*2 = 404 pixels, which is more than the 400px allotted to them. No wonder the divs are wrapping instead of staying on the same row.
So how do you solve this? Dany’s answer suggests changing the margin-right value from a pixel value to a percent value. But that is only one possible solution. Finding the best solution depends on why you chose the two specific numbers in width: 48% and margin-right: 10px, and which number is more important to keep. If you need the width to remain at 48%, consider whether you want to keep a fixed margin width or switch to a flexible margin width. If you you still want a fixed width, use margin-right: 8px. If you want a flexible width, use margin-right: 2% (Dany’s solution). On the other hand, if you need the right margin width to remain at 10px, then for the width, use width: 47.5%. All of these values ensure that even when the page is only 400px wide, the divs stay on the same row.