CSS - Vertical line between bullets in an unordered list
Asked Answered
J

5

36

How would I go about drawing a vertical line between the bullets in an unordered list, like so:

enter image description here

Notice that the line stops at the last list bullet. I'm using list-style:none; and images as bullets. The HTML looks like this:

<ul class="experiences">

  <!-- Experience -->
  <li class="green">
    <div class="where">New York Times</div>
    <h3 class="what green">Senior Online Editor</h3>
    <div class="when">2012 - Present</div>

    <p class="description">Jelly-o pie chocolate cake...</p>
   </li>

   ...

CSS code as requested:

/* Experiences */
ul.experiences {
    padding-left: 15px;
    margin-top: -1px;
}
ul.experiences li {
    padding-left: 33px;
    margin-bottom: 2.5em;
    list-style: none;
    background: url('../img/misc/list-bullet-darkgray.png') no-repeat;
}
ul.experiences li.green {
    background: url('../img/misc/list-bullet-green.png') no-repeat;
}
ul.experiences li.blue {
    background: url('../img/misc/list-bullet-blue.png') no-repeat;
}
ul.experiences li.pink {
    background: url('../img/misc/list-bullet-pink.png') no-repeat;
}
.where {
    font-size: 1.2857em; /* 18/16 -> 18px */
    font-weight: 300;
    display: inline;
    margin-right: 0.5em;
}
.what {
    font-size: 0.75em; /* 12/16 -> 12px */
    font-weight: 700;
    text-transform: uppercase;
    color: #fff;
    background-color: #444444;
    display: inline-block;
    padding: 0 12px;
    margin: -5px 0.5em 0 0 !important;
    -webkit-border-radius: 3px;
    -moz-border-radius: 3px;
    border-radius: 3px;
}
.what.green {
    background-color: #c4df9b;
}
.what.blue {
    background-color: #6dcff6;
}
.what.pink {
    background-color: #f06eaa;
}
.when {
    float: right;
    color: #b9b9b9;
    font-style: italic;
}
.description {
    display: block;
    margin-top: 0.5em;
}
Jeffers answered 13/7, 2013 at 10:25 Comment(4)
I believe you can use .experiences li:last-child to -not- display a left-border while you can use .experiences li to display a border on the left side of the restBoreas
@Boreas This way, the border won't go down to the last bullet.Mongrelize
So, did you solve this problem? If you used a solution provided on this page, consider marking it as an accepted answer.Mongrelize
Sorry for the delay, I haven't had time to look at this for a while. See my comment of your answer.Jeffers
M
35

I doubt that this is achievable using just borders and "fiddling with margins" as others have suggested, at least I've had no luck in doing so.

This solution uses CSS-generated content (:before and :after) to draw bullets and lines. It allows for a high degree of customization and it keeps the markup clean, but note the browser support.

JSFiddle (scroll through CSS until the /* BORDERS AND BULLETS */ comment)

ul.experiences li {
    position:relative; /* so that pseudoelements are positioned relatively to their "li"s*/
    /* use padding-bottom instead of margin-bottom.*/ 
    margin-bottom: 0; /* This overrides previously specified margin-bottom */
    padding-bottom: 2.5em;
}

ul.experiences li:after {
    /* bullets */
    content: url('http://upload.wikimedia.org/wikipedia/commons/thumb/3/30/RedDisc.svg/20px-RedDisc.svg.png');
    position: absolute;
    left: -26px; /*adjust manually*/
    top: 0px;
}

ul.experiences li:before {
    /* lines */
    content:"";
    position: absolute;
    left: -16px; /* adjust manually */
    border-left: 1px solid black;
    height: 100%;
    width: 1px;
}

ul.experiences li:first-child:before {
   /* first li's line */
   top: 6px; /* moves the line down so that it disappears under the bullet. Adjust manually */
}

ul.experiences li:last-child:before {
    /* last li's line */
   height: 6px; /* shorten the line so it goes only up to the bullet. Is equal to first-child:before's top */
}

NOTE: if the line's border-color has an alpha-channel specified, the overlap between first and second elements' borders will be noticeable.

Mongrelize answered 13/7, 2013 at 11:38 Comment(4)
This seems to be working great - except for IE8 which shows the line for the last item as well... Is there any way around this? I will accept this answer if I get it to work with IE8. Look at this example with IE8: graphic-dev.com/stuff/vcardJeffers
I haven't found a way to support IE8 here purely with CSS. The best workaround is to use jQuery (since you'll probably use it on the page anyway). It has a :last-child selector, which can be used to assign a specific class to the last child, e.g. experiences-last-li. Then change the last rule's selector from ul.experiences li:last-child:before to ul.experiences li.experiences-last-li:before. Don't forget to add a comment in the source explaining the need for this workaround!Mongrelize
EDIT: Works like a charm! Why didn't I think of that...? :) Thanks a lot!Jeffers
Thanks dude. It saved me half working day. Cheers :+1:Insurrection
G
8

Since there aren't many good answers here, I figured I'd add my solution:

I take advantage of position relative and include a white mask on the last item to hide the overflow. Works in mobile view and variation of the item heights.

example of line through bullet points

HTML

<div class="list-wrapper">

    <div class="red-line"></div>

    <div class="list-item-wrapper">
        <div class="list-bullet">1</div>
        <div class="list-item">
            <div class="list-title">ITEM</div>
            <div class="list-text">Text</div>
        </div>
    </div>

    <div class="list-item-wrapper">
        <div class="list-bullet">2</div>
        <div class="list-item">
            <div class="list-title">ITEM</div>
            <div class="list-text">Text</div>
        </div>
    </div>

    <div class="list-item-wrapper">
        <div class="list-bullet">3</div>
        <div class="list-item">
            <div class="list-title">ITEM</div>
            <div class="list-text">Text</div>
        </div>
        <div class="white-line"></div>
    </div>

</div>

CSS

.list-wrapper {
  position:relative;
}
.list-item-wrapper {
  margin-top:10px;
  position:relative;
}
.list-bullet {
  float:left;
  margin-right:20px;
  background:#FF4949;
  height:30px;
  width:30px;
  line-height:30px;
  border-radius:100px;
  font-weight:700;
  color:white;
  text-align:center;
}
.list-item {
  display:table-row;
  vertical-align:middle;
}
.list-title {
    font-weight:700;
}
.list-text {
    font-weight:400;
}
.red-line {
  background:#FF4949;
  z-index:-1;
  width:1px;
  height:100%;
  position:absolute;
  left:15px;
}
.white-line {
  background:#FFF;
  z-index:-1;
  top:0px;
  width:1px;
  height:100%;
  position:absolute;
  left:15px;
}

DEMO http://jsfiddle.net/cfzsgkyn/

Grime answered 31/10, 2018 at 16:46 Comment(0)
F
1

Probably a bit old now but here is a way you can do this. It requires a bit more markup to create styles and control the heights of elements (I used spans but you can use tags ):

ol,
ul {
  list-style: none;
}
li {
  display: flex;
  flex-flow: row;
  min-height: 100px;
  position: relative;
}
span.number {
  margin-right: 100px;
  text-align: center;
  width: 1em;
  height: 1em;
  background-color: red;
  border-radius: 50%;
  z-index: 1;
}
span.line {
  position: absolute;
  height: 100%;
  border: solid black 0.1em;
  top: 0.5em;
  left: 0.45em;
}
li:last-child span.line {
  display: none;
}
}
span.blob {}
<ul>
  <li><span class='line'></span><span class='number'>1</span>
    <div class='blob'>Hello</div>
  </li>
  <li><span class='number'>2</span>
    <div class='blob'>Goodbye</div>
  </li>
</ul>

http://jsfiddle.net/efava0je/

Featherstitch answered 19/11, 2015 at 22:35 Comment(1)
You should include your css from the jsfiddle.Blus
T
0
ul.experiences li {
    padding-left: 33px;
    margin-bottom: 2.5em;
    list-style: none;
    background: url('../img/misc/list-bullet-darkgray.png') no-repeat;
    border-left: 1px solid #yourcolor;
}

And then I would just use padding and margins to align it and to stop the last one from extending:

ul.experiences li:last-child {
    padding-left: 33px;
    margin-bottom: 2.5em;
    list-style: none;
    background: url('../img/misc/list-bullet-darkgray.png') no-repeat;
    border-left: none;
}

The last child selector does not work in versions of IE < 7

DEMO

Triturable answered 13/7, 2013 at 10:32 Comment(2)
Currently that solution looks like this: s18.postimg.org/jok2ljwzd/line.png As you can see, there are a couple of issues. The white space between the list items might be possible to fix by using padding instead of margin, but I'm not sure if that's optimal... Also, I don't want the line to extend even one pixel above the first bullet or below the last one...Jeffers
@graphic_dev then you need to play around with paddings, margins and offsetting the background image of the bullet point so it all lines up. Its fiddly but using a border is the best solution.Triturable
R
-1

You need to add a inner and outter div and then play with margins. Here is what i mean

DEMO: http://jsfiddle.net/kevinPHPkevin/N9svF/

ul {
    padding-left:14px;
    margin-top:-6px;
    margin-bottom:-6px;
    padding-bottom:0;
}
#mainDiv {
    height: 200px;
    width:200px;
    position: relative;
}
#borderLeft {
    border-left: 2px solid #f51c40;
    position: absolute;
    top: 25px;
}
Rechabite answered 13/7, 2013 at 10:44 Comment(2)
I don't think this will work. You're using a negative bottom-margin to make sure that the line doesn't extend below the last bullet, but there is no way of knowing what the height of the last li item will be. See this example where I have two lines of content for the last li item: jsfiddle.net/N9svF/3Jeffers
THIS WORKS. However, you have to add a negative left margin to the list items. Like this: li {margin-left:-5px;}Krongold

© 2022 - 2024 — McMap. All rights reserved.