使用纯HTML / CSS创建树图(多个父级)

时间:2018-04-13 03:59:50

标签: html css tree

我想创建一个包含多个父项的树形图。我们的想法是为Dota 2 Items创建一个图表,其中几个项目可以组成一个项目(加上一个食谱),和/或一个项目可以被分成几种可能性(多个父项目)。

enter image description here

我的一个参考来自thecodeplayer's code

到目前为止,jsfiddle上的my work

<div class="items">
  <ul>
    <li>
        <a href="#" class="">Dagon</a>
        <a href="#" class="">Veil of Discord</a>
        <a href="#" class="">Other Parent Item</a>
      <ul>
        <li>
          <a href="#">Null Talisman</a>
            <ul>
            <li><a href="#">Circlet</a></li>
            <li><a href="#">Mantle of Intelligence</a></li>
            <li><a href="#">Recipe: Null Talisman</a></li>
          </ul>
        </li>
      </ul>
    </li>
  </ul>
</div>

CSS

<style type="text/css">
* {
  margin: 0 auto;
  padding: 0;
  text-align: center;
  color: black;
  font-family: tahoma;
}

.items ul {
  padding-top: 20px;
  position: relative;
}

/* Make all children "inline" */
.items li {
  float: left;
  text-align: center;
  list-style-type: none;
  position: relative;
  padding: 20px 5px 0 5px;
}

/* Add horizontal connector. Note: they are 2 pseudo-elements */
.items li::before, .items li::after {
  content: '';
  position: absolute;
  top: 0;
  right: 50%;
  width: 50%;
  height: 45px;
  z-index: -1;
  border-top: 1px solid red;
}

.items li::after {
  border-left: 1px solid green;
  left: 50%;
  right: auto;
}

/* Remove left and right connector from a single child */
.items li:only-child::after, .items li:only-child::before {
  display: none;
}

.items li:only-child {
  padding-top: 0;
}

/* Remove "outer" connector */
.items li:first-child::before, .items li:last-child::after {
  border: 0 none;
}
/* Add back the down connector for last node */
.items li:last-child::before {
  border-right: 1px solid blue;
  border-radius: 0 5px 0 0;
}

/* Add curve line to the first child's connector */
.items li:first-child::after {
  border-radius: 5px 0 0 0;
}


/* Add down connector from parent */
.items ul ul::before {
  content: '';
  border-left: 1px solid magenta;
  z-index: -1;
  height: 20px;
  position: absolute;
  top: 0px;
  left: 50%;
  width: 0;
}

/* Add cosmetic for each item */
.items li a {
  font-size: 12px;
  background-color: white;
  border: 1px solid #ccc;
  padding: 5px 10px;
  text-decoration: none;
  display: inline-block;
  border-radius: 4px;
}

.items li a:hover {
  background-color: #EEE;
}

/* Experimental for multiple parents */
/* Add margin for the parents */
.items li a+a {
  position: relative;
  margin-bottom: 12px;
}
/* Implement also for the first parent */
.items li a:first-child {
  position: relative;
  margin-bottom: 12px;
}

/* 
- Add "down" connector (vertical line) from each parent 
- Currently it will also select the single parent
*/
.items li > a:not(:only-child)::after{
  content: '';
  position: absolute;
  border-right: 1px solid pink;
  top: 20px;
  height: 20px;
  width: 0;
  left: 50%;
  z-index: -1;
}

/* Starting to fvcked up from here */

/* Making the horizontal connector line after each multiple parent */
.items li > a:not(:only-of-type):not(:last-of-type)::before {
  content: '';
  position: absolute;
  top: 40px;
  left: auto;
  width: 100%;
  border-top: 1px solid indigo;
}

.items li > a:last-of-type:not(:first-child)::before {
  content: '';
  position: absolute;
  top: 40px;
  right: auto;
  width: 100%;
  border-top: 1px solid indigo;
}
</style>

我的尝试(失败或不够好)是创建另一个伪元素(:: before或:: after)<a>(多父)元素。

1 个答案:

答案 0 :(得分:2)

我建议您在最左侧和最右侧left伪类上将50%属性设置为::before,然后调整width最左边和中间的伪类来覆盖偏移量。

我还建议top向下增加2px向下连接器,以避免出现尖峰&#39;。

有点草率,但这是我的尝试:

&#13;
&#13;
* {
  margin: 0 auto;
  padding: 0;
  text-align: center;
  color: black;
  font-family: tahoma;
}

.items ul {
  padding-top: 20px;
  position: relative;
}


/* Make all children "inline" */

.items li {
  float: left;
  text-align: center;
  list-style-type: none;
  position: relative;
  padding: 20px 5px 0 5px;
}


/* Add horizontal connector. Note: they are 2 pseudo-elements */

.items li::before,
.items li::after {
  content: '';
  position: absolute;
  top: 0;
  right: 50%;
  width: 50%;
  height: 45px;
  z-index: -1;
  border-top: 1px solid red;
}

.items li::after {
  border-left: 1px solid green;
  left: 50%;
  right: auto;
}


/* Remove left and right connector from a single child */

.items li:only-child::after,
.items li:only-child::before {
  display: none;
}

.items li:only-child {
  padding-top: 0;
}


/* Remove "outer" connector */

.items li:first-child::before,
.items li:last-child::after {
  border: 0 none;
}


/* Add back the down connector for last node */

.items li:last-child::before {
  border-right: 1px solid blue;
  border-radius: 0 5px 0 0;
}


/* Add curve line to the first child's connector */

.items li:first-child::after {
  border-radius: 5px 0 0 0;
}


/* Add down connector from parent */

.items ul ul::before {
  content: '';
  border-left: 1px solid magenta;
  z-index: -1;
  height: 20px;
  position: absolute;
  top: 2px; /* Changed */
  left: 50%;
  width: 0;
}


/* Add cosmetic for each item */

.items li a {
  font-size: 12px;
  background-color: white;
  border: 1px solid #ccc;
  padding: 5px 10px;
  text-decoration: none;
  display: inline-block;
  border-radius: 4px;
}

.items li a:hover {
  background-color: #EEE;
}


/* Experimental for multiple parents */


/* Add margin for the parents */

.items li a+a {
  position: relative;
  margin-bottom: 12px;
}


/* Implement also for the first parent */

.items li a:first-child {
  position: relative;
  margin-bottom: 12px;
}


/* 
- Add "down" connector (vertical line) from each parent 
- Currently it will also select the single parent
*/

.items li>a:not(:only-child)::after {
  content: '';
  position: absolute;
  border-right: 1px solid pink;
  top: 20px;
  height: 20px;
  width: 0;
  left: 50%;
  z-index: -1;
}


/* Starting to fvcked up from here */


/* Making the horizontal connector line after each multiple parent */

.items li>a:not(:only-of-type):not(:last-of-type)::before {
  content: '';
  position: absolute;
  top: 40px;
  left: auto;
  width: 110%; /* Changed */
  border-top: 1px solid indigo;
}

.items li>a:last-of-type:not(:first-child)::before {
  content: '';
  position: absolute;
  top: 40px;
  right: auto;
  width: 42%; /* Changed */
  border-top: 1px solid indigo;
}


/* ADDED STYLES */
.items li>a:first-of-type:first-child::before {
  left: 50%;
}

.items li>a:last-of-type:last-child::before {
  left: 50%;
}
&#13;
<div class="items">
  <ul>
    <li>
      <a href="#" class="">Dagon</a>
      <a href="#" class="">Veil of Discord</a>
      <a href="#" class="">Other Parent Item</a>
      <ul>
        <li>
          <a href="#">Null Talisman</a>
          <ul>
            <li><a href="#">Circlet</a></li>
            <li><a href="#">Mantle of Intelligence</a></li>
            <li><a href="#">Recipe: Null Talisman</a></li>
          </ul>
        </li>
      </ul>
    </li>
  </ul>
</div>
&#13;
&#13;
&#13;