Center last row element using Flexbox - css

When I resize the window to smaller resolution I would like the last element to be centered. I know that I can achive that by setting parent's justify-content parameter to space-around or center, but it has to be set to: space-between.
ul {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
background: rgba(255, 0, 0, 0.3);
padding: 0;
}
li {
list-style-type: none;
display: inline-block;
min-width: 100px;
height: 100px;
background: red;
margin: 10px;
}
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
http://jsfiddle.net/k7fzdn80/

use auto margin
margin: 10px auto;
is this what you expect?
Solution

Unfortunately, it is not possible with flexbox for your problem. But I have a CSS hack to solve the issue. Target the last element within the media-query. I have used custom breakpoints below.
ul {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
background: rgba(255, 0, 0, 0.3);
padding: 0;
}
li {
list-style-type: none;
display: inline-block;
min-width: 100px;
height: 100px;
background: red;
margin: 10px;
}
#media (min-width: 376px) and (max-width: 494px) {
li:last-child {
margin: 10px auto;
}
}
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>

It's not possible. space-between definition says
If [...] there is only a single flex item on the line, this value
is identical to 'flex-start'.
The only way would be doing the alignment manually, e.g. with media queries and auto margins. But then the layout won't be flexible at all.

I have another proposal. Using the calc() to calculate the width of the flex item. And so the last element could be centered.
.container {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
width: 100%;
row-gap: 10px;
}
.column {
display: flex;
width: calc(100% / 4);
overflow: hidden;
text-align: center;
background: green;
}
.inside-column {
background: white;
width: 100%;
display: block;
margin: 15px;
border: 5px solid red;
}
.wrap {
max-width: 350px;
background: #CCC;
}
<div class="container">
<div class="column">
<a href="#" class="inside-column">
1
<br>Content Content Content
</a>
</div>
<div class="column">
<div class="inside-column">
2
<br>Content Content Content
</div>
</div>
<div class="column">
<div class="inside-column">
3
</div>
</div>
<div class="column">
<div class="inside-column">
4
<br>Content Content Content
</div>
</div>
<div class="column">
<div class="inside-column">
5
<br>Content Content Content
</div>
</div>
<div class="column">
<div class="inside-column">
6
</div>
</div>
<div class="column">
<div class="inside-column">
7
</div>
</div>
<div class="column">
<div class="inside-column">
8
</div>
</div>
<div class="column">
<div class="inside-column">
9
</div>
</div>
</div>
<br>
<br>
<div class="wrap">
<div class="container">
<div class="column">
<a href="#" class="inside-column">
1
<br>Content Content Content
</a>
</div>
<div class="column">
<div class="inside-column">
2
<br>Content Content Content
</div>
</div>
<div class="column">
<div class="inside-column">
3
</div>
</div>
<div class="column">
<div class="inside-column">
4
<br>Content Content Content
</div>
</div>
<div class="column">
<div class="inside-column">
5
</div>
</div>
<div class="column">
<div class="inside-column">
6
</div>
</div>
<div class="column">
<div class="inside-column">
7
</div>
</div>
<div class="column">
<div class="inside-column">
8
</div>
</div>
<div class="column">
<div class="inside-column">
9
</div>
</div>
</div>
</div>

Related

Flexbox didnt vertically centered [duplicate]

This question already has answers here:
Flexbox: center horizontally and vertically
(14 answers)
Closed 2 years ago.
I am trying to make this as an example to learn:
https://i.ibb.co/m4qJmQz/image.png
my code doesn't center the boxes.How can I make it better?
I want to learn how to
**center vertically the columns' content
**add space between gray ">" and texts - apply space-around or space-between 's space amount, so apply automatic space; not padding or margin
my html file:
http://elementor.help.helvatica.com/flexbox.html
code:
<html>
<head>
<title>The Flexbox Example - Murat Deniz</title>
<meta content="">
<style></style>
</head>
<body>
<style>
.container {
display: flex;
justify-content: space-around;
align-items: center;
height: 100%;
}
.icon {
background-color: gray;
color: saddlebrown;
width: 100%;
text-align: center;
height: fit-content;
}
.sub-container {
border-color: gainsboro;
border-radius: 5px;
border-style: solid;
box-shadow: 0px 0px 30px 0px gainsboro;
display: flex;
justify-content: space-around;
width: 100%;
height: 100%;
}
li {
flex-direction: row;
display: flex;
}
ul {
padding-inline-start: unset;
}
.inline {
flex-direction: row;
display: flex;
}
.inline li:nth-child(3) {
align-content: flex-end;
color: red;
}
.main-container {
/** display: flex;
justify-content: space-around;
align-items: center; **/
height: 50%;
}
.section {
height: 100%;
}
</style>
<div class="main-container">
<div class="container">
<div class="section">
<p>Artboard</p>
<div class="sub-container">
<ul>
<li>
<div class="icon">
>
</div>
<div class="text">
video
</div>
</li>
<li>
<div class="icon">
</div>
<div class="text">
photo
</div>
</li>
<li>
<div class="icon">
>
</div>
<div class="text">
video
</div>
</li>
<li>
<div class="icon">
>
</div>
<div class="text">
video
</div>
</li>
</ul>
</div>
</div>
<div class="section">
<p>Artboard Copy</p>
<div class="sub-container">
<ul class="inline">
<li>
<div class="icon">
>
</div>
<div class="text">
video
</div>
</li>
<li>
<div class="icon">
</div>
<div class="text">
photo
</div>
</li>
<li>
<div class="icon">
>
</div>
<div class="text">
video
</div>
</li>
<li>
<div class="icon">
>
</div>
<div class="text">
video
</div>
</li>
</ul>
</div>
</div>
</div>
</div>
</body>
</html>
I think you can't put in-between space without using margin or padding as you are using 100% width. When you talk about automatic space you mean to use relative units of measure like .em or .vw

Why would the overflow property on a flex item affect its flex-shrink behavior? [duplicate]

This question already has answers here:
Why don't flex items shrink past content size?
(5 answers)
Why is a flex item limited to parent size?
(1 answer)
Closed 2 years ago.
I am creating a layout that contains three parts: sidebar (left), page (center), and summary (right). The left will remain fixed at the width of its inner content when the viewport width decreases, which is the expected behavior.
However, once I add overflow-y: auto to the left container, it loses respect for its inner content width, and completely shrinks along with the viewport width.
How does overflow-y: auto affect an item's flex-shrink behavior? How do I apply an overflow-y while allowing it to continue respecting its inner content width?
.root {
display: flex;
}
.root .sidebar {
border: 8px solid red;
flex: 2;
background: #f3f3f5;
height: 100vh;
display: flex;
justify-content: flex-end;
padding-top: 80px;
position: sticky;
top: 0;
/*
enable this and shrink the viewport
notice how the sidebar shrinks completely
and no longer respects the inner content's fixed width
*/
/*overflow-y: auto;*/
}
.root .page {
border: 8px solid green;
flex: 8;
max-width: 810px;
padding: 80px 80px 160px 80px;
}
#media only screen and (max-width: 1024px) {
.root .page {
padding-right: 40px;
padding-left: 40px;
}
}
.root .summary {
border: 8px solid blue;
flex: 2;
padding-top: 160px;
position: sticky;
top: 0;
align-self: flex-start;
}
.root .actions {
border: 8px solid orange;
position: fixed;
bottom: 0;
padding: 10px;
width: 100%;
background: white;
display: flex;
justify-content: center;
align-items: center;
}
.root .actions .inner {
display: flex;
justify-content: space-between;
align-items: center;
flex-basis: 650px;
}
.root .stepper {
border: 4px solid #333;
flex-basis: 320px;
}
.root .stepper .step {
display: flex;
align-items: center;
margin: 0px 70px 40px 40px;
white-space: nowrap;
}
.root .stepper .step .circle {
background: #ffc2d4;
border-radius: 50%;
width: 28px;
height: 28px;
display: flex;
justify-content: center;
align-items: center;
margin-right: 10px;
}
.root .form-stuff {
margin-bottom: 80px;
}
.root .card {
border: 4px solid #333;
align-self: flex-start;
border-radius: 8px;
padding: 10px;
max-width: 280px;
min-width: 180px;
white-space: nowrap;
}
.root .card .title {
margin: 20px 0;
}
.root .card .subtitle {
margin: 20px 0;
font-size: 14px;
}
.root .button {
background: #ffc2d4;
padding: 10px 20px;
}
* {
box-sizing: border-box;
}
<div class="root">
<div class="sidebar">
<div class="stepper">
<div class="step">
<div class="circle">
1
</div>
<div class="title">Step 1</div>
</div>
<div class="step">
<div class="circle">
2
</div>
<div class="title">Step 2</div>
</div>
<div class="step">
<div class="circle">
3
</div>
<div class="title">Step 3</div>
</div>
<div class="step">
<div class="circle">
4
</div>
<div class="title">Step 4</div>
</div><div class="step">
<div class="circle">
4
</div>
<div class="title">Step 4</div>
</div><div class="step">
<div class="circle">
4
</div>
<div class="title">Step 4</div>
</div><div class="step">
<div class="circle">
4
</div>
<div class="title">Step 4</div>
</div><div class="step">
<div class="circle">
4
</div>
<div class="title">Step 4</div>
</div><div class="step">
<div class="circle">
4
</div>
<div class="title">Step 4</div>
</div><div class="step">
<div class="circle">
4
</div>
<div class="title">Step 4</div>
</div><div class="step">
<div class="circle">
4
</div>
<div class="title">Step 4</div>
</div><div class="step">
<div class="circle">
4
</div>
<div class="title">Step 4</div>
</div><div class="step">
<div class="circle">
4
</div>
<div class="title">Step 4</div>
</div><div class="step">
<div class="circle">
4
</div>
<div class="title">Step 4</div>
</div><div class="step">
<div class="circle">
4
</div>
<div class="title">Step 4</div>
</div><div class="step">
<div class="circle">
4
</div>
<div class="title">Step 4</div>
</div><div class="step">
<div class="circle">
4
</div>
<div class="title">Step 4</div>
</div><div class="step">
<div class="circle">
4
</div>
<div class="title">Step 4</div>
</div><div class="step">
<div class="circle">
4
</div>
<div class="title">Step 4</div>
</div><div class="step">
<div class="circle">
4
</div>
<div class="title">Step 4</div>
</div>
</div>
</div>
<div class="page">
<div class="form">
<div class="form-stuff">
form stuff
</div>
<div class="form-stuff">
form stuff
</div>
<div class="form-stuff">
form stuff
</div>
<div class="form-stuff">
form stuff
</div>
<div class="form-stuff">
form stuff
</div>
<div class="form-stuff">
form stuff
</div>
<div class="form-stuff">
form stuff
</div>
<div class="form-stuff">
form stuff
</div>
<div class="form-stuff">
form stuff
</div>
<div class="form-stuff">
form stuff
</div>
<div class="form-stuff">
form stuff
</div>
<div class="form-stuff">
form stuff
</div>
</div>
</div>
<div class="summary">
<div class="card">
<div class="title">Summary</div>
<div class="subtitle">foo</div>
<div class="subtitle">foo</div>
<div class="subtitle">foo</div>
<div class="subtitle">foo</div>
<div class="subtitle">foo</div>
</div>
</div>
<div class="actions">
<div class="inner">
<div class="button">Back</div>
<div class="button">Next</div>
</div>
</div>
</div>

How to make div expand with content using flex?

I have this HTML and CSS:
.container {
width: 100%;
}
.group {
display: flex;
justify-content: space-between;
min-width: 214px;
background: #eee;
}
.abbr {
/* some styling */
}
.name {
/* some styling */
}
<div class="container">
<div class="group">
<div class="abbr">
<p>MS</p>
</div>
<div>
<p class="name">Mark Smith</p>
</div>
</div>
</div>
Now, if I use just min-width, the whole div stretches as the entire width of the container. If I just use width, it won't expand if the name is longer than Mark Smith (rather it will go to the next line).
This is what I wanted to achieve:
How do I achieve this in flexbox?
What you're looking for is to apply width: fit-content to .group.
Then you can adjust the offset between the abbreviation and name with min-width on the .abbr.
This can be seen in the following:
.group {
display: flex;
width: fit-content;
background: #eee;
margin: 10px 0;
}
.group > div {
margin: 0 10px;
}
.abbr {
min-width: 50px;
}
<div class="container">
<div class="group">
<div class="abbr">
<p>MS</p>
</div>
<div>
<p class="name">Mark Smith</p>
</div>
</div>
<div class="group">
<div class="abbr">
<p>MS</p>
</div>
<div>
<p class="name">A Really Really Long Name</p>
</div>
</div>
</div>
I use inline-block on .container so that it won't take up the whole line.
.container {
display: inline-block;
}
.group {
display: flex;
background: #eee;
}
.abbr {
padding: 0 7px;
}
.name {
padding: 0 7px;
}
<div class="container">
<div class="group">
<div class="abbr">
<p>MS</p>
</div>
<div>
<p class="name">Mark Smith</p>
</div>
</div>
</div><br/><br/>
<div class="container">
<div class="group">
<div class="abbr">
<p>MR</p>
</div>
<div>
<p class="name">Loooooooooooooooong Name</p>
</div>
</div>
</div>
Another solution is to use a third element that consume all the remaining space and set the background color on the text content only:
.container {
margin: 0 0 5px 0;
}
.group {
display: flex;
}
.abbr {
padding: 0 7px;
background: #eee;
}
.name {
padding: 0 7px;
background: #eee;
flex: 0 0 auto;
}
.blank-space{
flex: 1 1 auto;
}
<div class="container">
<div class="group">
<div class="abbr">
<p>MS</p>
</div>
<div class="name">
<p>Mark Smith</p>
</div>
<div class="blank-space"></div>
</div>
</div>
<div class="container">
<div class="group">
<div class="abbr">
<p>MR</p>
</div>
<div class="name">
<p>Loooooooooooooooong Name</p>
</div>
<div class="blank-space"></div>
</div>
</div>

How to style space between items?

Is it possible to style spaces between items in flex?
Case Scenario:
I have a kind of table/grid
I don't want items to grow (flex-grow: 0)
I don't want space-between items
If there is not enough remaining space, next item falls to next line
Example:
Fiddle:
https://jsfiddle.net/t245o0vr/21/
Desired effect:
I would like to add a border-bottom in those spacing in the end. You think it's possible? Any ideas?
.container {
display: flex;
flex-wrap: wrap;
border: 1px solid #ccc;
border-bottom: 0;
max-width: 470px; /* for the sake of example */
}
.item {
display: inline-flex;
padding: 10px;
border-bottom: 1px solid #ccc;
}
<div class="container">
<div class="item">
itemA
</div>
<div class="item">
itemBitemB
</div>
<div class="item">
itemCCCC
</div>
<div class="item">
itemA
</div>
<div class="item">
itemBitemB
</div>
<div class="item">
itemCCCC
</div>
<div class="item">
itemA
</div>
<div class="item">
itemBitemB
</div>
<div class="item">
itemCCCC
</div>
</div>
This solutions is not based in flex (I also would like to know how to solve it with any flex'ish rule) but it works.
Instead of adding border to elements add and absolute positioned &:after pseudo-element on every item and hide the overflow in parent
.container {
display: flex;
flex-wrap: wrap;
border: 1px solid #ccc;
border-bottom: 0;
max-width: 470px; /* for the sake of example */
overflow: hidden; /* <------- new */
}
.item {
display: inline-flex;
padding: 10px;
/* border-bottom: 1px solid #ccc; <---- removed */
position: relative; /* <------- new */
}
.item:after {
content: "";
position: absolute;
left: 0;
bottom: 0;
width: 100vw; /* Bigger enough :P */
border-bottom: 1px solid #ccc;
}
<div class="container">
<div class="item">
itemA
</div>
<div class="item">
itemBitemB
</div>
<div class="item">
itemCCCC
</div>
<div class="item">
itemA
</div>
<div class="item">
itemBitemB
</div>
<div class="item">
itemCCCC
</div>
<div class="item">
itemA
</div>
<div class="item">
itemBitemB
</div>
<div class="item">
itemCCCC
</div>
</div>
I would consider another way using gradient. The trick is to have a gradient that will get repeated each line to cover each new line that will appear. You simply need to know the height of your line which is based on the line-height and padding
.container {
display: flex;
flex-wrap: wrap;
border: 1px solid #ccc;
line-height:1.2em;
background:
repeating-linear-gradient(to bottom,
transparent 0,transparent calc(1.2em + 20px),
#ccc calc(1.2em + 20px),#ccc calc(1.2em + 21px));
max-width: 470px; /* for the sake of example */
}
.item {
display: inline-flex;
padding: 10px;
}
<div class="container">
<div class="item">
itemA
</div>
<div class="item">
itemBitemB
</div>
<div class="item">
itemCCCC
</div>
<div class="item">
itemA
</div>
<div class="item">
itemBitemB
</div>
<div class="item">
itemCCCC
</div>
<div class="item">
itemA
</div>
<div class="item">
itemBitemB
</div>
<div class="item">
itemCCCC
</div>
</div>

Flex Row space between wrapped items

What is the most dynamic way of having any amount of rows with any amount of items with a set margin between all the items? Right now the only thing that works for me is to wrap each item in a wrapper set the flex basis to the wrapper and the margin to the child. The issues with this is I loose the ability to have each row the same height of the tallest content in the row.
Case 1: Only margin bottom
https://jsfiddle.net/6oaney4e/6/
This works well because the content keep the height of the tallest item on each row
html
<div class="wrapper">
<div class="item">
text
</div>
<div class="item">
text
<br>
line2
</div>
<div class="item">
text
</div>
<div class="item">
text
</div>
</div>
css
.wrapper{
display: flex;
flex-flow: row wrap;
margin: -10px;
padding: 10px;
background: green;
}
.item{
flex: 0 0 50%;
background: orange;
margin-bottom: 10px;
}
Case 2: All around margin
https://jsfiddle.net/6oaney4e/7/
Here for some reason the rows break I'm guessing that's because the row cant fit the items in with the extra margin on the side.
html same as CASE 1
css
.wrapper{
display: flex;
flex-flow: row wrap;
margin: -10px;
padding: 10px;
background: green;
}
.item{
flex: 0 0 50%;
background: orange;
margin: 10px;
}
Case 3: Wrapping items and adding margin to the inner item
https://jsfiddle.net/6oaney4e/8/
That worked but now the items on each row arent really aware of each other and cant have the same height.
html
<div class="wrapper">
<div class="item-wrap">
<div class="item">
text
</div>
</div>
<div class="item-wrap">
<div class="item">
text
<br>
line2
</div>
</div>
<div class="item-wrap">
<div class="item">
text
</div>
</div>
<div class="item-wrap">
<div class="item">
text
</div>
</div>
</div>
css
.wrapper{
display: flex;
flex-flow: row wrap;
margin: -10px;
padding: 10px;
background: green;
}
.item-wrap{
flex: 0 0 50%;
}
.item{
background: orange;
margin: 10px;
}
Is there a way to keep the HTML as in CASE 1 (without the div.item-wrap), have the items on each row the same height as in CASE 1 and have the spacing work like in CASE 3?
Ideally, you do want to use rows and make the .item-wrap divs flex-parents too.
.wrapper {
display: flex;
flex-flow: row wrap;
margin: -10px;
padding: 10px;
background: green;
}
.item-wrap {
flex: 0 0 50%;
display: flex;
}
.item {
background: orange;
margin: 10px;
flex: 1;
}
<div class="wrapper">
<div class="item-wrap">
<div class="item">
text
</div>
</div>
<div class="item-wrap">
<div class="item">
text
<br> line2
</div>
</div>
<div class="item-wrap">
<div class="item">
text
<br> line2
<br> line3
</div>
</div>
<div class="item-wrap">
<div class="item">
text
</div>
</div>
</div>
However if you must retain the existing structure, you'll need to use calc to adjust the flex-basis. Something like this:
.wrapper {
display: flex;
flex-flow: row wrap;
background: green;
justify-content: space-between;
}
.item {
flex-grow:0;
flex-shrink:0;
flex-basis:calc(50% - 10px); /* separate properties for IE11 upport */
background: orange;
margin: 5px;
}
<div class="wrapper">
<div class="item">
text
</div>
<div class="item">
text
<br> line2
</div>
<div class="item">
text
<br> line2
<br> line3
</div>
<div class="item">
text
</div>
</div>

Resources