I want to add bullet points between my flexbox navigation menu, but only have them appear between flex items on the same line. Not at the beginning or end of line, and not at all if the flex item is on the line by itself.
I've been using this (CSS styling for horizontal list with bullet only between elements) question as a starting point, but modified bined the top two answers to make it work with a flexbox.
Here's what I've got:
JS:
<script>
$(function() {
var lastElement = false;
$("ul li").each(function(index) {
if (lastElement && lastElement.offset().top == $(this).offset().top) {
$(lastElement).after( $('<li>').attr('class', 'bullet') );
}
lastElement = $(this);
});
});
</script>
CSS (essentially the exact same as the original question I linked to):
<style>
.bullet {
width: 6px;
height: 7px;
background-position: 50% 50%;
background-repeat: no-repeat;
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAOElEQVQI113M0Q3AIBRC0aM76P7jmHSmSj/6mibyc4EQkEEWuYtDmU1SXO1d6H7tjgupIl8+P+cD22cff9U1wbsAAAAASUVORK5CYII=);
}
</style>
Most of the time everything renders correctly. But at certain browser widths, bullet points are added where they shouldn't be. For instance, if the window is re-sized to a width of 678 px (according to the codepen.io counter that displays in the middle of screen while re-sizing), a bullet point appears on the right side of the top row when it shouldn't. (Depending on the browser it may work correctly at 678px, but there are several spots that it does occur, and I've only tested this on Chrome and IE11).
Sometimes a refresh is required to fix the bullet points locations, which is understandable, but at some widths refreshing doesn't help and they reappear incorrectly.
I believe the problem is caused by the extra space the bullet points add.
I think it would be a simpler and cleaner solution to do it entirely via CSS instead of JS, but I'm not sure that's possible with flexbox items. Even though the flexbox items appear to take up a wider width than their content, the css selector ::after seems to only calculate the actual content width.
What is going on with my JS? Can I make it better/cleaner?
I want to add bullet points between my flexbox navigation menu, but only have them appear between flex items on the same line. Not at the beginning or end of line, and not at all if the flex item is on the line by itself.
I've been using this (CSS styling for horizontal list with bullet only between elements) question as a starting point, but modified bined the top two answers to make it work with a flexbox.
Here's what I've got: http://codepen.io/anon/pen/EjQzWZ
JS:
<script>
$(function() {
var lastElement = false;
$("ul li").each(function(index) {
if (lastElement && lastElement.offset().top == $(this).offset().top) {
$(lastElement).after( $('<li>').attr('class', 'bullet') );
}
lastElement = $(this);
});
});
</script>
CSS (essentially the exact same as the original question I linked to):
<style>
.bullet {
width: 6px;
height: 7px;
background-position: 50% 50%;
background-repeat: no-repeat;
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAOElEQVQI113M0Q3AIBRC0aM76P7jmHSmSj/6mibyc4EQkEEWuYtDmU1SXO1d6H7tjgupIl8+P+cD22cff9U1wbsAAAAASUVORK5CYII=);
}
</style>
Most of the time everything renders correctly. But at certain browser widths, bullet points are added where they shouldn't be. For instance, if the window is re-sized to a width of 678 px (according to the codepen.io counter that displays in the middle of screen while re-sizing), a bullet point appears on the right side of the top row when it shouldn't. (Depending on the browser it may work correctly at 678px, but there are several spots that it does occur, and I've only tested this on Chrome and IE11).
Sometimes a refresh is required to fix the bullet points locations, which is understandable, but at some widths refreshing doesn't help and they reappear incorrectly.
I believe the problem is caused by the extra space the bullet points add.
I think it would be a simpler and cleaner solution to do it entirely via CSS instead of JS, but I'm not sure that's possible with flexbox items. Even though the flexbox items appear to take up a wider width than their content, the css selector ::after seems to only calculate the actual content width.
What is going on with my JS? Can I make it better/cleaner?
Share Improve this question edited May 23, 2017 at 12:23 CommunityBot 11 silver badge asked Jul 3, 2015 at 23:07 SmokeyTehBearSmokeyTehBear 911 silver badge6 bronze badges4 Answers
Reset to default 3You can put your bullet logic in a function, then call that function on page load and attach it to the window resize event.
The updated javascript would look like this:
$(function() {
addBullets();
$(window).resize(addBullets);
});
function addBullets(){
$('li.bullet').remove(); //remove bullets before you add new ones
var lastElement = false;
$("ul li").each(function(index) {
if (lastElement && lastElement.offset().top == $(this).offset().top) {
$(lastElement).after( $('<li>').attr('class', 'bullet') );
}
lastElement = $(this);
});
}
See this updated CodePen for a demo.
Also, I don't think this would be possible with pure CSS.
UPDATE
The reason the bullet was showing up on the edge in those certain widths is because the bullets them selves where <li>
's also and were taking up 6px a piece. So when you iterate through the <li>
's It would correctly identify the correct element to put the bullet after, but when the browser renders all the small bullets it would... at certain widths... shove the last <li>
to the next line.
To correct this I have created a CSS class for the bullets and will add that to the items that need bullets instead of creating new <li>
's which would take up additional space.
New CSS:
.flex-item {
position:relative; /*added*/
flex: 1 1 auto;
color: #a6a7a9;
font-size:1.5em;
padding: 50px; /*use padding instead of margin for easier absolute positioning of bullet*/
color: black;
text-align: center;
}
.flex-item.bullet:after{
position:absolute;
right:0;
top:50%;
transform:translateY(-50%);
color:blue;
content:"•"; /*could also be "url(data:image/png;base64 ..."*/
}
New Javascript:
function addBullets(){
$('li.bullet').removeClass('bullet'); //remove all bullet classes
var lastElement = false;
$("ul li").each(function(index) {
if (lastElement && lastElement.offset().top == $(this).offset().top)
$(lastElement).addClass('bullet'); //add class
lastElement = $(this);
});
}
See this updated CodePen.
If for whatever reason you can't use this CSS class approach you could add your bullets (as <img>
or <div>
) inside the <li>
and position them absolutely with CSS. As long as they don't contribute to the overall width of the <ul>
it should work fine.
You can do this using CSS only.
Delete your .bullet
definition, and add this CSS:
.flex-container {
margin-left: -10px; //hide the first bullet on each row
}
.flex-item {
position: relative; //so we can have absolute positioning on the :before
}
.flex-item:before {
content: "•"; //the bullet
position: absolute; //positioned absolutely
left: -55px; //account for the 50px margin and the bullet's width
}
Updated CodePen
div:before{
content:"\b7\a0"; /* \b7 is a middot, \a0 is a space */
font-size:30px;
}
Or try this
div:before{
content:"•";
}
You can use the :not(:first-child) selector to apply the bullet to all but the first child.
.flex-row
{
display: flex;
flex-direction: row;
&.bulleted
{
div:not(:first-child):before{
content: "•";
}
}
}