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>
Related
I am trying to get 3 columns in a row and be the same height.
I am using the HTML/CSS below. I can't figure out why the boxes arent the same height.
.container {
text-align: center;
display: block;
width: 100%;
}
.grid {
width: 100%;
height: 100%;
}
.row {
display: flex;
height: 100%;
flex-direction: row;
}
.col {
background: #444;
padding: 2em;
flex: 1;
height: 100%;
border: 1px solid blue;
}
<div class="container">
<div class="data">
<div class="grid">
<div class="row">
<div class="col">
<p>col 1</p>
</div>
<div class="col">
<p>col </br>2</p>
</div>
<div class="col">
<p>col 3</p>
</div>
</div>
</div>
</div>
</div>
How can I make the boxes all the same height. thanks
Simply, remove the height: 100% from .col.
flex: 1; will do the job.
.row {
display: flex;
}
.col {
flex: 1;
background: #444;
padding: 2em;
border: 1px solid blue;
text-align: center;
}
<div class="container">
<div class="data">
<div class="grid">
<div class="row">
<div class="col">
<p>col 1</p>
</div>
<div class="col">
<p>col </br>2</p>
</div>
<div class="col">
<p>col 3</p>
</div>
</div>
</div>
</div>
</div>
This question already has answers here:
Align inline-block DIVs to top of container element
(5 answers)
Why is this inline-block element pushed downward?
(8 answers)
Closed 1 year ago.
I am trying to order some divs, the idea is that I want to be able to offset them relative to each other to create asymmetrical grid.
All of it is working, until the moment content is added inside.
When a content is added into a div, that div is moved and positioned relative to the content inside it, so that the content is at the top left of the div, I am expecting the opposite behaviour, the div should not move, and the content should move relative to the div.
NOTE: I can not use an outside container to wrap all of them in it.
.column{
width: 49%;
height: 200px;
position: relative;
display: inline-flex;
}
.column:nth-child(2n){
top: 30px;
right: 20px;
}
.column:nth-child(2n - 1){
bottom: 30px;
left: 20px;
}
.red {
background-color: red;
}
.green {
background-color: green;
}
.blue {
background-color: blue;
}
<div class="column red">
<p>
This breaks it
</p>
</div>
<div class="column green">
</div>
<div class="column blue">
</div>
<div class="column red">
</div>
<div class="column green">
</div>
<div class="column blue">
</div>
<div class="column red">
</div>
<div class="column green">
</div>
<div class="column blue">
If possible you could achieve the expected behavior by wraping the content inside another div and positioning it using position: absolute
.column{
width: 49%;
height: 200px;
position: relative;
display: inline-flex;
}
.column:nth-child(2n){
top: 30px;
right: 20px;
}
.column:nth-child(2n - 1){
bottom: 30px;
left: 20px;
}
.red {
background-color: red;
}
.green {
background-color: green;
}
.blue {
background-color: blue;
}
.column > div {
position: absolute
}
<div class="column red">
<div>
<p>
This breaks it
</p>
</div>
</div>
<div class="column green">
</div>
<div class="column blue">
</div>
<div class="column red">
</div>
<div class="column green">
</div>
<div class="column blue">
</div>
<div class="column red">
</div>
<div class="column green">
</div>
<div class="column blue">
Why don't you use the old pal float. I still use it over flex and grid often. much easier when simple layouts-
* {box-sizing:border-box;}
.column{
width: 50%;
height: 200px;
float:left;
position:relative;
}
.column:nth-child(2n){
top: 30px;
right: 20px;
}
.column:nth-child(2n - 1){
bottom: 30px;
left: 20px;
}
.red {
background-color: red;
}
.green {
background-color: green;
}
.blue {
background-color: blue;
}
<div class="column red">
<p>
This breaks it
</p>
</div>
<div class="column green">
</div>
<div class="column blue">
</div>
<div class="column red">
</div>
<div class="column green">
</div>
<div class="column blue">
</div>
<div class="column red">
</div>
<div class="column green">
</div>
<div class="column blue">
Note: I add box-sizing rule becouse I hate that width:49%
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>
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>
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>