I need to design a navigation rendered dynamically by a CMS (so I have no control over HTML markup). The menu has a unknown, variable number of items, and all items have a variable, unknown width. I need to layout those menu items in one line with an equidistant spacing in between (easily done with flexbox) and with a visual separator exactly in the middle of the spacing (this is my unsolved problem).
Below is the code I've got so far. The HTML is just an example output, and I can't modify it. I'm also not allowed to use JS. The CSS is from myself and I can fully control it.
.mainnav {
width: 100%;
display: flex;
justify-content: space-between;
list-style-type: none;
margin: 0;
padding: 0;
border: 1px solid black;
}
.mainnav__item {
flex: 0 0 auto;
background-color: yellow;
position: relative;
white-space: nowrap;
}
.mainnav__item + .mainnav__item::before {
content: '';
width: 1px;
height: 100%;
background-color: red;
position: absolute;
left: -50%;
top: 0;
}
<ul class="mainnav">
<li class="mainnav__item">
<a class="mainnav__link" href="#">Short</a>
</li>
<li class="mainnav__item">
<a class="mainnav__link" href="#">Looooooooooooooong</a>
</li>
<li class="mainnav__item">
<a class="mainnav__link" href="#">Mediuuum</a>
</li>
<li class="mainnav__item">
<a class="mainnav__link" href="#">whatever else</a>
</li>
</ul>
My problem is the red separator line. It should be exactly in the middle, but I don't know how to calculate the horizontal position.
Can anybody tell me a CSS only solution for the delimiter placement?
The solution should work in common, up-to-date browsers (current version of [Android|Win] Chrome, [macOs|iOs] Safari, Firefox, Edge), but also in IE11
One idea is to consider display:contents;1 within the li element and keep the pseudo element in-flow (remove position:absolute). This will make the pseudo element and the a to be the flex items instead of the li element thus space-between will do the job.
Simply pay attention to the browser support since it's a new feature.
.mainnav {
width: 100%;
display: flex;
justify-content: space-between;
list-style-type: none;
margin: 0;
padding: 0;
border: 1px solid black;
}
.mainnav__item {
flex: 0 0 auto;
position: relative;
white-space: nowrap;
display:contents;
}
.mainnav__item a {
background:yellow;
}
.mainnav__item + .mainnav__item::before {
content: '';
width: 1px;
display:block;
background-color: red;
}
<ul class="mainnav">
<li class="mainnav__item">
<a class="mainnav__link" href="#">Short</a>
</li>
<li class="mainnav__item">
<a class="mainnav__link" href="#">Looooooooooooooong</a>
</li>
<li class="mainnav__item">
<a class="mainnav__link" href="#">Mediuuum</a>
</li>
<li class="mainnav__item">
<a class="mainnav__link" href="#">whatever else</a>
</li>
</ul>
1 The element itself does not generate any boxes, but its children and pseudo-elements still generate boxes and text runs as normal. For the purposes of box generation and layout, the element must be treated as if it had been replaced in the element tree by its contents (including both its source-document children and its pseudo-elements, such as ::before and ::after pseudo-elements, which are generated before/after the element’s children as normal).ref
Another idea is to adjust flex-grow and use border instead of relying on space-between:
.mainnav {
display: flex;
list-style-type: none;
margin: 0;
padding: 0;
border: 1px solid black;
}
.mainnav__item {
flex: 0 0 auto;
position: relative;
white-space: nowrap;
flex-grow:2; /*middle elements need to grow twice that edge element*/
text-align:center;
border-left:1px solid red;
border-right:1px solid red;
}
.mainnav__item a {
background:yellow;
}
.mainnav__item:first-child {
flex-grow:1;
text-align:left;
border-left:none;
}
.mainnav__item:last-child {
flex-grow:1;
text-align:right;
border-right:none;
}
<ul class="mainnav">
<li class="mainnav__item">
<a class="mainnav__link" href="#">Short</a>
</li>
<li class="mainnav__item">
<a class="mainnav__link" href="#">Looooooooooooooong</a>
</li>
<li class="mainnav__item">
<a class="mainnav__link" href="#">Mediuuum</a>
</li>
<li class="mainnav__item">
<a class="mainnav__link" href="#">whatever else</a>
</li>
</ul>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With