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>
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.
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>
Instead of :after
try using a set of <li class="separator"></li>
.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>
PS: yes, I tried using display: list-item
initially on the :after
pseudo but naah.
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>
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>
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>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.