Pure css tree with borders
Simple with Multi-level Depth Support
UPDATED: Tweaked to accommodate hover
No extra HTML needed, no having to limit depth because of css selector chaining, as it supports any number of levels deep without having to adjust your css at all for those levels (no keeping track of "padding" to set on the next level deep).
This works well with only a two minor limitations (which I don't believe will factor into affecting you).
See fiddle demo.
Add a position: relative
to your ul.tree
, but keep all the child elements the default static
position. Then change/add the following css:
ul.tree a {
display: block;
height:30px;
line-height: 30px;
padding-left: 15px;
}
/* this is making our bottom border, but sizing off the .tree ul width */
ul.tree a:before {
content: '';
height: 30px; /* match your <a> height */
position: absolute;
left: 0;
right: 0;
z-index: -1;
border-bottom-width: 1px;
border-bottom-color: lightgray;
border-bottom-style: solid;
}
ul.tree a + ul {
padding-left: 15px; /* this is your spacing for each level */
}
ul.tree a:hover:before {
background-color: #DDDDDD;
}
The limitations are that no child elements can have a position set and we are using a pseudo-element (which means it cannot be used for some other feature, but that is probably not an issue either).
Is it possible to make a pure CSS Tree diagram?
Try the code below, it's pure CSS and no JS/jQuery (which IMO is way more compatible), works by manipulating borders and spacing.
Works on FF/Chrome & IE. Enjoy :-)
.parent a,
li {
font-size: 22px;
color: #000;
font-family: "Source Sans Pro", sans-serif;
}
.child a,
li {
font-size: 18px;
color: #000;
}
.subchild a,
li {
font-size: 18px;
color: #888888;
}
.s2child a,
li {
font-size: 16px;
color: #ccc;
}
.tree,
.tree ul {
list-style-type: none;
margin-left: 0 0 0 10px;
padding: 0;
position: relative;
overflow: hidden;
}
.tree li {
margin: 0 0 0 15px;
padding: 0 12px 0 20px;
position: relative;
}
.tree li::before,
.tree li::after {
content: '';
position: absolute;
left: 0;
}
/* horizontal line on inner list items */
.tree li::before {
border-top: 2px solid #000;
top: 14px;
width: 15px;
height: 0;
}
/* vertical line on list items */
.tree li:after {
border-left: 2px solid #000;
height: 100%;
width: 0px;
top: -5px;
}
/* lower line on list items from the first level because they don't have parents */
.tree > li::after {
top: 15px;
}
/* hide line from the last of the first level list items */
.tree > li:last-child::after {
display: none;
}
/* hide line from before the Home or starting page or first element */
.tree > li:first-child::before {
display: none;
}
.tree ul:last-child li:last-child:after {
height: 20px;
}
.tree a:hover {
color: red;
font-weight: 500;
text-shadow: 1px 2px 2px #F3F3F3;
}
<!doctype html><html>
<head> <meta charset="utf-8"> <title>Pure CSS Tree</title> <link href="tree.css" rel="stylesheet" type="text/css"></head>
<body> <ul class="tree"> <li class="parent"><a href="#">Grand Parent</a> <ul> <li class="child"><a href="#">Parent</a> </li> <li class="child"><a href="#">Parent</a> <ul> <li class="subchild"><a href="#">Child</a> <ul> <li class="s2child"><a href="#">Grand Child</a> </li> <li class="s2child"><a href="#">Grand Child</a> </li> <li class="s2child"><a href="#">Grand Child</a> </li> <li class="s2child"><a href="#">Grand Child</a> </li> <li class="last s2child"><a href="#">Grand Child</a> </li> </ul> </li> <li class="subchild"><a href="#">Child</a> <ul> <li class="s2child"><a href="#">Grand Child</a> </li> <li class="s2child"><a href="#">Grand Child</a> </li> </ul> </li> </ul> </li> <li class="child"><a href="#">Parent</a> </li> </ul> </li> </ul>
</body>
</html>
Family tree hierarchy with Pure CSS using divs
First, try using more semantic tags, in the example <main>
, <section>
, <figure>
, and <figcaption>
were used instead of <div>
and <span>
. It doesn't make the HTML invalid if you only use <div>
and <span>
but it'll hold less meaning and there's a greater chance of errors being overlooked.
display: table/table-row/table-cell
was assigned to <main>/<section>/<figure>
respectively. Using <table>
for layout is highly discouraged, but using other tags that behave like a <table>
is ok. In the example, the table-like layout is 3 rows (one row for each generation) and 5 columns. The only borders that are visible are actually the lines that connect "leaves" to each other (as spouses or siblings). For demonstration purposes I added a little JavaScript -- just click anywhere to toggle the invisible borders off and on.
Further details are commented in the example below
<!DOCTYPE html>
<html>
<head>
<title>Family Tree</title>
<link rel="shortcut icon" href="./img/family-tree.png" type="image/x-icon">
<link rel="stylesheet" type="text/css" href="./css/style.css">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=My+Soul&family=Sacramento&display=swap" rel="stylesheet">
<style>
* {
margin: 0;
padding: 0;
}
/*
Default font-size is referenced here
Any rem used elsewhere will be directly referenced to this font-size
Default is dynamic -- whenever window is resized, it will adjust to width
if it is bigger than height and vice versa.
In turn, anything in rem will also adjust 2.5vmax === 1rem
*/
html {
font: 2.5vmax/1.5 Sacramento;
}
body {
padding-bottom: 12px;
}
/*
As a <table>, main will adhere to what each column is in width. this
behavior allows it to scale to the width of viewport (window).
*/
main {
display: table;
table-layout: fixed;
width: 100%;
background: transparent;
}
h1 {
display: table-caption;
margin: 10px auto;
padding-top: 10px;
font-family: 'My Soul';
font-size: 2.6rem;
text-align: center;
}
/*
As a <tr>, it automatically holds it's children in a solid row
*/
section {
display: table-row;
background: transparent;
}
/*
As a <td>, padding, vertical-align, width, etc are handled so each one is
uniformly the same height and content is evenly positioned.
*/
figure,
.cell {
display: table-cell;
width: 20%;
background: transparent;
}
img {
width: 7.5em;
height: 7.5rem;
border: solid 3px #606f46;
border-radius: 100%;
box-shadow: 4px 4px 13px #222;
}
figcaption {
width: min-content;
margin-top: -5px;
padding: 10px;
border-style: solid;
border-color: #606f46;
border-radius: 30px 0 30px 0;
background: #beebb3;
box-shadow: 4px 4px 13px #222;
text-align: center;
}
/*
These tags act as empty cells and are placed in-between each "leaf". The majority
of the lines are from their visible borders.
*/
.cell b {
display: block;
position: relative;
z-index: -1;
min-height: 4rem;
}
/*
Applied to .cell between parents -- it connects them
*/
.parents b {
border-top: 6px solid black;
}
/*
Applied to .cell between parents -- it adds a descendant line
*/
.parents b::before {
content: '';
display: block;
position: absolute;
left: 45%;
width: 1px;
height: 8.25rem;
border: 3px solid black;
background: black;
}
/*
Applied to .cell between siblings and the <figure> of any middle children
-- it connects them
*/
.siblings {
border-top: 6px solid black;
}
/*
Applied to .cell to the right of the oldest child and to the left of the
youngest child
*/
.elder,
.baby {
position: relative;
}
/*
Applied to .cell to the right of the oldest child and adds an arrow
*/
.elder::before {
content: '\002b9f';
position: absolute;
left: -1rem;
top: -1.5rem;
font-size: 2rem;
transform: rotate(45deg);
}
/*
Applied to the .cell to the left of the youngest child and adds an arrow
*/
.baby::after {
content: '\002b9f';
position: absolute;
right: -1rem;
top: -1.5rem;
font-size: 2rem;
transform: rotate(-45deg);
}
/*
For demonstration purposes
Styles showLayout(e) toggles on every click (optional)
*/
.show .cell b {
outline: 3px dotted rgba(255, 0, 50, 0.6);
}
.show .cell {
outline: 2px dashed rgba(129, 129, 129, 0.4);
}
</style>
</head>
<body>
<main>
<h1>___Simpson Family Tree___</h1>
<section>
<div class='cell'><b></b></div>
<figure>
<img src="https://i.pinimg.com/originals/e5/4a/bc/e54abc44b68d6b2770696b789b20dafa.png">
<figcaption>Abraham Simpson</figcaption>
</figure>
<div class='cell parents'><b></b></div>
<figure>
<img src='https://comicvine.gamespot.com/a/uploads/square_tiny/11/111746/6556151-mona_simpson.png'>
<figcaption>Mona Simpson</figcaption>
</figure>
<div class='cell'><b></b></div>
</section>
<section>
<div class='cell'><b></b></div>
<div class='cell'><b></b></div>
<figure>
<img src="https://entertainment.time.com/wp-content/uploads/sites/3/2013/05/fictioninfluence_list_homersimpson.jpg">
<figcaption> Homer Simpson </figcaption>
</figure>
<div class='cell parents'><b></b></div>
<figure>
<img src="https://static.wikia.nocookie.net/theultimatesimpsons/images/0/0f/Marge-Simpson-icon.png">
<figcaption>Marge Simpson</figcaption>
</figure>
</section>
<section>
<figure>
<img src="https://openpsychometrics.org/tests/characters/test-resources/pics/S/2.jpg">
<figcaption>Bart Simpson</figcaption>
</figure>
<div class='cell siblings elder'><b></b></div>
<figure class='siblings'>
<img src="https://mella187.github.io/Cartoon-Hero/img/lisa-avatar.jpg">
<figcaption>Lisa Simpson</figcaption>
</figure>
<div class='cell siblings baby'><b></b></div>
<figure>
<img src="https://icons.iconarchive.com/icons/jonathan-rey/simpsons/256/Maggie-Simpson-icon.png">
<figcaption>Maggie Simpson</figcaption>
</figure>
</section>
</main>
<script>
/*
For demonstration purposes - it exposes the borders (optional)
*/
document.querySelector('main').onclick = showLayout;
function showLayout(e) {
this.classList.toggle('show');
}
</script>
</body>
</html>
CSS Vertical line for tree menu
try to add to your CSS
li:last-child {
height: 1px;
}
check demo http://jsbin.com/tigepavemi/1/edit?html,css,output
Related Topics
CSS Selection Color Behaving Strangely on Chrome
CSS Font-Face with the Arabic Fonts
Css3 Flexbox Compatibility Problems with Firefox and Safari
Jquery Mobile Textarea: How Does It Use 'Rows' Attribute
How to Prevent Hidden Element to Be Shown When Focused in Chrome
Css: Semi-Transparent Background and an Image
Bootstrap 4 Multiple Fixed Navbars with Animated Shrink
Edit Microsoft Chatbot UI Design
Vertically Center Responsive Iframe
Why Doesn't This Radial-Gradient Complete the Circle
How to Create a Dynamic Grid Using Vue