Reputation: 5520
I have a list with different items which have auto widths (no fixed width can be given in my case). I use justify-content: space-between
because my first item has to start at the beginning of the container and my last item at the end.
All of the above works fine, but whenever I try to add a line between these list items, the problems start to emerge. I have no way to determine how many px or % I have to position these lines. Is there any way to 'dynamically' position the lines between the different list-items or not?
The html we are using is not editable as it is rendered by the CMS we are using.
This is what I have:
This is what I try to achieve
Here is the code I currently have
html {
box-sizing: border-box;
}
.Container {
max-width: 70%;
margin-right: auto;
margin-left: auto;
background: blue;
padding-top: 20px;
padding-bottom: 20px;
}
.Flex {
display: flex;
flex-flow: row wrap;
justify-content: space-between;
list-style: none;
margin: 0;
padding: 0;
}
.Flex-item {
background: red;
position: relative;
}
.Flex-item:after {
content: "";
position: absolute;
background: white;
width: 1px;
height: 40px;
top: 50%;
transform: translateY(-50%);
}
<div class="Container">
<ul class="Flex">
<li class="Flex-item">Lorem</li>
<li class="Flex-item">consectetur</li>
<li class="Flex-item">vestibulum</li>
<li class="Flex-item">nec</li>
<li class="Flex-item">condimentum</li>
</ul>
</div>
Upvotes: 47
Views: 79139
Reputation: 21
You can use this solution:
.Container {
max-width: 70%;
margin-right: auto;
margin-left: auto;
background: blue;
padding-top: 20px;
padding-bottom: 20px;
}
.Flex {
display: flex;
justify-content: space-between;
list-style: none;
margin: 0;
padding: 0;
}
.Flex-item {
/* here's part of the trick (content-box) */
background: red content-box;
}
/* here's part of the trick */
.Flex-item + .Flex-item {
border-left: 1px solid white;
margin-left: 1rem;
padding-left: 1rem;
}
<div class="Container">
<ul class="Flex">
<li class="Flex-item">Lorem</li>
<li class="Flex-item">consectetur</li>
<li class="Flex-item">vestibulum</li>
<li class="Flex-item">nec</li>
<li class="Flex-item">condimentum</li>
</ul>
</div>
Upvotes: 2
Reputation: 206151
Instead of :after
use a stylistic, ARIA representational LIs
<li class="separator" aria-hidden="true" role="presentation"></li>
like:
.Container {
max-width: 70%;
margin: 0 auto;
background: blue;
}
.Flex {
display: flex;
justify-content: space-between;
list-style: none; padding: 20px 0; margin:0;
}
.Flex-item {
background: red;
}
.separator {
background: white; width: 1px;
}
<div class="Container">
<ul class="Flex">
<li class="Flex-item">Lorem</li>
<li class="separator" aria-hidden="true" role="presentation"></li>
<li class="Flex-item">consectetur</li>
<li class="separator" aria-hidden="true" role="presentation"></li>
<li class="Flex-item">vestibulum</li>
<li class="separator" aria-hidden="true" role="presentation"></li>
<li class="Flex-item">nec</li>
<li class="separator" aria-hidden="true" role="presentation"></li>
<li class="Flex-item">condimentum</li>
</ul>
</div>
P.S: yes, I tried using display: list-item
initially on the :after
pseudo but naah.
Upvotes: 9
Reputation: 603
I'm using this solution on a project I'm working on.
It sets justify-content: space-between;
on the flex container and flex: 1 1 auto;
on the children with a left border on all childrens except first.
I modified your example CSS so you can have a look. I wasn't sure if you were going to have background color on the children so I just used line-height to get larger borders.
html {
box-sizing: border-box;
}
.Container {
max-width: 70%;
margin-right: auto;
margin-left: auto;
background: blue;
padding-top: 20px;
padding-bottom: 20px;
}
.Flex {
display: flex;
flex-flow: row wrap;
justify-content: space-between;
list-style: none;
margin: 0;
padding: 0;
}
.Flex-item {
flex: 1 1 auto;
background: red;
position: relative;
text-align: center;
line-height: 40px;
}
.Flex-item + .Flex-item {
border-left: solid 1px white;
}
/** Optional for OPs exact layout */
.Flex-item:first-child {
text-align: left;
}
.Flex-item:last-child {
text-align: right;
}
<div class="Container">
<ul class="Flex">
<li class="Flex-item">Lorem</li>
<li class="Flex-item">consectetur</li>
<li class="Flex-item">vestibulum</li>
<li class="Flex-item">nec</li>
<li class="Flex-item">condimentum</li>
</ul>
</div>
No modification to HTML.
Upvotes: 40
Reputation: 105903
if you imbricate flex
, you might get something close to what you try to do without any extra markup.
It involves pseudos, order
& css3 selectors(fine aside flex
).
http://codepen.io/gc-nomade/pen/BpzYWP
body {
margin:0;
}
.Flex, .Flex-item {
display:flex;
padding:0.5em 0;
margin:0;
}
.Flex-item {
flex:1;/*spray them evenly*/
}
.Flex-item:before,
.Flex-item:after {/* add pseudos to fill extra space */
content:'';
flex:1;/* thats where it takes room not use by the text */
margin:-1em 0;/* grow them taller */
border-right:solid 1px white;
}
.Flex-item:first-child:before
{
order:2;/* put both pseudo after text*/
flex:.5;/* shrink that one can be .75 to .25 */
border:none; /* remove the border useless for the show */
}
.Flex-item:last-child:after {
order:-1;/* put both pseudos before text */
flex:0.5;/* shrink that one can be .75 to .25 */
}
.Flex-item:first-child + .Flex-item:before ,
.Flex-item:nth-last-child(1):after{
border:none; /* remove the border useless for the show */
}
body, :after, :before {
background:tomato;/* pseudo will hide li background */
}
li {
background:turquoise;
}
/* give some space around the text */
.Flex-item:first-child {
padding-left:1em;
}
.Flex-item:last-child {
padding-right:1em;
}
.Flex-item:before {
border:none;/* we do not need those after all */
margin-right:1em;
}
.Flex-item:after {
margin-left:1em;
}
.Flex-item:first-child:before {
margin:-1em 0;
}.Flex-item:last-child:after {
margin:-1em 0;
}
<div class="Container">
<ul class="Flex">
<li class="Flex-item">Lorem</li>
<li class="Flex-item">consectetur</li>
<li class="Flex-item">vestibulum</li>
<li class="Flex-item">nec</li>
<li class="Flex-item">condimentum</li>
</ul>
</div>
Upvotes: 1
Reputation: 371271
I think the only way to accomplish this with flexbox is to wrap the text in a new element, as @Kukkuz has done in another answer.
Without that extra wrapper, you can still get the equal spaced dividers, but the red background isn't confined to the length of the text.
Below is an example with:
If a background color for the text isn't necessary, then remove it and this should be all you need.
.Flex {
display: flex;
list-style: none;
margin: 0;
padding: 0;
}
.Flex-item {
flex: 1 1 auto;
background: red;
}
.Flex-item {
text-align: center;
}
.Flex-item:first-child {
text-align: left;
}
.Flex-item:last-child {
text-align: right;
}
.Flex-item + .Flex-item {
border-left: 1px solid white;
}
.Container {
max-width: 70%;
margin-right: auto;
margin-left: auto;
background: blue;
padding-top: 20px;
padding-bottom: 20px;
}
<div class="Container">
<ul class="Flex">
<li class="Flex-item">Lorem</li>
<li class="Flex-item">consectetur</li>
<li class="Flex-item">vestibulum</li>
<li class="Flex-item">nec</li>
<li class="Flex-item">condimentum</li>
</ul>
</div>
If you can add a span
around the text, which will allow you to limit the red background to the length of the text, then you're all set:
.Flex {
display: flex;
list-style: none;
margin: 0;
padding: 0;
}
.Flex-item {
flex: 1 1 auto;
display: inline-flex;
justify-content: center;
}
.Flex-item span {
background-color: red;
}
.Flex-item:first-child span {
margin-right: auto;
}
.Flex-item:last-child span {
margin-left: auto;
}
.Flex-item + .Flex-item {
border-left: 1px solid white;
}
.Container {
max-width: 70%;
margin-right: auto;
margin-left: auto;
background: blue;
padding-top: 20px;
padding-bottom: 20px;
}
<div class="Container">
<ul class="Flex">
<li class="Flex-item"><span>Lorem</span></li>
<li class="Flex-item"><span>consectetur</span></li>
<li class="Flex-item"><span>vestibulum</span></li>
<li class="Flex-item"><span>nec</span></li>
<li class="Flex-item"><span>condimentum</span></li>
</ul>
</div>
Upvotes: 2
Reputation: 42352
You can make it work by using a nested flexbox
es - I understand you can't change the markup, but at least you have to wrap the contents of the li
into a span
like I have here:
Make .flex-item
also a flexbox
with the text in a span
(this would have the red background now) and the separator as an :after
element
Apply flex-grow
and flex-shrink
to 1 and flex-basis
to auto
for the Flex-item
.
The flex: 0
to the last Flex-item
and margin-auto
to the :after
also contributes to the effect.
A demo may explain it better - see below:
html {
box-sizing: border-box;
}
.Container {
max-width: 70%;
margin-right: auto;
margin-left: auto;
background: blue;
padding-top: 20px;
padding-bottom: 20px;
}
.Flex {
display: flex;
justify-content: space-between;
list-style: none;
margin: 0;
padding: 0;
}
.Flex-item {
display: flex;
justify-content: space-between;
align-items: center;
flex: 1 1 auto;
}
.Flex-item span {
background: red;
}
.Flex-item:not(:last-child):after {
content: "";
border: 1px solid white;
height: 40px;
margin: auto;
}
.Flex-item:last-child {
flex: 0;
}
<div class="Container">
<ul class="Flex">
<li class="Flex-item">
<span>Lorem</span>
</li>
<li class="Flex-item">
<span>consectetur</span>
</li>
<li class="Flex-item">
<span>vestibulum</span>
</li>
<li class="Flex-item">
<span>nec</span>
</li>
<li class="Flex-item">
<span>condimentum</span>
</li>
</ul>
</div>
Upvotes: 7
Reputation: 1490
Try this
html {
box-sizing: border-box;
}
.Container {
max-width: 90%;
margin-right: auto;
margin-left: auto;
background: blue;
padding-top: 11px;
padding-bottom: 50px;
}
.Flex {
list-style: none;
margin: 0;
padding: 0;
position: relative;
left: 50%;
transform: translateX(-50%);
float: left;
}
.Flex-item {
position: relative;
float: left;
padding: 5px 10px;
border-right:1px solid #fff;
}
.Flex-item:last-child{border-right:none;}
.Flex-item >div{
margin:0 5px;
background:red;
padding:5px;
}
<div class="Container">
<ul class="Flex">
<li class="Flex-item"><div>
Lorem
</div></li>
<li class="Flex-item"><div>
consectetur
</div></li>
<li class="Flex-item"><div>
vestibulum
</div></li>
<li class="Flex-item"><div>
nec
</div></li>
<li class="Flex-item"><div>
condimentum
</div></li>
</ul>
</div>
Upvotes: 0