I would like to evenly space around using flex on 3 columns but the last column is much smaller than the first 2, so I end up with dead space.
How do I take up the dead space to the right of the last column?
please see pic
enter image description here
Here is the code I'm working with now:
#side {
width:100%;
display:flex;
flex-direction:row;
flex-wrap:wrap;
justify-content:space-evenly;
}
#side > div {
text-align:justify;
padding:1.5rem;
width:33.33%;
}
<div id="side">
<div>long content</div>
<div>long content</div>
<div>short</div>
</div>
All 3 columns are equal (33.33%). The last column is much smaller than the first 2 so I would like to reclaim the dead space from the last element. How to do that with flex though?
You want to use flex: 1 in your CSS, which is a shorthand for flex-grow, flex-shrink and some more.
flex: 1 will take up all of the space available. If you would have two columns, column A with flex: 1 and column B with flex: 2, that would mean that column B would take twice as much space as column B.
I can recommend this: https://css-tricks.com/snippets/css/a-guide-to-flexbox/
And here is the code: https://jsfiddle.net/4mt20koh
Related
This question already has answers here:
Make flex item wrap to the next row with following items continuing the flow
(2 answers)
Closed 6 months ago.
I am trying to achieve a dynamic CSS grid layout where some columns with class 'featured' for example are going to expand on full width of the row and the other columns which don't have this class will stay and flow into 3 cols in a row layout.
But in my case is that if we take the second column for example and it becomes with class 'featured', then this column should expand full-width on the next row and then the flow of the columns to become - col 3 takes the place of col 2 and col 4 to come one row above and takes the position of col 3.
So it will become something like this afterwards:
col 3 becomes col2, col 4 goes one position up and goes on the position of col 3, col 2 (class 'featured') is going full width on the next row, then col 5 going on col 4 position and etc. And that's the concept from where I put class 'featured' on specific columns on the grid there to follow that same layout dynamic flow. Please refer to the attached mockup for reference.
Image Mockup for reference
Thank you. Hope someone can help me achieve this.
Best regards, Nick.
I think you can do this easily with css grid. They key would be to use grid-auto-flow: dense and then just add grid-column: 1 / -1 to the grid cell that you want to feature.
I have created a small demonstration here (click "Run code snippet" to see it work):
const button = document.querySelector('#btn');
const target = document.querySelector('#target');
button.addEventListener('click', () => {
target.classList.toggle('featured');
})
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-gap: .5rem;
margin-bottom: 1rem;
grid-auto-flow: dense;
}
.cell {
height: 50px;
background-color: lightgrey;
display: flex;
align-items: center;
justify-content: center;
}
.cell.featured {
background-color: pink;
grid-column: 1 / -1;
}
<div class="grid">
<div class="cell">1</div>
<div class="cell">2</div>
<div id="target" class="cell">3</div>
<div class="cell">4</div>
<div class="cell">5</div>
<div class="cell">6</div>
<div class="cell">7</div>
<div class="cell">8</div>
</div>
<button id="btn">Toggle featured</button>
You can click the button to toggle a "featured" class on the 3rd grid.
When it has the "featured" class it takes the whole row and the other cells take the available space.
(you won't need the JS. that is just for this demonstration)
i hope this is what you wanted...
I have a somewhat complicated problem. I have to present ingredients of recipes in 2 columns. One column is the ingredient quantity and measuring unit and on the right it is the ingredient.đ
Structure wise one ingredient get's 2 DIV-s, left and right part
.recipeIngredient {
display: flex
}
.unit {
flex: 1: border-right:1 px solid #666;
padding-right: 3%;
text-align: right;
}
.ingredient {
flex: 2;
padding-left: 3%;
text-align: left
}
<p class='recipeIngredient'>
<div class='unit'>1 kg</div>
<div class='ingredient'>flour (it should be wholegrain type</div>
</p>
<p class='recipeIngredient'>
<div class='unit'>2 pieces of big</div>
<div class='ingredient'>tomatoe</div>
</p>
There can be numerous rows.
I did this with floats and widths, but it doesn't play out well, so I am trying to use flex. In my example left column is 33% width and the right one is double the size. That is usually ok. But sometimes I get a longer line in the left column and sometimes in the right.
How can I make the widths fluid in a way if all of my rows in column one are short and the right rows are longer that have to be broken into two, the width proportions would change, giving only the needed space of the left or right column?
And another problem here is that I want to give priority to the left column if content is too long of both columns, the right one should break, not the left one, because it looks stupid if the column is like this:
up to 1 | wholewheet flower
kg
I would rather have the wholewheet flower would break and left side would keep together if possible. And if there is room on the left side, shrink column and give more space to the right one.
I am not sure if this is possible at all, because I have cells row based not column based and all should adapt acording to the whole, not each one separately, I would like all ingredients to be aligned (left side right justified and right side left justified).
There is one other problem I do have with my code. If I like to vertical align ingredient to the bottom instead of top so that it would read
up to 1 |
kg | wholewheet flower
It looks better. But using flex to put it on bottom shrinks right cell to the content so the divider line is missing on top.
PS - Maybe this could be better done without using CSS grids? But I guess my structure is not the best for it, but it is needed for google smart cards.
Using table:
section {
display: table;
table-layout: fixed;
border: 1px solid;
max-width: 200px;
}
.recipeIngredient {
display: table-row;
}
.unit,
.ingredient {
display: table-cell;
outline: 1px solid;
padding: 5px;
}
.unit {
white-space: nowrap;
}
<section>
<div class='recipeIngredient'>
<div class='unit'>1 kg</div>
<div class='ingredient'>flour (it should be wholegrain type</div>
</div>
<div class='recipeIngredient'>
<div class='unit'>2 pieces of big</div>
<div class='ingredient'>tomatoe</div>
</div>
</section>
This question already has answers here:
Flexbox 3 divs, two columns, one with two rows
(3 answers)
Closed 5 years ago.
I have an HTML markup structure like so:
<div class="container>
<div id="one"></div>
<div id="two"></div>
<div id="three"></div>
</div>
I am trying to shape this markup into display flex row. Where div one takes up half the line width and the remaining divs take the other half of the line width but are stacked on top of each other in the same line as div one.
I realize that I should probably wrap div 2 and 3 in a div and then execute the design I am seeking. I am just wondering if it is possible to do so without wrapping div 2 and 3 in another div.
Thanks!
You will have to wrap them with another div, a quick example for it will be giving your container:
.container {
display: flex;
flex-direction: row;
}
Then, you make a wrapper for both two and three, and giving him:
.wrapper {
display: flex;
flex-direction: column;
}
That's the most basic thing, you will need to modify other things of course.
I have a layout with multiple columns, of which some are fixed and others stretch as needed. Therefore, I use flexbox. Additionally, I want and need to use flex-wrap.
The structure is like this:
<div class="row" style="display: flex; flex-flow: row wrap">
<div class="column fixed" style="flex: 0 0 auto"></div>
<div class="column stretch" style="flex: 1 1 auto"></div>
<div class="column fixed" style="flex: 0 0 auto"></div>
</div>
Please see http://jsfiddle.net/mh3rypqj/1/
Now everything works as expected as long as we are talking about empty divs. Once I put a p in the stretch column, wrapping and shrinking behaves differently.
My expected behaviour when space is getting smaller: First shrink, then wrap. Shrink the .stretch. Once min-width is reached, wrap the elements.
The behaviour I get once I put the p in .stretch: First wrap, then shrink. The row is first wrapped. Shrinking only occurs after everything is wrapped.
I want to have First shrink, then wrap. In short, I want the second row in the JSFiddle to behave just like the first. What do I have to do?
Set flex-basis equal to min-width:
.column.stretch {
flex: 1 1 100px; /* or 1 0 100px, and no more need in min-width at all */
max-width: 300px;
min-width: 100px;
background: red;
}
edited JSfiddle example
When using flex-flow, shrinking only ever happens AFTER the flex-basis size is reached. So setting flex-basis: 100px as suggested above, means you want the line to start wrapping once there's not enough room for all the items, including that column's 100px basis. Once room runs out, items will wrap down onto a new line. When space runs out again, a new line will form. This continues until each item has its very own line. Only then - if there's still not space for the basis - will the item(s) start to shrink.
The reason you're seeing a difference with the paragraph of content is because you're not explicitly setting a flex-basis. If flex-basis is set to auto, then it will fallback to the item's width. If width isn't set, the basis falls back to item's size once its content is rendered, then corrected by min and max width. So 300px in this case because you set a max-width. Notice that if you take off the max-width that item gets a full 100% width and instantly gets flowed down to its own line. Then when you resize the page that item starts to shrink because it already has its own line and there's not enough space for that initial size.
Hope that helps!
I'll throw this in, based on what worked for me in the answers here. It grows, it shrinks, it wraps. (Syntax is verbose for clarity.) Note that the flex-basis/min-width value and the user's current browser zoom change what happens. AFAICS.
<div id="outer"
style="
display: flex;
flex-wrap: wrap;
">
<div id="inner"
style="
flex-grow: 1; /* it can grow */
flex-shrink: 1; /* it can shrink */
flex-basis: 225px; /* arbitrary depending on design */
min-width: 225px; /* equal to flex-basis */
max-width: 20%; /* (100% - margins)/number of boxes */
padding: .5em; /* half of desired margin */
">
<...content...>
</div>
</div>
i've got 4 columns in one row and depending on how much information i put in each of them they will have different heights. you can see that if you put a background color on them.
how do i give the other columns the height of the column with the largest height?
You can use jQuery to do this.
http://www.cssnewbie.com/equal-height-columns-with-jquery/
Alternaively for a CSS only approach you can make it look like they are the same height, by wrapping all columns in a div, and then applying a single background image, with 4 blocks of colour that match the column widths.
This wrapper div will expand to be the size of the largest column, and will give the impression of 4 equal sized cols.
Well, I don't know if this works for 960, but in Blueprint you can get that by applying the following style to the columns:
padding-bottom : 20000px;
margin-bottom : -20000px;
overflow:hidden;
You could use CSS property display: table-cell
http://jsfiddle.net/AGjBM/
<style>
div.table-cell {
display: table-cell;
border: 1px solid;
}
</style>
<div class="table-cell">
Some Text
</div>
<div class="table-cell">
Some Text<br>
Some More Text
</div>