css flexbox 3-column layout where first is fixed width - html

I am trying to better understand flex box css and have a main layout for all pages. It is 3 columns where the first column is fixed width and the others can be any size so long as all 3 take up 100% width.
I believe the problem is in .col class but unsure how to set the 1st column and let the other grow. Thank you.
.wrapper {
display: flex;
flex-direction: row;
}
.col {
flex-basis: 25%;
align-items: stretch;
}
<div class="wrapper">
<div class="col">1</div>
<div class="col">2</div>
<div class="col">3</div>
</div>

You simply need to specify a fixed width to the first one and then set flex:1 to the other so they take the remaining space and fill 100% of the container space:
.wrapper {
display: flex;
flex-direction: row;
}
.col {
flex: 1;
background: red;
}
.col:first-child {
width: 100px; /* Or a percentage value */
flex:initial;
background: green;
}
<div class="wrapper">
<div class="col">1</div>
<div class="col">2</div>
<div class="col">3</div>
</div>

Related

Is flex's "align-items:flex-end" causing fixed-height divs inside flex-wrapped boxes to be vertically aligned according to each box's tallest one?

Doing a fairly basic HTML page I found myself perplexed by the following issue with flex in CSS.
First assume the following configuration:
A div wrapper with display: flex and applying justify-content: space-evenly, containing three inner boxes (could be more or less) each one also using flex (applying flex-wrap: wrap and align-items: end).
Each one of those inner boxes contains, in turn, two div elements: a top one and a bottom one (each with width: 100%); the bottom element has the same height while the top element has a different height per box; all of them are fixed heights in px.
This configuration looks more or less like this in HTML:
<div class="wrapper">
<div class="box">
<div class="top-element one"></div>
<div class="bottom-element one"></div>
</div>
<div class="box">
<div class="top-element two"></div>
<div class="bottom-element two"></div>
</div>
<div class="box">
<div class="top-element three"></div>
<div class="bottom-element three"></div>
</div>
</div>
And here's the CSS (written in SCSS to save space, I will include a snippet below where you can check the compiled CSS should you prefer); the commented line: "align-content: flex-end" indicates that I've already evaluated the effect of this property.
.wrapper {
display: flex;
justify-content: space-evenly;
.box {
display: flex;
align-items: flex-end;
// align-content: flex-end;
flex-wrap: wrap;
width: 30%;
.top-element {
width: 100%;
background-color: teal;
&.one {
height: 200px;
}
&.two {
height: 300px;
}
&.three {
height: 100px;
}
}
.bottom-element {
width: 100%;
background-color: lightblue;
&.one {
height: 100px;
}
&.two {
height: 100px;
}
&.three {
height: 100px;
}
}
}
}
Here's the snippet.
.wrapper {
display: flex;
justify-content: space-evenly;
}
.wrapper .box {
display: flex;
align-items: flex-end;
flex-wrap: wrap;
width: 30%;
}
.wrapper .box .top-element {
width: 100%;
background-color: teal;
}
.wrapper .box .top-element.one {
height: 200px;
}
.wrapper .box .top-element.two {
height: 300px;
}
.wrapper .box .top-element.three {
height: 100px;
}
.wrapper .box .bottom-element {
width: 100%;
background-color: lightblue;
}
.wrapper .box .bottom-element.one {
height: 100px;
}
.wrapper .box .bottom-element.two {
height: 100px;
}
.wrapper .box .bottom-element.three {
height: 100px;
}
<div class="wrapper">
<div class="box">
<div class="top-element one"></div>
<div class="bottom-element one"></div>
</div>
<div class="box">
<div class="top-element two"></div>
<div class="bottom-element two"></div>
</div>
<div class="box">
<div class="top-element three"></div>
<div class="bottom-element three"></div>
</div>
</div>
The issue is: It doesn't matter if you change the height of any of the top elements on any inner box, these remain vertically center-aligned according to the tallest element among all boxes, while the bottom ones remain at the bottom, and the space between top and bottom elements on each box is proportionally kept.
Now the question(s): is this correct css? and if so, I'm suspicious of align-items:"end" on each box to be the one to blame for this result, am I right? and if I'm wrong, why does this happen then?
Why didn't I use grid? well I'm in my flex phase... bear with me please.
You forget to define a vertical flex main direction for the elements with the CSS class .box.
Setting CSS property's flex-direction value to column for those elements fixes your problem.
SCSS
.box {
display: flex;
flex-direction: column;
...

Set two flex items side by side in a flexbox column

I have some elements I am displaying in a column direction within a display: flex container.
This places the containers within into a stacked view.
Say I have 5 stacked elements I need to make two of them display inline or flex direction row.
Without placing the two elements in question into another div that i can apply flex direction row to...
Is it possible to get these elements to sit side by side?
.flex-column {
display: flex;
flex-direction: column;
}
.flex-column .column-item:nth-of-type(4),
.flex-column .column-item:nth-of-type(5) {
width: calc(50% - 10px);
display: inline-block;
float: left;
}
.flex-column .column-item:nth-of-type(4) {
margin-right: 20px;
}
<div class="flex-column">
<div class="column-item">a</div>
<div class="column-item">b</div>
<div class="column-item">c</div>
<div class="column-item">d</div>
<div class="column-item">e</div>
</div>
I don't think it is possible once you have given your parent the flex-direction:column; property, alternatively you can enable flex-wrap:wrap and control the width of elements using the flex-basis property. This allows you to achieve the effect you want without altering your html structure.
.flex-column {
display: flex;
flex-wrap:wrap;
}
.flex-column .column-item {
flex-basis:100%;}
.flex-column .column-item:nth-of-type(4),
.flex-column .column-item:nth-of-type(5) {
flex-basis:50%;
}
<div class="flex-column">
<div class="column-item">a</div>
<div class="column-item">b</div>
<div class="column-item">c</div>
<div class="column-item">d</div>
<div class="column-item">e</div>
</div>
The layout is fairly simple with flexbox. You don't need flex-direction: column.
Just use flex-direction: row with flex-wrap: wrap.
Then make each element long enough to occupy a full row.
Reduce the flex-basis on the elements that are to share a row.
.flex-column {
display: flex;
flex-wrap: wrap;
}
.column-item {
flex: 1 0 61%; /* flex-grow, flex-shrink, flex-basis */
margin: 2px;
background-color: lightgreen;
}
.column-item:nth-of-type(4),
.column-item:nth-of-type(5) {
flex-basis: 40%;
}
<div class="flex-column">
<div class="column-item">a</div>
<div class="column-item">b</div>
<div class="column-item">c</div>
<div class="column-item">d</div>
<div class="column-item">e</div>
</div>
With flex-grow: 1 defined in the flex shorthand, there's no need to use calc().
Since flex-grow will consume free space on the row, flex-basis only needs to be large enough to enforce a wrap. In this case, with flex-basis: 61%, there's plenty of space for the margins, but never enough space for a second item.
There's an even simpler and more efficient solution using CSS Grid:
.flex-column {
display: grid;
grid-template-columns: 1fr 1fr;
grid-gap: 5px;
}
.column-item:nth-of-type(-n + 3) {
grid-column: span 2;
}
.column-item {
background-color: lightgreen;
}
<div class="flex-column">
<div class="column-item">a</div>
<div class="column-item">b</div>
<div class="column-item">c</div>
<div class="column-item">d</div>
<div class="column-item">e</div>
</div>
.flex-column {
display: flex;
flex-wrap:wrap;
}
.column-item {
}
<div class="flex-column">
<div class="column-item">a</div>
<div class="column-item">b</div>
<div class="column-item">c</div>
<div class="column-item">d</div>
<div class="column-item">e</div>
</div>

place two divs per row

so I have X divs and I want to put 2 divs in one row next to each other. If the screen size width is below n px there should be 1 div per row.
Currently I have this
#container {
display: flex;
}
.box {
width: 50px;
background: red;
}
#media(max-width: 300px) {
#container {
display: block;
}
}
<div id="container">
<div class="box"> 1 </div>
<div class="box"> 2</div>
<div class="box"> 3 </div>
<div class="box"> 4 </div>
</div>
How can I limit the flex box to two divs per row?
Add 50% width on .box and flex-wrap:wrap on the container
Additionally, what you did by changing display: flex to block was not required. Just change the .box elements width to 100%
#container {
display: flex;
flex-wrap: wrap;
}
.box {
width: 50%;
background: red;
}
#media(max-width: 300px) {
.box {
width: 100%;
}
}
<div id="container">
<div class="box"> 1 </div>
<div class="box"> 2</div>
<div class="box"> 3 </div>
<div class="box"> 4 </div>
</div>
Just add a property in your container class like
.container {
display: flex;
flex-wrap: wrap;
}
And in box class just specify the width of your box as 50% like
.box {
width: 50%;
background: red;
}
That should do the trick.
Flex will do a trick for you. flex-wrap: wrap for #container will make children wrap when necessary. .box with 50% and after breakpoint 100%.`
According to MDN:
The CSS flex-wrap property specifies whether flex items are forced into a single line or can be wrapped onto multiple lines. If wrapping is allowed, this property also enables you to control the direction in which lines are stacked.
If you are new to flexbox I recommend this guide.
Snippet
#container {
display: flex;
flex-wrap: wrap;
}
.box {
width: 50%;
background: red;
}
#media(max-width: 300px) {
.box {
width: 100%;
}
}
<div id="container">
<div class="box"> 1 </div>
<div class="box"> 2 </div>
<div class="box"> 3 </div>
<div class="box"> 4 </div>
</div>

Forcing flexbox element to float right

I'm currently working on responsiveness on my website and I hit the wall. On smaller resolutions I changed the flex-direction to column from row, changed the ordering of flex elements, changed the main textbox width to 100% and sideboxes to 50%.
Code looks like this:
<section class="about" id="ABOUT">
<div class="about-sidebox l">
</div>
<div class="about-mainbox">
</div>
<div class="about-sidebox r">
</div>
</section>
As you can see the sideboxes are not within the container. Putting them in container helps but completely ruins my previous layout.
CSS for wanted resolution is:
.about {
flex-direction: column;
}
.about-mainbox {
order: 1;
}
.about-sidebox {
order: 2;
width: 50%;
flex-wrap: wrap;
}
Effect is like this:
As you can see I want the sideboxes to be next to each other. Any solution I can't think of without adding additional container?
I hope I've understood you correctly. You could remove the flex-direction property from .about
Add flex-wrap. Then just give .about-mainbox a width of 100%
.about {
display: flex;
flex-wrap: wrap;
}
.about-mainbox {
order: 1;
width: 100%;
}
.about-sidebox {
order: 2;
width: 50%;
}
<section class="about" id="ABOUT">
<div class="about-sidebox l">demo left
</div>
<div class="about-mainbox">demo
</div>
<div class="about-sidebox r">demo right
</div>
</section>
The simplest possible is to do this;
Set the about to flex-wrap: wrap so its flex items can wrap, skip flex-direction so it uses its default row
Set the mainbox to order: -1 (default is 0), which will position it before the sidebox's, and flex-basis: 100%, which will make it take full width and by doing that, it pushes the sidebox's to a new line
Give the sidebox's flex-basis: 50% to be equally wide, and min-width: 0; so they stay side-by-side (if you wan't them to wrap and stack vertical when their content force's them to, drop this, or control it with a set width, i.e. min-width: 150px;)
I also recommend you use Flexbox's own properties, i.e. in this case flex-basis instead of width
.about {
display: flex;
flex-wrap: wrap;
}
.about-mainbox {
flex-basis: 100%;
order: -1;
}
.about-sidebox {
flex-basis: 50%;
min-width: 0;
}
<section class="about" id="ABOUT">
<div class="about-sidebox l">Left
</div>
<div class="about-mainbox">Main
</div>
<div class="about-sidebox r">Right
</div>
</section>

How to shrink flex items height to fit container heights

I am trying to display a layout below in flex .
I have divs of equal width and height. I want to achieve the layout out below. By placing one item on the left and the remaining four fit on the right container and maintaining the same container height in the process . Thats the one on the left increase to fill the left height and width and the other right size of the container is shared among the four items.
.trades {
display: flex;
flex: 1;
}
.trade-panel {
flex: 1;
}
.layout-5-2 {
-ms-flex-direction: row;
flex-direction: row;
justify-content: space-between;
display: flex;
}
.layout-container-5-2-1 {
-ms-flex-direction: column;
flex-direction: column;
height: 100%;
justify-content: space-between;
flex: 0 0 48%;
display: flex;
}
.layout-container-5-2-2 {
flex: 0 0 48%;
display: flex;
flex-direction: column;
}
<div class="trades">
<div class="layout-5-2">
<div class="layout-container-5-2-1">
<div class="trade-panel">item 1</div>
<div class=" trade-panel">item 2</div>
<div class="trade-panel">item 3</div>
<div class=" trade-panel">item 4</div>
</div>
<div class="layout-container-5-2-1">
<div class="trade-panel">vertical item.</div>
</div>
</div>
</div>
My layout displays close to what i was expecting.with four to in the container to the right and one item to the left. However, The trades container scroll vertically to accommodate the four trades height. The trades does not shrink to fit into the right container thats .layout-container 5-2-2. Please how do i shrink the four to fix in the container heights ? Any help would be appreciated.
Try this
body,
html {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
display: flex;
min-height: 100vh;
background: #2A3052;
}
.left {
flex: 1;
background: #9497A8;
margin: 10px;
}
.right {
flex: 1;
display: flex;
flex-direction: column;
}
.box {
flex: 1;
background: #9497A8;
margin: 10px;
}
<div class="container">
<div class="left"></div>
<div class="right">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
</div>