Guy Ben David
Guy Ben David

Reputation: 518

CSS - drawing lines between dynamically sized boxes


I created something like this using CSS.
The tricky thing here is that the height of the boxes can change if the text is too long.

So, I don't know how to make the dashed lines always behave this way, because the size of the boxes is dynamic.
(There should always be a line from the middle of the first box to the middle of the next box)

This is the HTML and CSS I'm using now.

boxes with dashed lines

Upvotes: 6

Views: 1683

Answers (2)

Amaury Hanser
Amaury Hanser

Reputation: 3456

Here is a quick proof of concept with a minimal markup.
I believe that you don't need any extra empty div.

li {
  position: relative;
  list-style: none;
  max-width: 77ch;
  background-color: #ccc;
  border-radius: 1em;
  padding: 1em;
  margin-bottom: 1em;
  z-index: 2;
}

li:before {
  content:'';
  position: absolute;
  display: block;
  height: 0px;
  width: 2em;
  top: 50%;
  left: -2em;
  border-top: 1px red dashed;
  z-index: -1;
}

li:after {
  content:'';
  position: absolute;
  display: block;
  height: calc(100% + 1em);
  width: 0px;
  top: -0.5em;
  bottom: -0.5em;
  left: -2em;
  border-left: 1px red dashed;
  z-index: -1;
}

li:first-child:after {
  top: 50%;
}

li:last-child:after {
  bottom: 50%;
}

li:first-child:after,
li:last-child:after {
  height: calc(50% + 0.5em);
} 
<ul>
  <li>
    <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Molestiae repudiandae minima, eligendi vero et eveniet magni sit facilis, dolores tempora cumque, atque deleniti dolore hic in architecto ducimus earum explicabo?</p>
  </li>
  <li>
    <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Molestiae repudiandae minima, eligendi vero et eveniet magni sit facilis, dolores tempora cumque, atque deleniti dolore hic in architecto ducimus earum explicabo?</p>
  </li>
  <li>
    <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Molestiae repudiandae minima, eligendi vero et eveniet magni sit facilis, dolores tempora cumque, atque deleniti dolore hic in architecto ducimus earum explicabo?</p>
    <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Molestiae repudiandae minima, eligendi vero et eveniet magni sit facilis, dolores tempora cumque, atque deleniti dolore hic in architecto ducimus earum explicabo?</p>
       <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Molestiae repudiandae minima, eligendi vero et eveniet magni sit facilis, dolores tempora cumque, atque deleniti dolore hic in architecto ducimus earum explicabo?</p> 
  </li>
  <li>
    <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Molestiae repudiandae minima, eligendi vero et eveniet magni sit facilis, dolores tempora cumque, atque deleniti dolore hic in architecto ducimus earum explicabo?</p>
  </li>  
</ul>

  • First, I create a before pseudo element for every li. This pseudo element is used to create the horizontal line. I've use a border to create the dashed effect, but you could use a linear gradiant or anything else.
  • Then, I create a after pseudo element for every li. This pseudo element is used to create the vertical line. You need to adapt the height of the first and last ones.

Edit:

In the exemple, the margin between the li is 1em.
This 1em value is also used here:

li:after {
  top: -0.5em; // <-- 1em / 2
  bottom: -0.5em; // <-- 1em / 2
}

li:first-child:after,
li:last-child:after {
  height: calc(50% + 0.5em); // <-- calc(50% - 1em / 2)
}

If you change the margin between the li, you should update those values accordingly.
As yo'ure using sass, juste use a variable and you'll be good.

Upvotes: 6

Ken
Ken

Reputation: 663

Your desired output is similar to a flowchart. With this analogy you can use an ordered list <ol> as the wrapper containing the lines. Then apply a margin to each <li>. Finally, wrap the box content in a <p> and style it to look like a box.

Here's a quick example where each box has a different height. You only need to adjust it according to your needs.

/* RESET STYLES & HELPER CLASSES
–––––––––––––––––––––––––––––––––––––––––––––––––– */

* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
}

ol {
  list-style: none;
}

body {
  padding: 24px;
}

.box {
  position: relative;
  padding: 24px;
  box-shadow: 0 5px 15px rgba(0, 0, 0, 0.15);
}


/* FLOWCHART
–––––––––––––––––––––––––––––––––––––––––––––––––– */

.wrapper {
  position: relative;
  width: 80%;
  margin-left: auto;
}

.wrapper::before {
  content: "";
  position: absolute;
  left: -20px;
  height: calc(100%);
  border: 1px dashed;
  );
}

.wrapper li+li {
  margin-top: 20px;
}

.box-content {
  font-weight: normal;
  background: yellow;
  border-radius: 8px;
}

.box-content::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 2px;
  transform: translate(-100%, -50%);
  width: 20px;
  border: 1px dashed;
  z-index: -1;
}
<ol class="wrapper">
  <li>
    <p class="box-content box">One line</p>
  </li>
  <li>
    <p class="box-content box">Two lines<br>Two lines</p>
  </li>
  <li>
    <p class="box-content box">Three lines<br>Three lines<br>Three lines</p>
  </li>
  <li>
    <p class="box-content box">Four lines<br>Four lines<br>Four lines<br>Four lines</p>
  </li>
</ol>

Upvotes: 0

Related Questions