Always wrap at least two items with flexbox - css

Take a look at this example
It has a flexbox container with flex-flow: row wrap; to wrap all items. This is almost what I want.
When it starts to wrap, item number 6 wraps to the second line:
1 2 3 4 5
6
But always I want to wrap at least two items when it starts to wrap so you'll never have a single items on a line:
1 2 3 4
5 6

While not the most elegant solution, you could wrap the last two elements in another flexbox:
<html>
<head>
<style>
.flex {
display: flex;
flex-wrap: wrap;
}
.flex > div {
flex: 1 0 auto;
padding: 20px;
text-align: center;
}
.flex .flex {
padding: 0;
flex-grow: 2;
}
</style>
</head>
<body>
<div class="flex">
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div class="flex">
<div>5</div>
<div>6</div>
</div>
</div>
</body>
</html>
See a pen here: https://codepen.io/anon/pen/prodVd

I figured out a way to do it for inline Elements, however it will behave inconsistently across browsers when used with inline-blocks. Still not a solution, but maybe somebody can figure out a way to make it behave with inline-block elements.
.item {
display: inline;
}
.item::before {
content: ' ';
font-size: 0;
}
.item:last-child::before {
content: '';
}
Here is a Fiddle with it in action.

Here's an approach that should work under the constraint that the width of the element is fixed
Assuming the width is 50px:
.container {
display: flex;
flex-flow: row wrap;
}
.flex-item: {
width: 50px;
display: block;
}
.flex-item:nth-child(even) {
translateX(100%)
margin-left: -100px;
}
.flex-item:nth-child(odd) {
margin-right: 50px;
}
The trick is to basically move the "footprint" of every 2nd element into its predecessor (negative margin), still display it in its original place (translate) and having the predecessor eat the remaining space (positive margin) for the purpose of row-breaking.

You can try to wrap 2 sibling elements with flex container

Based on https://stackoverflow.com/a/30431565/6884587 which did not work due to syntactical and logical reasons, I figured out how to do it for preknown same width items.
.container {
display: flex;
flex-flow: row wrap;
justify-content: center;
/* gap: 5px <-- can be used for spacing */
}
.flex-item: {
width: 50px;
display: block;
}
.flex-item:last-child {
margin-left: -50px; /* consider gap in this value, if applicable */
}
.flex-item:nth-last-child(2) {
margin-right: 50px; /* consider gap in this value, if applicable */}
This way, the last and the next to last item literally end on the same pixel, causing them to wrap line together.
For not preknown, but same width items it is a little more complex, since setting the margin to a percentage value is based on the item parent's width.

Related

How to position elements side-by-side using flexbox when they automatically wrap without filling up the row

I have tried every solution that I am aware of to get these two footer elements to display side-by-side on mobile. I have three footer widgets on a wordpress site (www.med-tac.com) and I am trying to reorder and re-align them on mobile using the #media approach for my screen size.
I am trying to get 1 and 3 on the same line and have tried adjusting the other properties to get it to work, but am now working with flexbox to try to accomplish this, but would be happy to revert to any solution that works.
I have tried the grid layout, the float left and float right approach, the flexbox approach and the display inline block approach, none of which will display the elements on the same line, even when the width is manually decreased to far less than the mobile footer width.
#media (max-width: 480px){
.secondary {
display:flex;
flex-flow: row wrap;
}
#footer-sidebar1 {
margin-top:-5px;
top:5px;
order:2;
}
#footer-sidebar2 {
margin-right: 20px !important;
right: 10px;
width:325px !important;
bottom:25px;
order:1;
}
#footer-sidebar3 {
order:3;
}
}
I am trying to get sidebar 1 and 3 to display side-by side on the same line, but they are wrapping on top of each other.
If you want to have items 1 and 3 in the first line, you need to set the order of the item 3 to be less than the order for item 2.
For instance:
.secondary {
display: flex;
flex-flow: row wrap;
}
.secondary div {
background-color: lightblue;
}
.secondary:after {
content: "";
order: 2;
flex-basis: 110%;
}
#footer-sidebar1 {
flex-basis: 48%;
order: 3;
}
#footer-sidebar2 {
order: 1;
margin-right: 100px;
}
#footer-sidebar3 {
flex-basis: 48%;
order: 4;
margin-left: 10px;
}
<div class="secondary">
<div id="footer-sidebar1">sidebar 1 </div>
<div id="footer-sidebar2">sidebar 2 </div>
<div id="footer-sidebar3">sidebar 3 </div>
</div>

Creating cv elements with flexbox

I want to make a div which includes my experience.
So I tried making a div (wrapper) which includes span for each word. Then I tried on each element with nth-child to give a style justify-content: flex-end;
The element goes to the end indeed, but the next element does not take it place. So if I try to flex-end the 'verkoopmedewerker' it goes to the right but a break appears at its previous place so 'plaats' will have a gap between 'functie' and itself.
How can I achieve what the picture shows?
See my DEMO here
.baan {
display: flex;
flex-flow: column;
background: red;
width: 40%;
}
.baan :nth-child(3) {
align-self: flex-end;
}
<h3>Bijbaan</h3>
<div class="baan">
<strong>Lidl</strong>
<span>Functie</span>
<span class="rechts">Verkoopmedewerker</span>
<span>Plaats</span>
<span class="rechts">Almeloplein 73
2533 AD, Den Haag
Part-time, 54 uur P. week
</span>
</div>
This is a possible flexbox solution:
.baan {
display: flex;
flex-flow: row wrap;
background: red;
width: 40%;
}
.baan span{
flex: 1 1 50%; /*change width if you don't want the same width for every "span"*/
}
.baan strong{
flex: 1 1 100%;
}
.baan .rechts{
text-align:right;
}
However, I think CSS-grid is better in your case 'cause works in 2 directions: rows and columns. Flexbox works well only in one direction and you have "to hack" this limit if you want it works like grid.

Flexbox: how to get divs to fill up 100% of the container width without wrapping?

I'm in the process of updating an old inline-block-based grid model I have to a newer Flexbox one I created. Everything has worked fine, apart from one little snag, which has become a bit of a dealbreaker:
I have a bunch of CSS-controlled sliders; so there's a containing wrapper with 100% width, and inside is another div: its width is also 100%, but its white-space is set to nowrap. Using inline-block, this meant that the internal divs (which were also set to 100% width) wouldn't be bound by their parents' constraints and wrap onto the next line - they'd just carry on flowing out of the box. This is exactly what I wanted. However, I cannot get this to work at all with flexbox. For reference, here's an image:
And for reference, here's a jsFiddle of the thing working with inline-block: http://jsfiddle.net/5zzvqx4b/
...and not working with Flexbox: http://jsfiddle.net/5zzvqx4b/1/
I've tried all kinds of variations with flex, flex-basis, flex-wrap, flex-grow, etc. but for the life of me I can't get this to work.
Note that I can force it to do what I want in a hacky, inflexible way by setting the .boxcontainer width to 200%. That works for this single example, but in some cases I won't know beforehand how many child boxes there will be, and I'd rather not resort to inline styling on each element if possible.
To prevent the flex items from shrinking, set the flex shrink factor to 0:
The flex shrink factor determines how much the flex item will
shrink relative to the rest of the flex items in the flex
container when negative free space is distributed. When omitted, it is
set to 1.
.boxcontainer .box {
flex-shrink: 0;
}
* {
box-sizing: border-box;
}
.wrapper {
width: 200px;
background-color: #EEEEEE;
border: 2px solid #DDDDDD;
padding: 1rem;
}
.boxcontainer {
position: relative;
left: 0;
border: 2px solid #BDC3C7;
transition: all 0.4s ease;
display: flex;
}
.boxcontainer .box {
width: 100%;
padding: 1rem;
flex-shrink: 0;
}
.boxcontainer .box:first-child {
background-color: #F47983;
}
.boxcontainer .box:nth-child(2) {
background-color: #FABCC1;
}
#slidetrigger:checked ~ .wrapper .boxcontainer {
left: -100%;
}
#overflowtrigger:checked ~ .wrapper {
overflow: hidden;
}
<input type="checkbox" id="overflowtrigger" />
<label for="overflowtrigger">Hide overflow</label><br />
<input type="checkbox" id="slidetrigger" />
<label for="slidetrigger">Slide!</label>
<div class="wrapper">
<div class="boxcontainer">
<div class="box">
First bunch of content.
</div>
<div class="box">
Second load of content.
</div>
</div>
</div>
You can use the shorthand flex property and set it to
flex: 0 0 100%;
That's flex-grow, flex-shrink, and flex-basis in one line. Flex shrink was described above, flex grow is the opposite, and flex basis is the size of the container.
In my case, just using flex-shrink: 0 didn't work. But adding flex-grow: 1 to it worked.
.item {
flex-shrink: 0;
flex-grow: 1;
}
Set the flex-direction: column
You're trying to stack the items in a column rather than a row.
{
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}

CSS flex, how to display one item on first line and two on the next line

This is a pretty simple question, I guess, but I can't get 3 items in the flex container to display in 2 rows, one in the first row and the other 2 in the second row. This is the CSS for the flex container. It displays the 3 items on a single line, obviously :)
div.intro_container {
width: 100%;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
}
If flex-wrap is set to wrap, then the 3 items are displayed in a column. I thought the wrap setting was needed to display container items on several lines.
I've tried this CSS for the first container item, intending to have it occupy the whole of the first row, but it didn't work
div.intro_item_1 {
flex-grow: 3;
}
I've followed the instructions in "CSS-Tricks" but I'm really not sure which combination of commands to use. Any help would be very welcome as I'm puzzled by this.
You can do something like this:
.flex {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.flex>div {
flex: 1 0 50%;
}
.flex>div:first-child {
flex: 0 1 100%;
}
<div class="flex">
<div>Hi</div>
<div>Hello</div>
<div>Hello 2</div>
</div>
Here is a demo: http://jsfiddle.net/73574emn/1/
This model relies on the line-wrap after one "row" is full. Since we set the first item's flex-basis to be 100% it fills the first row completely. Special attention on the flex-wrap: wrap;
The answer given by Nico O is correct. However this doesn't get the desired result on Internet Explorer 10 to 11 and Firefox.
For IE, I found that changing
.flex > div
{
flex: 1 0 50%;
}
to
.flex > div
{
flex: 1 0 45%;
}
seems to do the trick. Don't ask me why, I haven't gone any further into this but it might have something to do with how IE renders the border-box or something.
In the case of Firefox I solved it by adding
display: inline-block;
to the items.
For SCSS file you can write this way:
.flex {
display: flex;
flex-direction: row;
flex-wrap: wrap;
>{
flex: 1 0 50%;
}
&:first-child{
flex: 0 1 50%;
}
}
<div class="flex">
<div>1</div>
<div>2</div>
<div>3</div>
</div>
Output:
1 2
3

Fill remaining horizontal space (or max-width) AND wrap on min-width

#fit and #wrap illustrate two different behaviors that I want to have for one element depending on the situation. The element should work like #fit if there is room, but should work like #wrap if there is not enough room.
http://jsfiddle.net/benstenson/dN8VJ/
<div id="print">
Printable
</div>
<div id="fit">
Looks good on same line
</div>
<div id="wrap">
Looks good on new line
</div>
css
body{overflow:hidden;padding:1em;}
div
{
/*display:inline-block;*/
float:left;
height:1in;
margin:.5em;text-align:center;line-height:1in;
white-space:nowrap;box-shadow:0 0 .5em gray;
}
#print
{
width:5in;
background-color:black; color:white;
}
#fit
{
/* when on same line
Size to min-width
OR fill remaining space
(like flexible box style).
Either way is fine.
*/
min-width:3in;
background-color:gold;
}
#wrap
{
/* when wrapped to next line */
/* fill 100% OR to max width */
width:100%;
min-width:3in;
max-width:5in;
background-color:orange;
}
What you're looking for is Flexbox, but most browsers that support Flexbox don't support wrapping. The ones that do are IE10, Chrome, and Opera.
http://codepen.io/cimmanon/pen/lqrGB
<div class="container">
<div id="print">
Printable
</div>
<div id="either">
Looks good on either line
</div>
</div>
.container {
display: -ms-flexbox;
display: -webkit-flex;
-webkit-flex-wrap: wrap;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
}
#supports (flex-wrap: wrap) {
.container {
display: flex;
}
}
.container div {
height: 1in;
margin: .5em;
text-align: center;
line-height: 1in;
white-space: nowrap;
box-shadow: 0 0 .5em gray;
}
#print {
/*-webkit-flex: 1 5in;
-ms-flex: 1 5in;
flex: 1 5in;*/
width: 5in;
background-color: black;
color: white;
}
#either {
-webkit-flex: 1 3in;
-ms-flex: 1 3in;
flex: 1 3in;
max-width: 5in;
background-color: gold;
}
Assuming I've understood your question correctly, I think you can achieve what you want with inline-block.
You'll need to put your content in a paragraph inside another div, like this:
<div class="wrap-or-fit">
<p>This is where your content goes.</p>
</div>
Then just set the min-width and max-width properties on the paragraph, as well as display:inline-block.
.wrap-or-fit > p {
max-width:5in;
min-width:3in;
display:inline-block;
...
}
If the content fits on a single line less than 3 inches wide, the container will expand to be at least 3 inches. If the content is wider than 5 inches, it is forced to wrap within a container of exactly 5 inches.
If the content is between 3 and 5 inches, the container width matches the content width. I'm not sure if that is what you wanted, but that may be the best you can do.
You can see an expanded example showing both narrow and wide content samples, and styling that more closely matching your original example in this codepen.

Resources