I actually found a solution to my problem but would like to know why my original solution doesn't work.
I have a simple flex container in which I want the first div to be 30% of the container. I gave it a flex-basis of 30% to try to achieve this. This works until I have content that exceeds the length of 30%. At this point, it extends the div making it more than 30%.
I solved this using the max-width attribute which I found from another question after some research, but am still confused why flex-basis does not work, and would prefer not to have a max-width attribute when using flex box. I read that if flex-direction is row, flex-basis should be a replacement for width, but this does not seem to be the case.
Here is a fiddle and the css along with it:
https://jsfiddle.net/jg5nbdgp/12/
.container {
display:flex;
flex-direction: row;
.left {
flex-basis: 30%; /* This doesn't work */
/* max-width: 30%; */ /* This works */
.box {
height: 50px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
.middle {
flex-basis: 50%;
}
.right {
flex-basis: 20%;
}
}
It is because flex box items cannot be smaller than the actual content. This is the default behaviour of flexbox.
Including min-width:0 to .left class will make flex-basis work.
So in your case your content width is greater the flex-basis value and by the default flexbox behaviour flex box width cannot be smaller than the content. By flexbox terms your code has actually become
.left {
flex-basis: 30%;
min-width: auto;
max-width: auto;
}
so you have to update the width to let flexbox come over the default behaviour. update your class to
.left {
flex-basis: 30%;
min-width: 0;
}
In order words you can remember width values precedes the flex-basis values.
JsFiddle: https://jsfiddle.net/gLodw7k1/
I had a similar issue. I had 2 equal columns with a max width like so:
flex-basis: 50%;
max-width: 30em;
Worked everywhere but IE. In IE it would shrink the columns. I fixed it by changing basis to the same value like so:
flex-basis: 30em;
max-width: 30em;
It's still responsive, because flex-basis works with proportions, so for 2 children it's equivalent to 50%.
Related
I have a div.grid that contains multiple div.column inside using flexbox. When a div.column increases in height due to having more content inside, all other div.column also increase in height.
It is to my understaind that this shouldn't help as their height is set to auto.
Also, my grid is using the flex display, with flex-wrap: wrap. I think is what is causing it, but I haven't found any explanation to why it is changing the children's height.
I have tried changing the following properties, in different combinations and manners, of parent and children: position, display, height.
These are the computed styles only, not my actual code.
div.grid {
display: flex;
flex-wrap: wrap;
width: 960px;
}
div.column {
display: block;
flex-basis: 37.5%;
flex-grow: 0;
flex-shrink: 0;
/* height is actually set to auto, but it is computed like this */
height: 132px;
}
<div class="grid">
<div class="column">something</div>
<div class="column">something<br>else<br>here</div>
<div class="column">something</div>
</div>
I expected the children to not fill the full height of the parent when the children don't all have the same amount of content.
As LGSon has asnwered in the comments:
Using flex: display automatically defaults align-items to stretch making the height of the children stretch to fill the height of the wrapper. It is also not shown in the computed properties, which is why it didn't cross my mind to check it.
Therefore, the solution was to add align-items: flex-start to .grid.
This question already has answers here:
Word-wrap in flexbox is not respecting 100% width limit [duplicate]
(2 answers)
Why don't flex items shrink past content size?
(5 answers)
Closed 4 years ago.
I have two flex children. I don't know the size of those children, but I want the .right (which contains unknown, but finite number of e.g. status icons) to not break, and fit on line, while .left child (which contains label of potentially too-long text) to break so that the .right child fits.
In the snippet, the .left should break the text so that the .right fits. Neither of the two children should overflow the .container.
I'm able to accomplish this by using word-break: break-word on .left, but that's non-standard. I can also use word-break: break-all, but that doesn't try to wrap the word on next line (as word-wrap does), first, which is undesirable. word-wrap: break-word doesn't do anything.
As stated, I cannot use width: calc( 100% - <right-width> ) on .left, because I don't know width of .right child.
note: the children's height: 20px is just to see the parent container. It's not part of the requirement.
Bonus: in the example the width of .container is known, but it may potentially not be known, either (i.e. it may inherit it in some way).
.container {
display: flex;
width: 200px;
height: 40px;
background: pink;
}
.left {
background: rgba(0,255,0,.1);
height: 20px;
// word-break: break-word; // works in WebKit, but non-standard
word-wrap: break-word;
}
.right {
background: rgba(0,0,255,.1);
height: 20px;
}
<div class="container">
<div class="left">xoxoxoxoxoxoxoxoxoxoxoxoxoxoxox</div>
<div class="right">rarararara</div>
</div>
the min-width: 0 on left ensures the element doesn't auto-resize to the parent flex container, and wraps as needed. It can be substituted with overflow: hidden, which has same effect.
If left to auto (default min-width flex value), it would overflow the container if it got too big. (thanks #Michael_B)
flex: 1 (shorthand for flex: 1 0 0, or flex-grow: 1; flex-shrink: 0; flex-basis: 0) ensures the left grows and pushes the right element to the right (thanks #LGSon)
right has initial flex values (flex: 0 1 auto) which ensures it doesn't word-break and doesn't grow above its content size, either.
WTBS, if it gets too big, it will also need word-wrap: break-word; min-width: 0 same as left.
Note: removed the 20px height which was not part of the OP requirement.
.container {
display: flex;
width: 200px;
background: pink;
}
.left {
background: rgba(0,255,0,.1);
word-wrap: break-word;
min-width: 0;
flex: 1;
}
.right {
background: rgba(0,0,255,.1);
}
<div class="container">
<div class="left">aaaaaaaa bbbbbbbbbbbbbbbbbbbb</div>
<div class="right">cccccc ccccc</div>
</div>
I've read awesome article and was astonished by the Flexbox Justification method. It works really well, but only when elements fit in the container entirely. I've created jsfiddle to illustrate this.
#container {
text-align: justify;
font-size: 0.1px; /* IE 9 & 10 don't like font-size: 0; */
min-width: 600px;
}
How, using this method, can I place the 6th element right after the 5th element without adding extra markup?
The sum of widths must not exceed the parent’s width, or there will be no space left to be distributed among them. Fixed (pixel) widths won’t always work on resize. If your six items are 150px each, and the container is, say, 800px in width, there’s no other way than to break into the next line.
Like the author of your article said: it’s more complicated. To stay that way, you could use calc() to have it dynamic. This is just an example:
.flex-item{
width: calc((100% / 6) - 20px); // 100% width ÷ 6 items - 20px space
}
Here’s an updated fiddle: https://jsfiddle.net/gy04jqdk/
Anyway, flexbox magic is relished best in its pure form. You can achieve the same using justify-content:space-between. To make it all work, you also have to add display:flex to the parent container. This will make it a flexbox and its immediate children flex-items. The extent of your changes might be limited to:
#container {
display: flex;
justify-content: space-between;
}
For visual illustration of element arrangement, the article at CSS-Tricks is well-known. You might be also interested in space-around, which is another value of justify-content.
Also, here’s a fiddle with a fixed width an evenly distributed space: https://jsfiddle.net/fdrgw3eu/
Assume you have a parent element that contains the three elements you would like to arrange in an equidistant manner:
.parent {
width: 100%;
}
.element1 {
width: 33.3%;
float: left;
}
.element2 {
width: 33.3%;
float: left;
left: -50%;
}
.element3 {
width: 33.3%;
float: right;
}
http://jsfiddle.net/u2zedzob/12/
<div class="wrapper">
<div class="main-content"></div>
<div class="footer"></div>
</div>
*, *:before, *:after {
box-sizing: border-box;
}
.wrapper {
background-color: red;
height: 300px;
width: 300px;
display: flex;
flex-direction: column;
}
.main-content {
height: 100%;
width: 100%;
background-color: green;
}
.footer {
height: 30px;
width: 100%;
background-color: blue;
display: table;
}
In this example, the footer's height is 30px and main-content grows to fill the rest of the space. Perfect!
However, if I remove the display: table property of footer -- its height becomes 27.266px. This can also be prevented by setting the footer's min-height to 30px.
I'm not too familiar with flex logic. Why is this happening? Is there a more elegant solution where the height of footer will be respected? Maybe a flex property I am missing?
When working with flex box model you do not need to set height property for the child elements which should scale. Instead you would use e.g. the flex-grow property. In the given case where just one element should be scaled a value of 1 would be appropriate (as no proportions need to be defined here).
Have a look at the updated example where the height of the .main-content element is scaled according to the available space and the height of the .footer element is retained correctly by 30px without setting the display property:
http://jsfiddle.net/u2zedzob/21/
For further information maybe check this guide:
http://css-tricks.com/snippets/css/a-guide-to-flexbox/
The flex-grow property is explained as:
This defines the ability for a flex item to grow if necessary. It
accepts a unitless value that serves as a proportion. It dictates what
amount of the available space inside the flex container the item
should take up.
If all items have flex-grow set to 1, every child will set to an equal
size inside the container. If you were to give one of the children a
value of 2, that child would take up twice as much space as the
others.
I want to set the width of the div elements' width accordingly depending on their container width. However, the number will be changed, so the width will need to be adjusted accordingly. Here is a CSSDeck link to explain the situation clearly:
http://cssdeck.com/labs/hvmkapkd
As you can see, both containers are identical (needed), also they have modular content (<div> elements) (which is also needed). Keeping the same structure, is it possible to auto adjust the width of the divs using CSS so that they fill up the whole container?
Then each item in the first container would have 33.333% width, and each item in the second container would have 20% width.
I found the solution right after posting the question.
Setting the .container elements as table and setting the colored content as table-cell made it.
Link is updated above, but here is the link once again anyway:
http://cssdeck.com/labs/hvmkapkd
Give the flex-box concept a chance (https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Flexible_boxes)
.container{
height: 100px;
width: 100px;
background-color: lightgray;
margin: 20px;
/* flexbox setup */
display: -webkit-flex;
-webkit-flex-direction: row;
display: flex;
flex-direction: row;
}
.container > div {
height: 100%;
/* flexbox setup */
-webkit-flex: 1 1 auto;
flex: 1 1 auto;
}
(http://cssdeck.com/labs/full/hvmkapkd)