I'm trying to build a family tree with HTML and CSS. I found a good example on codepen.
As a family is not a simple node hierarchy, but sometimes rather complex relations, I need to have multiple nodes that almost act as one. But let's start with not the most complex example, taking my family as an example, starting with my grand mother from the mother side as the root:
- There is my father who is the ex-husband of my mother
- My mother married again, thus I have a step father
So the base node from above is my mother, but me and my sister should be placed below my father as we are not related to the step father. I tried to picture this here:

Here is my markup and css (based on the codepen example above):
/* Person */
.person {
border: 1px solid black;
padding: 10px;
min-width: 150px;
background-color: #FFFFFF;
display: inline-block;
}
.person.female {
border-color: #F45B69;
}
.person.male {
border-color: #456990;
}
.person div {
text-align: center;
}
.person .name {
font-size: 16px;
}
.person .parentDrop, .person .spouseDrop, .person .childDrop {
border: 1px dashed #000000;
width: auto;
min-width: 80px;
min-height: 80px;
display: inline-block;
vertical-align: top;
position: relative;
padding-top: 15px;
}
.person .parentDrop>span,
.person .spouseDrop>span,
.person .childDrop>span {
position: absolute;
top: 2px;
left: 2px;
font-weight: bold;
}
.parentDrop>.person,
.spouseDrop>.person,
.childDrop>.person {
margin-top: 20px;
}
/* Tree */
.tree ul {
padding-top: 20px;
position: relative;
transition: all 0.5s;
-webkit-transition: all 0.5s;
-moz-transition: all 0.5s;
}
.tree li {
display: table-cell;
text-align: center;
list-style-type: none;
position: relative;
padding: 20px 5px 0 5px;
transition: all 0.5s;
-webkit-transition: all 0.5s;
-moz-transition: all 0.5s;
}
/*We will use ::before and ::after to draw the connectors*/
.tree li::before, .tree li::after {
content: '';
position: absolute;
top: 0;
right: 50%;
border-top: 1px solid #ccc;
width: 50%;
height: 20px;
}
.tree li::after {
right: auto;
left: 50%;
border-left: 1px solid #ccc;
}
/*We need to remove left-right connectors from elements without
any siblings*/
.tree li:only-child::after, .tree li:only-child::before {
display: none;
}
/*Remove space from the top of single children*/
.tree li:only-child {
padding-top: 0;
}
/*Remove left connector from first child and
right connector from last child*/
.tree li:first-child::before, .tree li:last-child::after {
border: 0 none;
}
/*Adding back the vertical connector to the last nodes*/
.tree li:last-child::before {
border-right: 1px solid #ccc;
border-radius: 0 5px 0 0;
-webkit-border-radius: 0 5px 0 0;
-moz-border-radius: 0 5px 0 0;
}
.tree li:first-child::after {
border-radius: 5px 0 0 0;
-webkit-border-radius: 5px 0 0 0;
-moz-border-radius: 5px 0 0 0;
}
/*Time to add downward connectors from parents*/
.tree ul ul::before {
content: '';
position: absolute;
top: 0;
left: 50%;
border-left: 1px solid #ccc;
width: 0;
height: 20px;
}
.tree li .parent {
transition: all 0.5s;
-webkit-transition: all 0.5s;
-moz-transition: all 0.5s;
margin-top: 10px;
}
.tree li .parent::before {
content: '';
position: absolute;
top: 40px;
left: 50%;
border-left: 1px solid #ccc;
border-right: 1px solid #ccc;
width: 3px;
height: 10px;
}
.tree li .family {
position: relative;
}
.tree li .family .spouse {
position: absolute;
top: 0;
left: 50%;
margin-left: 95px;
}
.tree li .family .spouse::before {
content: '';
position: absolute;
top: 50%;
left: -10px;
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
width: 10px;
height: 3px;
}
/*Time for some hover effects*/
/*We will apply the hover effect the the lineage of the element also*/
.tree li .child:hover,
.tree li .child:hover+.parent .person,
.tree li .parent .person:hover,
.tree li .child:hover+.parent .person+ul li .child,
.tree li .parent .person:hover+ul li .child,
.tree li .child:hover+.parent .person+ul li .parent .person,
.tree li .parent .person:hover+ul li .parent .person {
background: #c8e4f8;
color: #000;
border: 1px solid #94a0b4;
}
/*Connector styles on hover*/
.tree li .child:hover+.parent::before,
.tree li .child:hover+.parent .person+ul li::after,
.tree li .parent .person:hover+ul li::after,
.tree li .child:hover+.parent .person+ul li::before,
.tree li .parent .person:hover+ul li::before,
.tree li .child:hover+.parent .person+ul::before,
.tree li .parent .person:hover+ul::before,
.tree li .child:hover+.parent .person+ul ul::before,
.tree li .parent .person:hover+ul ul::before {
border-color: #94a0b4;
}
<div class="tree">
<ul>
<li>
<div class="family">
<div class="person child male">
<div class="name">Grandfather</div>
</div>
<div class="parent">
<div class="person female">
<div class="name">Grandmother</div>
</div>
<ul>
<li>
<div class="family" style="width: 172px">
<div class="person child male">
<div class="name">Uncle</div>
</div>
<div class="parent">
<div class="person female">
<div class="name">Wife of Uncle</div>
</div>
</div>
</div>
</li>
<li>
<div class="family" style="width: 172px">
<div class="person child female">
<div class="name">Aunt</div>
</div>
<div class="parent">
<div class="person male">
<div class="name">Husband of Aunt</div>
</div>
</div>
</div>
</li>
<li>
<div class="family" style="width: 344px">
<div class="person child female">
<div class="name">Mother</div>
</div>
<div class="parent">
<div class="person male">
<div class="name">Father</div>
</div>
<ul>
<li>
<div class="person child male">
<div class="name">Me</div>
</div>
</li>
<li>
<div class="person child female">
<div class="name">Sister</div>
</div>
</li>
</ul>
</div>
<div class="person spouse male">
<div class="name">Spouse</div>
</div>
</div>
</li>
</ul>
</div>
</div>
</li>
</ul>
</div>
EDIT: I found a solution, whereas I calculate the nodes shown next to each other in the backend and write some style attributes with widths to a newly introduced div. It is still not perfect, so if someone has improvements, post a comment or answer.



.persondivs within the structure and also the.parentwith the children, so the lines depart from that node... So, any markup and CSS changes that could make this work are welcome.