Stuck between flex-end and space-between and margin - html

In a flexbox, when I use justify-content:space-between the first and last items are exactly aligned to the bounds of flex container where space is divided between them. How can I align first item to the right where other items are also aligned to the right (not to entire the width)?
The sample code below is not good because when I use flex-end, I have to set margin for items and so the first one in each row is not sticky to the right.
#flexcontainer{
display: -webkit-flex;
display: flex;
flex-wrap:wrap;
-webkit-flex-direction: row;
flex-direction: row;
-webkit-justify-content: flex-end;
justify-content: flex-end;
background:#ff8800;
}
.flexitem{
display: -webkit-flex;
display: flex;
margin:20px;
width:24%;
background:#666666;
box-sizing:border-box;
height:50px;
}
<div id="flexcontainer">
<div class="flexitem"></div>
<div class="flexitem"></div>
<div class="flexitem"></div>
<div class="flexitem"></div>
<div class="flexitem"></div>
<div class="flexitem"></div>
</div>
and this is not also good because items are not aligned to the right (but entire the width):
#flexcontainer{
display: -webkit-flex;
display: flex;
flex-wrap:wrap;
-webkit-flex-direction: row;
flex-direction: row;
-webkit-justify-content: space-between;
justify-content: space-between;
background:#ff8800;
}
.flexitem{
display: -webkit-flex;
display: flex;
margin:0;
width:24%;
background:#888888;
box-sizing:border-box;
height:50px;
}
<div id="flexcontainer">
<div class="flexitem"></div>
<div class="flexitem"></div>
<div class="flexitem"></div>
</div>
My desired output in image (first one sticks to the right with no margin-right and the 4th one sticks to the left if 4 element exist and others align to the right if more than 4):

AFAIK the best you can achieve using a flexbox to achieve your desired output can be done manipulating the flex-basis and margin of the flexitems using this:
margin: 20px;
display: flex;
flex: 0 1 calc(25% - 40px);
The flex-basis of calc(25% - 40px) in the flex style divides the width into four adjusting for margin also.
Note I have set flex-grow disabled.
flex-end finishes it up.
Let me know your feedback. Thanks!
#flexcontainer {
display: flex;
flex-wrap: wrap;
flex-direction: row;
justify-content: flex-end;
background: #ff8800;
}
.flexitem {
margin: 20px;
display: flex;
flex: 0 1 calc(25% - 40px);
background: #666666;
box-sizing: border-box;
height: 50px;
}
<div id="flexcontainer">
<div class="flexitem"></div>
<div class="flexitem"></div>
<div class="flexitem"></div>
<div class="flexitem"></div>
<div class="flexitem"></div>
<div class="flexitem"></div>
</div>
EDIT:
So I did some more adjustments to the margin calculations:
Change the flex-basis by reducing 10px more to adjust for removing the 20px each at the left and right ends of a row:
flex: 0 1 calc(25% - 30px);
For the rightmost / leftmost boxes to sit to the right / left edge:
.flexitem:nth-child(4n) {
margin-right: 0;
}
.flexitem:nth-child(4n + 1) {
margin-left: 0;
}
.flexitem:last-child {
margin-right: 0;
}
Give me your feedback on this. Thanks!
#flexcontainer {
display: flex;
flex-wrap: wrap;
flex-direction: row;
justify-content: flex-end;
background: #ff8800;
}
.flexitem {
margin: 20px;
display: flex;
flex: 0 1 calc(25% - 30px);
background: #666666;
box-sizing: border-box;
height: 50px;
}
.flexitem:nth-child(4n) {
margin-right: 0;
}
.flexitem:nth-child(4n + 1) {
margin-left: 0;
}
.flexitem:last-child {
margin-right: 0;
}
<div id="flexcontainer">
<div class="flexitem"></div>
<div class="flexitem"></div>
<div class="flexitem"></div>
<div class="flexitem"></div>
<div class="flexitem"></div>
<div class="flexitem"></div>
</div>

I guess you could simply remove the right margin in your first example, is this how you wanted it to look?
#flexcontainer {
display: flex;
flex-wrap: wrap;
flex-direction: row;
justify-content: flex-end;
background: #ff8800;
}
.flexitem {
margin: 20px;
margin-right: 0;
width: 24%;
background: #666666;
box-sizing: border-box;
height: 50px;
}
<div id="flexcontainer">
<div class="flexitem"></div>
<div class="flexitem"></div>
<div class="flexitem"></div>
<div class="flexitem"></div>
<div class="flexitem"></div>
<div class="flexitem"></div>
</div>

Related

Shrink flexbox to the size of its children

I need to arrange a bunch of blocks of fixed size into a grid. I am using flex-wrap: wrap to get as many in each row as will fit. But, I would like this whole wrapped column to be centered in the page. Ideally, I would like it to look something like this:
But, in the snippet I have below, the green flexbox fills to fit any space it can, so all the blue boxes are pushed all the way to the left. I don't want to set the flexbox to a fixed width because I want it to be able to flow to fit as many boxes in a row as possible, but I just don't want it to take up any more space beyond that.
Obviously, I could use justify-content: center to center the boxes within the container, but the incomplete row at the bottom gets out of alignment, which I don't want.
Is there any way to achieve the effect I am looking for with CSS?
I saw this question which suggested using display: inline-flex. That does seem to work when you are not wrapping, but as soon as you put on flex-wrap: wrap and add enough items to make it wrap, it jumps back to filling the full width.
.page {
width: 100%;
background-color: pink;
padding: 10px;
box-sizing: border-box;
display: flex;
flex-direction: column;
align-items: center;
}
.flex-column {
display: flex;
flex-direction: row;
flex-wrap: wrap;
background-color: green;
justify-content: flex-start;
gap: 10px;
}
.flex-child {
display: block;
width: 200px;
height: 100px;
background-color: blue;
}
.button {
display: inline-block;
padding: 20px;
background-color: red;
}
.
<div class='page'>
<div class="flex-column">
<div class="flex-child"></div>
<div class="flex-child"></div>
<div class="flex-child"></div>
<div class="flex-child"></div>
<div class="flex-child"></div>
<div class="flex-child"></div>
<div class="flex-child"></div>
<div class="flex-child"></div>
</div>
<div class="button">Load more</div>
</div>
Since the width is always the same, CSS grid can help you here:
.page {
background-color: pink;
display: grid;
grid-template-columns:repeat(auto-fit,200px); /* same width as child */
gap:10px; /* the same gap here */
justify-content:center; /* center everything */
}
.flex-column {
display: flex;
flex-direction: row;
flex-wrap: wrap;
background-color: green;
grid-column:1/-1; /* take all the columns */
gap: 10px;
}
.flex-child {
width: 200px;
height: 100px;
background-color: blue;
}
.button {
padding: 20px;
background-color: red;
grid-column:1/-1; /* take all the columns */
margin:auto; /* center the button */
}
<div class='page'>
<div class="flex-column">
<div class="flex-child"></div>
<div class="flex-child"></div>
<div class="flex-child"></div>
<div class="flex-child"></div>
<div class="flex-child"></div>
<div class="flex-child"></div>
<div class="flex-child"></div>
<div class="flex-child"></div>
</div>
<div class="button">Load more</div>
</div>
In mine it is working like this you can see:
.page {
width: 100%;
background-color: pink;
padding: 10px;
box-sizing: border-box;
display: flex;
flex-direction: column;
align-items: center;
}
.flex-column {
display: flex;
flex-direction: row;
flex-wrap: wrap;
background-color: green;
justify-content: flex-start;
gap: 10px;
display: flex;
padding: 20px;
}
.flex-child {
display: block;
width: 200px;
height: 100px;
background-color: blue;
flex: 0 1 auto;
}
.button {
display: inline-block;
padding: 20px;
background-color: red;
}
.
<div class='page'>
<div class="flex-column">
<div class="flex-child"></div>
<div class="flex-child"></div>
<div class="flex-child"></div>
<div class="flex-child"></div>
<div class="flex-child"></div>
<div class="flex-child"></div>
<div class="flex-child"></div>
<div class="flex-child"></div>
</div>
<div class="button">Load more</div>
</div>

CSS Flexbox: How to arrange three Items in a Row, but two of them below each other?

Assumed we have this simple CSS flexbox layout:
.flex-container {
display: flex;
justify-content: space-between;
align-items: center;
height: 100vh;
}
.flex-item:nth-child(1) {
order: 0;
}
.flex-item:nth-child(2) {
order: 1;
align-self: flex-start;
}
.flex-item:nth-child(3) {
order: 1;
align-self: flex-end;
}
.flex-item {
width: 50px;
height: 50px;
background:red;
}
<div class="flex-container">
<div class="flex-item"></div>
<div class="flex-item"></div>
<div class="flex-item"></div>
</div>
Description of the issue:
Unfortunately flex-item 2 and 3 are not located at the right edge below each other, although they are both set to order: 1.
Question:
How can I arrange flex-item 2 to be at the upper right edge, while flex-item 3 is located at the lower right edge (item 1 should remain vertically centered at left edge)?
I did not yet figure out on how to arrange all three items in a row, but the latter two items below each other within this row.
I guess you are trying to do that.
* {
padding: 0;
margin: 0;
}
.flex-container {
display: flex;
justify-content: space-between;
align-items: center;
height: 100vh;
}
.flex-container-col {
display: flex;
flex-direction:column;
justify-content: space-between;
align-items: center;
height: 100vh;
}
.flex-item:nth-child(1) {
order: 0;
align-self: flex-center;
}
.box {
width: 50px;
height: 50px;
background:red;
}
<div class="flex-container">
<div class="flex-item box"></div>
<div class="flex-item flex-container-col">
<div class="box"></div>
<div class="box"></div>
</div>
</div>
If you want to both item 2 and 3 top of the right edge together, you can delete justify-content in flex-container-col so they will unite at the top. Hope works.
If you want a block to be at up right, one at the center and other at the bottom right, then you can use this snippet. The flex item 1 should be at flex-start, the flex item 3 should be at the flex end and the flex item 2 should be where it is.
* {
padding: 0;
margin: 0;
}
.flex-container {
display: flex;
justify-content: space-between;
align-items: center;
height: 100vh;
}
.flex-item:nth-child(1) {
order: 0;
align-self: flex-start;
}
.flex-item:nth-child(2) {
order: 1;
}
.flex-item:nth-child(3) {
order: 1;
align-self: flex-end;
}
.flex-item {
width: 50px;
height: 50px;
background:red;
}
<div class="flex-container">
<div class="flex-item"></div>
<div class="flex-item"></div>
<div class="flex-item"></div>
</div>

How to wrap last row of flexbox with "space-around"? [duplicate]

This question already has answers here:
Targeting flex items on the last or specific row
(10 answers)
Closed 3 years ago.
I am trying to create a Bootstrap-like grid of cards using CSS flex properties. I have 10 cards (4 each row). However, when using justify-content: space-around (this is what I need), the last row is not aligning with the others (naturally). What is the workaround?
.card-gallery {
width: 100%;
height: auto;
display: flex;
justify-content: space-around;
flex-wrap: wrap;
align-items: center;
flex-direction: row;
}
.card-box {
width: 270px;
height: 400px;
background: red;
}
<div class="container">
<div class="card-gallery">
<div class="card-box"></div>
<div class="card-box"></div>
<div class="card-box"></div>
<div class="card-box"></div>
<div class="card-box"></div>
<div class="card-box"></div>
<div class="card-box"></div>
</div>
</div>
You could try CSS :last-child as in the example below to use different style in your last div.
.flexbox {
display: flex;
flex-flow: column;
}
.flex-child {
background: red;
align-content: center;
align-self: center;
}
.flex-child:last-child {
align-content: space-around;
align-self: flex-start;
}
<div class="flexbox">
<div class="flex-child">
one
</div>
<div class="flex-child">
two
</div>
<div class="flex-child">
three
</div>
</div>
By the way space-between and applying relative width to your card div works better.
.card-gallery {
width: calc(100% -2rem);
height: auto;
display: flex;
justify-content: space-between;
flex-wrap: wrap;
flex-direction: row;
padding: 1rem;
}
.card-box {
width: 45%;
height: 40px;
background: #ff0;
align-self: center;
}
div.card-box:last-child {
align-self: flex-start;
}
<div class="container">
<div class="card-gallery">
<div class="card-box">1</div>
<div class="card-box">2</div>
<div class="card-box">3</div>
<div class="card-box">4</div>
<div class="card-box">5</div>
<div class="card-box">6</div>
<div class="card-box">7</div>
</div>
</div>
You can't achieve this easily with flexbox.
Instead, set .card-gallery to display:grid to make sure the cards always line up in a grid formation when multiple rows exist. Then give it this style rule:
grid-template-columns: repeat(auto-fill, 120px)
The auto-fill keyword will make sure the items will wrap when the viewport shrinks:
.container{max-width:479px;background:lightblue}
.card-gallery {
width: 100%;
height: auto;
display: grid;
grid-template-columns: repeat(auto-fill, 120px);
justify-content: space-around;
}
.card-box {
height: 100px;
background: #fff;
margin-bottom:30px;
border:solid 2px dodgerblue
}
<div class="container">
<div class="card-gallery">
<div class="card-box">cb</div>
<div class="card-box">cb</div>
<div class="card-box">cb</div>
<div class="card-box">cb</div>
<div class="card-box">cb</div>
<div class="card-box">cb</div>
<div class="card-box">cb</div>
</div>
</div>

How to align the flex items in three different ways?

So, I want to align items inside flex-box like in the above picture.
I have html as follows:
<div class="flex-row">
<div class="flex-item">
<img src="/default.png">
</div>
<div class="flex-item">
<img src="/default.png">
</div>
<div class="flex-item">
<img src="/default.png">
</div>
</div>
css as
.flex-row {
min-height: 400px;
display: flex;
align-items: flex-start;
}
.flex-item:nth-child(2) {
align-items: center;
}
.flex-item:last-child {
align-items: flex-end;
}
Use align-self not align-items
.flex-row {
min-height: 300px;
display: flex;
width: 90%;
margin: 1em auto;
border: 1px solid red;
justify-content: space-between;
}
.flex-item {
height: 50px;
background: lightblue;
width: 100px;
}
.flex-item:nth-child(2) {
align-self: center;
}
.flex-item:last-child {
align-self: flex-end;
}
<div class="container flex-row">
<div class="flex-item"></div>
<div class="flex-item"></div>
<div class="flex-item"></div>
</div>
Like so?
You need flex-wrap: wrap; In order to wrap the items need to be wide enough (100%). Since 100% flex item is always justified to the full width, you need text-align, not align-items which is the wrong property in the first place.
align-items is the alignment at the cross axis, not the main axis which would be justify-content
.flex-row {
min-height: 400px;
display: flex;
align-items: flex-start;
flex-wrap: wrap;
}
.flex-item {
flex-basis: 100%;
}
.flex-item:nth-child(2) {
text-align: center;
}
.flex-item:last-child {
text-align: right;
}
<div class="flex-row">
<div class="flex-item">
<img src="/default.png" width="100" height="50">
</div>
<div class="flex-item">
<img src="/default.png" width="100" height="50">
</div>
<div class="flex-item">
<img src="/default.png" width="100" height="50">
</div>
</div>
Look at this code
display:flex;
flex-direction: row;
justify-content: flex-start;
align-items: centre;
With flex-direction you specify le principal alignment (horizontal with row , vertical with column). Depending on what you choose here the following properties will have a different effect.
Then with justify-content you specify how your items inside your elements should align on the principal axis you just defined (vertical or horizontal).
In this case flex-start means at the beginning of my axis.
And with align-items you specify the alignment for the secondary axe.The vertical one because we choose flex-direction: row; and not flex-direction: column;. So in the vertical axis items will align at centre
And don't forget to take look at the available properties like space-between or flex-end
NOTE!
to set height to column change the px here:flex: 0 1 50px; or remove it!
Using margin-right/left:auto as:
.flex-row {
min-height: 400px;
display: flex;
flex-wrap: wrap;
flex-direction: column;
}
.flex-item {
flex: 0 1 50px;
}
.flex-item:nth-child(2) {
margin-right: auto;
margin-left: auto;
}
.flex-item:last-child {
margin-left: auto;
}
<div class="flex-row">
<div class="flex-item">
<img src="/default.png">
</div>
<div class="flex-item">
<img src="/default.png">
</div>
<div class="flex-item">
<img src="/default.png">
</div>
</div>
2. using align-self
.flex-row {
min-height: 400px;
display: flex;
flex-wrap: wrap;
flex-direction: column;
}
.flex-item {
flex: 0 1 50px;
align-self: flex-start;
}
.flex-item:nth-child(2) {
align-self: center;
}
.flex-item:last-child {
align-self: flex-end;
}
<div class="flex-row">
<div class="flex-item">
<img src="/default.png">
</div>
<div class="flex-item">
<img src="/default.png">
</div>
<div class="flex-item">
<img src="/default.png">
</div>
</div>

Can you make flexbox background height the same?

I am using flexbox display and it is working fine. Except when I happen to use a background color on one of the divs, the color does not cover the entire height of the div. It ends up looking like this --
Of course what I'd like is for the background color to extend to the same height as the div to the right. Is this even possible with flexbox?
.row {
display: flex;
align-items: center;
}
.left {
flex: 1 0 auto;
background-color: wheat;
}
.right {
flex: 1 0 auto;
}
<div class="row">
<div class="left">Some text</div>
<div class="right">
<input type="text" style="height:40px" />
</div>
</div>
The problem is that you use
align-items: center;
The default value does what you want:
align-items: stretch;
.row {
display: flex;
}
.left {
flex: 1 0 auto;
background-color: wheat;
}
.right {
flex: 1 0 auto;
}
<div class="row">
<div class="left">
Some text
</div>
<div class="right">
<input type="text" style="height:40px" />
</div>
</div>
But then you will need to center the contents vertically. You can do it with more flexbox. Some examples:
Row layout and align-items:
.left {
display: flex; /* More flexbox */
align-items: center; /* Center in the cross (vertical) axis */
}
.row {
display: flex;
}
.left {
flex: 1 0 auto;
background-color: wheat;
display: flex;
align-items: center;
}
.right {
flex: 1 0 auto;
}
<div class="row">
<div class="left">
Some text
</div>
<div class="right">
<input type="text" style="height:40px" />
</div>
</div>
Column layout and justify-content:
.left {
display: flex; /* More flexbox */
flex-direction: column; /* Column layout */
justify-content: center; /* Center in the main (vertical) axis */
}
.row {
display: flex;
}
.left {
flex: 1 0 auto;
background-color: wheat;
display: flex;
flex-direction: column;
justify-content: center;
}
.right {
flex: 1 0 auto;
}
<div class="row">
<div class="left">
Some text
</div>
<div class="right">
<input type="text" style="height:40px" />
</div>
</div>
Inserting pseudo-elements with auto margins:
.left {
display: flex; /* More flexbox */
flex-direction: column; /* Column layout */
}
.left::before, .left::after {
content: ''; /* Generate pseudo-elements */
margin: auto; /* Push contents */
}
.row {
display: flex;
}
.left {
flex: 1 0 auto;
background-color: wheat;
display: flex;
flex-direction: column;
}
.left::before, .left::after {
content: '';
margin: auto;
}
.right {
flex: 1 0 auto;
}
<div class="row">
<div class="left">
Some text
</div>
<div class="right">
<input type="text" style="height:40px" />
</div>
</div>