how to add icon to a div using the pseudo elements- CSS

Viewed 1121

I want to add an icon as a connector before a div container: something like this:

enter image description here

This is what I have have (https://jsfiddle.net/kmcursf6/).

.parent {
  border-left: 1px solid #ff0000;
}

.child {
  position: relative;
  margin-left: 20px;
  background: #e9e9e9;
  margin-bottom: 10px;
  padding: 10px;
}

.child::before {
  position: absolute;
  content: '';
  left: -20px;
  top: 50%;
  border-top: 1px solid #ff0000;
  width: 20px;
}

.child:last-child::after {
  position: absolute;
  content: '';
  left: -21px;
  top: calc(50% + 1px);
  bottom: 0;
  border-left: 1px solid #FFFFFF;
}
<div class="parent">
  <div class="child">
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat
  </div>
  <div class="child">
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat
  </div>
  <div class="child">
    click to add more
  </div>
</div>

I tried this to add that icon:

.child::before {
  position: absolute;
  content: '';
  left: -20px;
  top: 50%;
  width: 20px;
  transform: rotate(90deg);
  border-radius: 20px;
}

but it doesn't work and it completely throws off what I have. Any ideas how to get there?

3 Answers
.child::after {
  position: absolute;
  content: '';
  left: -10px;
  top: 50%;
  margin-top: -10px;
  width: 20px;
  height: 20px;
  background: #000;
  border-radius: 90%;
  clip-path: polygon(50% 0, 50% 100%, 0 100%, 0 0);
}

https://jsfiddle.net/r5z0av87/1/

.parent {
  border-left: 1px solid #000;
}

.child {
  position: relative;
  margin-left: 20px;
  background: #e9e9e9;
  margin-bottom: 10px;
  padding: 10px;
  
}

.child::before {
  position: absolute;
  content: '';
  left: -5px;
  top: calc(50% - 5px);
  border: 1px solid black;
  background: black;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  z-index: -1;
}
.child::after{
    position: absolute;
  content: '';
  left: -20px;
  top: 50%;
  border-top: 1px solid #000;
  width: 20px;
}

.child:last-child::after {
  position: absolute;
  content: '';
  left: -21px;
  top: calc(50% + 1px);
  bottom: 0;
  border-left: 1px solid #FFFFFF;
}
<div class="parent">
  <div class="child">
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat
  </div>
  <div class="child">
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat
  </div>
  <div class="child">
    click to add more
  </div>
</div>

Add an ::before element. Create an square. put border-radius: 50% so you have an circle. Then position the element at the right place. Put z-index: -1 so that the circle is under your div block.

Use calc to calculate the vertical alignment. calc(50% - 5px) here i used 50% like for the lines and 5px are the half of the width or height of the square.

For left i used 6px. Usually 5px, the half of the width, should be the exact half but i decided to go with 6px kinda looks better for me, personal opinion.

.child::before {
  position: absolute;
  content: '';
  left: -6px;
  top: calc(50% - 5px);
  border: 1px solid black;
  background: black;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  z-index: -1;
}

It's hard to create a black circle and a horizontal line in the middle with using only CSS. Therefore, I reached the conclusion that the circle and the horizontal line must be two separate pseudo-elements.

In this case, the ::after pseudo-element creates the circle part. Also, we use the z-index to make it so that the full circle appears only as semicircle because half of it is covered by div.child.

As for the horizontal line, we are still creating it using the ::before pseudo-element. However, the line (from the parent's border-left) is protruding and we want to make the last trailing bit of the list-like line disappear. To do this, we can modify the last div.child's ::before pseudo-element so that it is instead a rectangle. Set its height to 50% of div.child, position it to 50% from the top of the div.child, make the border-top black to create the horizontal line, and make the border-left white to cover the parent's trailing line.

Here's a working example. I used 4px on last div.child::before pseudo-element so that it doesn't draw wrongly upon zoom. Also, you might want to read about box-sizing: border-box here (although unrelated).

.parent {
  font-family: Helvetica;
  font-size: 0.8em;
  border-left: 1px solid #000;
}

.child {
  position: relative;
  margin-left: 20px;
  background: #e9e9e9;
  margin-bottom: 10px;
  padding: 10px;
}

.child::before {
  position: absolute;
  content: '';
  top: 50%;
  left: -20px;
  border-top: 1px solid #000;
  width: 20px;
}

.child::after {
  position: absolute;
  z-index: -1;
  content: '';
  top: 50%;
  left: -5px;
  width: 10px;
  height: 10px;
  background: black;
  border-radius: 50%;
  transform: translateY(-50%);
}

.child:last-child::before { 
  box-sizing: border-box;
  border-left: 4px solid #FFF;
  height: 50%;
  left: -22px;
}
<div class="parent">
  <div class="child">
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat
  </div>
  <div class="child">
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat
  </div>
  <div class="child">
    click to add more
  </div>
</div>

Related