У меня есть система, которая генерирует список узлов, которые могут иметь или не иметь дополнительные элементы между узлами. Я хочу визуализировать этот список горизонтально с линиями, соединяющими узлы, как показано в примере ниже.
Содержимое между двумя узлами является переменным и может даже содержать более сложные элементы, такие как изображения и таблицы. Сами узлы помечаются только текстом (точка A, точка B и т. д.).
В моей первой попытке визуализировать узлы я просто использовал вертикальный список с псевдоэлементами :before и :after CSS, чтобы нарисовать линии между узлами. Однако мне трудно перевести этот подход в горизонтальный список.
Горизонтальный подход: (обновлено благодаря Ответ Маянка Гупты ниже)
h1, h2 {
margin: 0;
padding: 0;
}
ul {
display: flex;
flex-wrap: wrap;
justify-content: center;
align-items: center;
flex-direction: row;
text-align: center;
list-style-type: none;
font-size: 1.5em;
}
ul li {
display: flex;
justify-content: flex-start;
flex: 2;
position: relative;
border-bottom: 2px solid #000;
padding-bottom: 10px;
}
ul li:after {
position: absolute;
bottom: -5px;
left: 0;
font-family: "Font Awesome 5 Free";
font-weight: 300;
content: "\f111";
height: 17px;
width: 23px;
background: #fff;
}
ul h2 {
margin: 0 0 0 -1em;
padding: 0;
}
ul li:last-of-type {
border: none;
}
ul li > div {
flex: 0 0 auto;
position: absolute;
left: 50%;
transform: translateX(-50%);
}<link href = "https://use.fontawesome.com/releases/v5.5.0/css/all.css" rel = "stylesheet"/>
<ul>
<li>
<h2>Node A</h2>
<div>Content</div>
</li>
<li>
<h2>Node B</h2>
<div>Content</div>
</li>
<li>
<h2>Node C</h2>
</li>
</ul>Проблемы с этим методом:
Как я могу решить эти проблемы?






Попробуйте этот код
h1, h2 {
margin: 0;
padding: 0;
}
ul {
display: flex;
align-items: center;
}
ul li {
position: relative;
width: 33%;
display: flex;
justify-content: center;
align-items: flex-start;
flex-direction: column;
border-bottom: 1px solid #ddd;
padding-bottom: 10px;
}
ul li:after {
position: absolute;
bottom: -10px;
left: 0;
font-family: "Font Awesome 5 Free";
font-weight: 300;
content: "\f111";
height: 17px;
width: 17px;
background: #fff;
}<link href = "https://use.fontawesome.com/releases/v5.5.0/css/all.css" rel = "stylesheet"/>
<ul>
<li>
<h2>Node A</h2>
<div>Content</div>
</li>
<li>
<h2>Node B</h2>
<div>Content</div>
</li>
<li>
<h2>Node C</h2>
<div>Content</div>
</li>
</ul>Это несколько отвечает на ваш вопрос [*] [* = однако я написал большую часть этого кода до того, как прочитал ваше первое изображение, не увидев содержимое h2/div].
Основная часть ответа — это HTML/CSS, но есть небольшой фрагмент javascript, чтобы сделать класс li [узлов до выбранной точки] активным.
Запустите фрагмент и щелкните по элементам узла по очереди, чтобы увидеть рисуемые линии.
Обновлено: Re. ваши вопросы:
Что касается последнего узла, вы можете задать ему другую ширину, удалить ширину границы/поля/отступы или отобразить: нет. Если вы используете селектор :последний ребенок, вы можете присвоить последнему элементу различные значения свойств по мере необходимости, используя CSS.
Что касается разных шрифтов/смещений, я бы сказал, что то же самое верно и для большей части кода, использующего разные шрифты. Старайтесь последовательно использовать один шрифт (в данном случае я считаю это лучшей практикой). Что касается смещения, если это различные размеры изображения, которые в основном вызывают его смещение, попробуйте использовать фиксированную ширину с
object-fit (содержание/уменьшение должно отображаться лучше для вас) Вы можете установить переполнение для div, и не забудьте wrap
Центрирование меток: вы пробовали просто добавить text-align: center;? Не уверен, что предложить относительно отрицательного смещения, так как это зависит/относительно других css. Нужно будет увидеть полный макет css/html.
Ре. потенциально перекрывающиеся элементы div: установите max-width для вашего контента и overflow/overflow-y, если это необходимо.
Надеюсь это поможет!
var nodelist1 = document.getElementById("connect");
var mynodes = nodelist1.getElementsByTagName("li");
for (var i = 0; i < mynodes.length; i++) {
mynodes[i].addEventListener("click", function() {
var currNode = document.getElementsByClassName("active");
currNode[0].className = currNode[0].className.replace("active", "");
this.className += "active";
});
}body {
font-family: "Font Awesome 5 Free";
/* padding: 2em;*/
}
#connect {
font-weight: 300;
content: "\f111";
}
h1,
h2 {
margin: 0;
padding: 0;
}
li {
vertical-align: middle;
display: inline-block;
position: relative;
color: white;
width: 4em;
height: 4em;
text-align: center;
margin: 0em .8em;
line-height: 4em;
border-radius: 1em;
background: navy;
}
li::before {
content: '';
position: absolute;
top: 2em;
left: -3em;
min-width: 4em;
/*width of connecting line*/
height: .2em;
background: maroon;
z-index: -1;
}
li:first-child::before {
display: none;
/*at pos 1, other nodes are 'disabled' line is light blue*/
}
.active {
background: navy;
}
.active~li {
background: lightgray;
}
.active~li::before {
background: lightblue;
}
.content {
display: none;
width: 5em;
max-height: 6em;
overflow-y: scroll;
overflow-x: none;
line-height: 1em;
color: red;
padding: 0;
margin: 0;
}
.active .content {
display: block;
}<link href = "https://use.fontawesome.com/releases/v5.5.0/css/all.css" rel = "stylesheet" />
<ul id = "connect">
<li>1</li>
<li class = "active">2</li>
<li>
<h2>Node A</h2>
<div class = "content">Manuel: hello how are you I speak English I learn it from a book</div>
</li>
<li>4</li>
<li>5</li>
</ul>Привет, спасибо за ваш вклад! Я смог немного приблизиться к своей цели, но, к сожалению, не без проблем. Я обновил свой вопрос выше новым кодом и проблемами, перечисленными ниже. Возможно, у вас есть идея, как я могу справиться с ними?
Вот мой ответ: по сути, вы добавляете display:flex в список ul и убедитесь, что узлы имеют фиксированный размер, используя flex:0 0 auto и фиксированную ширину. Это позволит контексту между быть переменным по размеру.
Что касается соединения узлов, хотя это можно сделать с помощью псевдоэлементов :before и :after, есть более простой способ сделать это; просто используйте псевдоэлемент для всего списка (элемент ul), который идет бок о бок по ширине элемента (в примере на самом деле left и right имеют значение 30 пикселей, чтобы компенсировать произвольное боковое заполнение, которое я установил) .
HTML:
<ul>
<li class = "node"><label>Point A</label></li>
<li class = "context"><span>Content here Content here Content here</span></li>
<li class = "node"><label>Point B</label></li>
<li class = "context"><span>Content here</span></li>
<li class = "node"><label>Point C</label></li>
</ul>
CSS:
ul {
list-style-type: none;
display: flex;
width: 100%;
margin: 50px 0 0 0;
padding: 0 30px;
position: relative;
}
ul:before {
content: "";
display: block;
position: absolute;
left: 30px;
right: 30px;
top: 50%;
margin-top: -1px;
height: 2px;
background: steelblue;
}
.node {
flex: 0 0 auto;
display: block;
width: 12px;
height: 12px;
border-radius: 12px;
border: 2px solid steelblue;
position: relative;
background: #fff;
}
.node label {
position: absolute;
top: -30px;
left: 50%;
transform: translateX(-50%);
white-space: nowrap;
}
.context {
flex: 1 1 auto;
}
.context span {
display: block;
margin-top: -15px;
text-align: center;
}
Вот рабочая рабочий пример: https://jsfiddle.net/8ksxtz60/
Кажется, это делает то, что я хотел, спасибо! Сила гибкости до сих пор меня поражает.
@Thomas представьте себе возможности сетки. Рад, что смог помочь
Привет, спасибо за ваш вклад! Это помогло мне приблизиться к моей цели, однако теперь я столкнулся с рядом новых проблем. Я обновил свой вопрос выше, у вас есть идеи, как их решить?