How to have items in flexbox only take content width? - html

I have a container which has a display flex property and i set the flex-wrap to wrap.
Problem I am having is that I am getting to much space between items.
My code:
#container {
display: flex;
flex-wrap: wrap;
width: 250px
}
.child {
flex-grow: 1;
flex-shrink: 1;
flex-basis: auto
}
<div id="container">
<div class="child">Ss</div>
<div class="child">Very very very long text text text</div>
<div class="child">Small</div>
<div class="child">Medium</div>
</div>
Image:
Can find code in action here:
Fiddle

The flex-grow property distributes free space on the line, based on the value applied.
If you give all items flex-grow: 1, each item will consume equal space.
Since you have two items with flex-grow: 1, they split the space on the line 50-50.
Remove flex-grow. Use margins or padding.

Remove the flex grow and add a gap to create a bit of a space between items.
#container {
display: flex;
flex-wrap: wrap;
width: 250px;
gap: 5px; /*emphasized text*/
}
.child {
flex-shrink: 1;
flex-basis: auto;
}

Related

what is the reason that display flex make <hr> hidden? [duplicate]

When using flexbox for styling, if the parent container is set to display: flex it will cause the <hr /> to be displayed vertically instead of horizontally.
.container {
display: flex;
flex: 1;
}
<div class='container'>
<h2>Test</h2>
<hr />
</div>
Use flex-grow: 1 or width: 100% so it will grow to match the width of the parent. You probably want to use that in combination with flex-wrap: wrap on .container if you plan on putting more flex children in .container
.container {
display: flex;
flex: 1;
}
hr {
flex-grow: 1;
/* width: 100%; */ /* or this */
}
<div class='container'>
<hr>
</div>
The reason for this is that default value of align-items is stretch so hr will get the same height as largest element in flex-container or in this case h2. And default value for justify-content is flex-start so width of hr is 0.
Easy way to fix this is to use flex-wrap: wrap on parent element and flex: 0 0 100% on hr
.container {
display: flex;
flex-wrap: wrap;
}
hr {
flex: 0 0 100%;
}
<div class='container'>
<h2>Test</h2>
<hr>
</div>

Center a flex item when its siblings have different widths [duplicate]

This question already has answers here:
Keep the middle item centered when side items have different widths
(12 answers)
Closed 5 years ago.
I know flexbox offers a great solution for centering items. But I run into an issue when I have 3 items and I'd like the center (2nd) item to be centered with respect to the window, regardless of the size of the other 2 items.
In my pen you can see the second item "Client Index" is off-center because the content on the right is larger than the content on the left. How can I force it to center itself?
.flex {
display: flex;
align-items: center;
justify-content: space-between;
}
<div class="flex">
<span style="font-size:12px;">small</span>
<span style="font-size:20px;">Client Index</span>
<span style="font-size:18px;">Lots of content that moves the center</span>
</div>
My Codepen
One way would be to set flex-grow: 1; flex-basis: 0 so the 3 columns are distributed evenly, then you can center the text or the content in the middle one.
I'm using text-align to center the middle column. You could also use display: flex; justify-content: center; to do the same thing.
.flex {
display: flex;
align-items: center;
justify-content: space-between;
}
.flex > span {
flex: 1 0 0;
}
.flex > span:nth-child(2) {
text-align: center;
}
<div class="flex">
<span style="font-size:12px;">small</span>
<span style="font-size:20px;">Client Index</span>
<span style="font-size:18px;">Lots of content that moves the center</span>
</div>
Use nested flex containers and auto margins.
.flex-container {
display: flex;
}
.flex-item {
flex: 1;
display: flex;
justify-content: center;
}
.flex-item:first-child>span {
margin-right: auto;
}
.flex-item:last-child>span {
margin-left: auto;
}
/* non-essential */
.flex-item {
align-items: center;
border: 1px solid #ccc;
background-color: lightgreen;
height: 40px;
}
<div class="flex-container">
<div class="flex-item"><span>short</span></div>
<div class="flex-item"><span>medium</span></div>
<div class="flex-item"><span>lonnnnnnnnnnnnnnnnnnnng</span></div>
</div>
Here's how it works:
The top-level div is a flex container.
Each child div is now a flex item.
Each item is given flex: 1 in order to distribute container space equally.
Now the items are consuming all space in the row and are equal width.
Make each item a (nested) flex container and add justify-content: center.
Now each span element is a centered flex item.
Use flex auto margins to shift the outer spans left and right.
You could also forgo justify-content and use auto margins exclusively.
But justify-content can work here because auto margins always have priority. From the spec:
8.1. Aligning with auto
margins
Prior to alignment via justify-content and align-self, any
positive free space is distributed to auto margins in that dimension.

Flex-direction column makes flex items overlap IE11

I'm running into an issue using flexbox in IE11. When using flex-direction: column the flex-items overlap:
In other browsers (chrome, safari) it looks like this:
.container {
display: flex;
flex-direction: column;
}
.flex {
flex: 1 1 0%;
}
<div class="container">
<div class="flex">
Hello
</div>
<div class="flex">
World
</div>
</div>
I've made a codepen to demonstrate the issue:
http://codepen.io/csteur/pen/XMgpad
What am I missing to make this layout not overlap in IE11?
It is caused by the 0% in your .flex class. Change it to auto then it should not be a problem:
.flex {
flex: 1 1 auto;
}
Instead of flex: 1 1 0%; use flex: 1 1 auto;
.container {
display: flex;
flex-direction: column;
}
.flex {
flex: 1 1 auto;
}
<div class="container">
<div class="flex">
Hello
</div>
<div class="flex">
World
</div>
</div>
My particular solution to this issue was that I needed to explicitly set the width on the containing element. Since flex is set to column IE11 will automatically expand the width of the container to accommodate the content of the children (remember that the flex boxes are flipped on their sides in column alignment so when they overflow they grow horizontally instead of vertically).
So my code would look like:
.container {
display: flex;
flex-direction: column;
width: 100%; // needs explicit width
}
.flex {
flex: 1 1 auto; // or whatever
}
Note also that flex: 1; compiles to flex : 1 1 0%;, so it's better (for IE users) if you explicitly write flex: 1 1 auto;, as mentioned above.

Flex items not wrapping

My issue is that I have a section within the article that I made a flexbox, and when I reduce the size of the browser those 3 elements in that flexbox will overlap. Any tips?
body {
display: flex;
flex-direction: column;
}
header {
background: blue;
}
main {
display: flex;
flex-direction: row;
flex: auto;
}
article {
flex: 2;
overflow-y: auto;
background: red;
}
aside {
flex: 1;
overflow-y: auto;
background: green;
}
.test {
display: flex;
flex-direction: row;
flex: auto;
align-items: stretch;
background: pink;
}
<body>
<header>
Test
</header>
<main>
<article>
<section>
test
</section>
<section class="test">
<div>
div one
</div>
div two
<div>
div three
</div>
<div>
</div>
</section>
</article>
<aside>
aside
</aside>
</main>
<footer>
</footer>
</body>
http://jsfiddle.net/zLmcyjy6/
Try adding flex-wrap: wrap to the flex container. Flex items do not wrap by default.
In reference to your website (I didn't use your fiddle demo, which has different code), each of the non-wrapping elements is a <section> child of <section class="other">, which is a row-direction, wrap-enabled flex container.
Each <section> flex item has a flex: 1 applied. This translates to:
flex-grow: 1
flex-shrink: 1
flex-basis: 0
With flex-basis set to zero, the initial main size of the flex item is 0, and the width could shrink to that degree, so there's no opportunity to wrap.
I would suggest changing flex-basis: 0 to something like flex-basis: calc(33% - 2em) (i.e., width minus approx. margin, border, padding), for wider screens. So flex: 1 1 calc(33% - 2em).
And then for smaller screens, using a media query, set flex-basis to something like:
#media screen and ( max-width: 500px ) {
.fitness, .education, .pastimes {
flex-basis: 100%;
display: flex; /* optional; for nicer alignment */
flex-direction: column; /* optional; for nicer alignment */ }
}
Alternatively, if you wanted to avoid using media queries, you could set a fixed value to flex-basis which would enable wrap, as well. Something like flex: 1 0 200px.

Keeping all elements aligned to the same grid and spanning multiple columns

I'm trying out CSS3's flexbox for the first time and it seems promising, but I'm having some trouble getting it to behave.
Basically, I want flexbox to behave like a table but with an order property so I can tell it in the CSS what order to display the elements in the grid. Is this even possible with flexbox?
Here's the test page I created: https://jsfiddle.net/Lb838dwf/
HTML:
<div id="main">
<div id="div1">div 1</div>
<div id="div2">div 2</div>
<div>generic</div>
<div id="div3">div 3</div>
<div>generic</div>
<div id="div4">div 4</div>
<div>generic</div>
<div>generic</div>
<div>generic</div>
<div>generic</div>
<div>generic</div>
</div>
CSS:
#main {
width: 100%;
border: 1px solid #c3c3c3;
display: -webkit-flex;
display: flex;
-webkit-flex-wrap: wrap;
flex-wrap: wrap;
}
#main div {
min-width: 25%;
height: 100px;
-webkit-flex: 1;
flex: 1;
-webkit-order: 2;
order: 1;
background-color: #ccc;
}
#main #div1 {
-webkit-order: 3;
order: 3;
background-color: coral;
}
#main #div2 {
-webkit-order: 5;
order: 5;
background-color: lightblue;
}
#main #div3 {
-webkit-flex: 2;
flex: 2;
-webkit-order: 2;
order: 2;
background-color: lightgreen;
}
#main #div4 {
-webkit-order: 4;
order: 4;
background-color: pink;
}
You can see that #div3 has flex: 2, which means it should span two columns, but it's only taking up 1 column. Also, the 3 divs at the bottom (div1, div4, div2) aren't aligning to the same grid as the items above it. If I add max-width: 25% to the #main div style, it keeps everything to the same grid, but spanning columns doesn't work. I tried setting max-width: 25% for all divs and max-width: none for just #div3 (the one with flex:2) but that doesn't have an affect.
Let's dissect a few of the things you wrote so we could clarify flexbox behavior.
You can see that #div3 has flex: 2, which means it should span two
columns, but it's only taking up 1 column.
flex: 2 does not mean it should span two columns. This isn't like an HTML colspan attribute. (And even if it was, you have three other flex items ["table cells"] already occupying the three remaining columns, so how would #div3 expand two columns? It would have to break out of the grid.)
The flex property is a shorthand for the flex-grow, flex-shrink and flex-basis properties.
The flex-grow property controls how flex items will expand by distributing remaining space in the flex container. So by applying flex: 2 you're saying you want the flex item to take twice as much remaining space than its siblings, not necessarily be double their size.
From the spec, the flex-grow property:
...determines how much the flex item will grow relative to the rest of
the flex items in the flex container when positive free space is
distributed.
However, since you've given the container (#main) a width: 100%, and each flex item min-width: 25%, there is no remaining space to distribute. So nothing happens.
To illustrate this behavior, change the width of each flex item to 50px. This leaves extra space to distribute and #div3 takes 2x as much. See demo: https://jsfiddle.net/Lb838dwf/6/
Also, the 3 divs at the bottom (div1,div4,div2) aren't aligning to
the same grid as the items above it.
Correct. They're not aligning because you applied flex: 1 to them in #main div. This tells them to evenly distribute all remaining space among themselves.
If I add max-width: 25% to the #main div style, it keeps
everything to the same grid, but spanning columns doesn't work. I
tried setting max-width: 25% for all divs and max-width: none for
just #div3 (the one with flex:2) but that doesn't have an affect.
What? You lost me.
I want flexbox to behave like a table but with an order property so I
can tell it in the CSS what order to display the elements in the grid.
Is this even possible with flexbox?
Yes, it's possible.
HTML
<div id="main">
<div>div 1</div>
<div>div 2</div>
<div>div 3</div>
<div>div 4</div>
<div>div 5</div>
<div>div 6</div>
<div>div 7</div>
<div>div 8</div>
<div>div 9</div>
<div>div 10</div>
<div>div 11</div>
</div>
CSS
#main {
display: flex;
justify-content: flex-start;
flex-wrap: wrap;
width: 100%;
}
#main div {
flex: 0 0 150px; /* don't grow, don't shrink, stay at 150px */
height: 100px;
margin: 5px;
background-color: #ccc;
border: 1px dashed black;
}
#main div:nth-child(2) { order: -4; background-color: lightblue; }
#main div:nth-child(5) { order: -3; background-color: lightgreen; }
#main div:nth-child(8) { order: -2; background-color: lightyellow; }
#main div:nth-child(11) { order: -1; background-color: lightpink; }
DEMO: http://jsfiddle.net/Lb838dwf/4/
Spanning multiple columns
As mentioned above, the flex property is a shorthand for the flex-grow, flex-shrink and flex-basis properties.
flex-grow tells flex items how to distribute available space, hence it is not a reliable tool for emulating the HTML colspan attribute. (The space available in the container and double the size of a flex item are unrelated lengths and not necessarily equal.)
However, the flex-basis property, which sets the initial size of a flex item, can be used to make flex items twice as wide, three times as wide, whatever.
In my code above, flex items are set to: flex: 0 0 150px; The third value represents flex-basis. So each box is set to 150px wide.
For a flex item to occupy two columns simply double that value.
Since flex cascades to all divs, we only need to adjust the flex-basis for targeted items.
#main div:nth-child(11) { flex-basis: calc(300px + 10px); } /* factoring in margin space */
#main div:nth-child(7) { flex-basis: calc(450px + 20px); } /* factoring in margin space */
DEMO: http://jsfiddle.net/Lb838dwf/5/ (expand window for effect)