Reputation: 518
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.
I'm actually using SCSS, and React (I'm printing the "row" div 4 times)
<div class="wrapper">
<div class="row">
<div class="bordered-div"></div>
<div class="step">
<img src="placeholder.svg" alt="img" />
<div class="step-text">
<div class="step-title">Title</div>
<div class="step-description">Decsription...</div>
</div>
</div>
</div>
</div>
.wrapper {
display: flex;
flex-direction: column;
align-items: center;
gap: 30px;
.row {
display: flex;
position: relative;
&:last-child {
.bordered-div {
height: 0;
}
}
.bordered-div {
position: absolute;
top: 50%;
left: -50px;
width: 50px;
border-top: 1px dashed #c2c9d5;
border-left: 1px dashed #c2c9d5;
height: calc(100% + 30px);
}
.step {
background: blue;
min-height: 118px;
width: 322px;
padding: 20px;
border-radius: 8px;
display: flex;
gap: 20px;
filter: drop-shadow(0px 0px 4px rgba(183, 183, 183, 0.15))
drop-shadow(0px 4px 4px rgba(217, 217, 217, 0.25));
svg {
width: 16px;
align-self: center;
flex: none;
}
.step-title {
font-size: 0.875rem;
font-weight: 600;
}
.step-description {
font-size: 0.875rem;
}
}
}
}
Upvotes: 6
Views: 1683
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>
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.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
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