Reputation: 1341
I want to create a tree diagram with multiple parents. The idea is to create a diagram for Dota 2 Items, which several items can be made into one single item (plus a recipe), AND/OR one item can be made into several possibilities (more than one parent item).
One of my reference is from thecodeplayer's code.
Here is my work on jsfiddle so far.
<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>
My attempts (which failed, or is not nice enough) is to create another pseudo-element (::before or ::after) the <a>
(multiple parent) element.
Upvotes: 4
Views: 12505
Reputation: 42304
What I would recommend doing is setting the left
property to 50%
on the left-most and right-most ::before
pseudo-classes, and then adjusting the width
of the left-most and middle pseudo-classes to cover the offset.
I'd also recommend increasing the top
of the downwards connectors by 2px
just to avoid spiky 'overhangs'.
A bit sloppy, but here's my attempt:
* {
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%;
}
<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>
Upvotes: 4