动态水平列表,节点之间具有可变宽度的线和内容

时间:2019-07-06 15:08:44

标签: html css alignment

我有一个系统,该系统生成节点列表,这些节点之间可能有也可能没有其他元素。我想用连接节点的线水平显示此列表,如下例所示。

两个节点之间的内容是可变的,甚至可以包含图像和表格等更复杂的元素。节点本身仅被标记为文本(点A,点B等)。

Fig 1

代码和到目前为止我已经尝试过的

在尝试可视化节点的第一次尝试中,我仅使用带有:before:after CSS伪元素的垂直列表来绘制节点之间的线。但是,我很难将这种方法转换为水平列表。

水平方法:(由于下面的Mayank Gupta's answer而更新)

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>

此方法存在问题:

  • 所有节点的宽度相等,导致最后一个节点不必要地占用空间(最后一个节点永远不会显示任何内容),实际上,这阻止了列表使用所有可用的水平空间(或至少在表面上);
  • 该行对字体大小更改敏感,导致其未对齐;
  • 节点标签使用负偏移居中,这可能不是最佳方法;
  • 将内容div从文档流中取出以使其在节点之间居中,这可能使它与节点标签重叠(在本示例中就是这种情况)

我该如何解决这些问题?

约束

  • 我仅支持最新版本的现代浏览器,因此不需要与旧版浏览器兼容;
  • 我更喜欢仅使用HTML(5)和CSS的方法

3 个答案:

答案 0 :(得分:1)

这是我的答案-本质上,您将display:flex添加到ul列表中,并通过使用flex:0 0 auto和固定宽度来确保节点具有固定大小。这样可以使上下文之间的大小可变。

关于节点的连接,尽管可以使用:before:after伪元素来完成,但是有一种更简单的方法;只需对沿元素宽度并排的整个列表(ul元素)使用伪元素(在示例中,实际上leftright具有一个值30px来补偿我设置的任意边距。

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/

答案 1 :(得分:0)

尝试此代码

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>

答案 2 :(得分:0)

这在某种程度上回答了您的问题[*] [* =但是,在我看到您的第一张图片而不看h2 / div内容之前,我已经编写了大部分代码。

答案大部分是HTML / CSS,但是有少量的javascript可以将li类(直到选定点的节点)设置为有效。

运行该代码段,然后依次单击节点项以查看正在绘制的线。

编辑:重新。您的问题:

关于最后一个节点,您可以选择给它一个不同的宽度,删除border-width / margin / padding或display:none。如果使用:last-child选择器,则可以使用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>