Creé algo como esto usando CSS.
Lo complicado aquí es que la altura de los cuadros puede cambiar si el texto es demasiado largo.
Entonces, no sé cómo hacer que las líneas discontinuas siempre se comporten de esta manera, porque el tamaño de los cuadros es dinámico.
(Siempre debe haber una línea desde el medio del primer cuadro hasta el medio del siguiente cuadro)
Este es el HTML y CSS que estoy usando ahora.
De hecho, estoy usando SCSS y React (estoy imprimiendo el div de "fila" 4 veces)
<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; } } } }Aquí hay una prueba de concepto rápida con un marcado mínimo.
Creo que no necesitas ningún div vacío extra.
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 para cada li . Este pseudo elemento se utiliza para crear la línea horizontal. He usado un borde para crear el efecto discontinuo, pero podrías usar un degradado lineal o cualquier otra cosa.after para cada li . Este pseudo elemento se utiliza para crear la línea vertical. Necesitas adaptar la altura del primero y del último.Editar:
En el ejemplo, el margen entre li es 1em .
Este valor 1em también se usa aquí:
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) } Si cambia el margen entre li , debe actualizar esos valores en consecuencia.
Como estás usando sass, solo usa una variable y estarás bien.
Su salida deseada es similar a un diagrama de flujo. Con esta analogía, puede usar una lista ordenada <ol> como contenedor que contiene las líneas. Luego aplique un margen a cada <li> . Finalmente, envuelve el contenido del cuadro en un <p> y dale estilo para que parezca un cuadro.
Aquí hay un ejemplo rápido donde cada caja tiene una altura diferente. Solo necesita ajustarlo de acuerdo a sus necesidades.
/* 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>