Elements
Organizational chart
25 Apr 2023
"Організаційна схема"
- виконано на таблицях;
- адаптується при додаванні нових елементів;
- при переповненні додається скроллбар;
- скрипт центрує таблицю при наявності скроллбару та надає можливість свайпати курсором;
HTML
SCSS
JS
<div class="wrapper">
<ul class="tree">
<li>
<span>
<!-- any content -->
<div class="tree__card">
<div class="tree__logo">
<img src="https://images.unsplash.com/photo-1560937526-61078e7eb7d8?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=735&q=80"
alt="">
</div>
<div class="tree__col">
<p>Title</p>
<p>Descr</p>
</div>
</div>
<!-- end any content -->
</span>
<ul>
<li>
<span>
<!-- any content -->
<div class="tree__card">
<div class="tree__logo">
<img src="https://images.unsplash.com/photo-1560937526-61078e7eb7d8?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=735&q=80"
alt="">
</div>
<div class="tree__col">
<p>Title</p>
<p>Descr</p>
</div>
</div>
<!-- end any content -->
</span>
</li>
<li>
<span>
<!-- any content -->
<div class="tree__card">
<div class="tree__logo">
<img src="https://images.unsplash.com/photo-1560937526-61078e7eb7d8?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=735&q=80"
alt="">
</div>
<div class="tree__col">
<p>Title</p>
<p>Descr</p>
</div>
</div>
<!-- end any content -->
</span>
<ul>
<li>
<span>
<!-- any content -->
<div class="tree__card">
<div class="tree__logo">
<img src="https://images.unsplash.com/photo-1560937526-61078e7eb7d8?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=735&q=80"
alt="">
</div>
<div class="tree__col">
<p>Title</p>
<p>Descr</p>
</div>
</div>
<!-- end any content -->
</span>
</li>
<li>
<span>
<!-- any content -->
<div class="tree__card">
<div class="tree__logo">
<img src="https://images.unsplash.com/photo-1560937526-61078e7eb7d8?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=735&q=80"
alt="">
</div>
<div class="tree__col">
<p>Title</p>
<p>Descr</p>
</div>
</div>
<!-- end any content -->
</span>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
.wrapper {
overflow-y: hidden;
scrollbar-width: thin;
scrollbar-color: #ccc black;
&::-webkit-scrollbar {
height: 8px;
background-color: #ccc;
}
&::-webkit-scrollbar-thumb {
background-color: black;
}
}
.tree {
&, & ul, & li {
list-style: none;
margin: 0;
padding: 0;
position: relative;
}
text-align: center;
margin: 0 auto;
&, & ul {
display: table;
}
ul {
width: 100%;
}
li {
display: table-cell;
padding: 38px 0;
vertical-align: top;
&::before {
content: "";
left: 0;
position: absolute;
right: 0;
top: 0;
outline: solid 1px #666;
}
&:first-child {
&::before {
left: 50%;
}
}
&:last-child {
&::before {
right: 50%;
}
}
}
span {
display: inline-block;
margin: 0 .2em 38px;
position: relative;
}
ul, span {
&::before {
content: "";
position: absolute;
outline: solid 1px #707070;
left: 50%;
height: 38px;
top: -38px;
}
}
&>li {
margin-top: 0;
padding: 0;
&::before, &::after , &>span {
outline: none;
}
}
// any content
&__card {
position: relative;
display: flex;
align-items: center;
width: 300px;
padding: 12px 16px;
margin: 0 5px;
border: 2px solid black;
background-color: white;
box-shadow: 0 5px 8px rgba(0,0,0, 0.04);
}
&__logo {
flex: 0 0 auto;
margin-right: 20px;
width: 149px;
height: 76px;
padding: 17px;
border: 1px solid black;
img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
&__col {
p {
font-size: 20px;
line-height: 28px;
&:last-child {
font-size: 16px;
line-height: 22px;
color: black;
}
}
}
}
const structureWrap = document.querySelector('.wrapper')
structureWrap.scrollLeft = (structureWrap.scrollWidth - structureWrap.clientWidth) / 2
let isDown = false;
let startX;
let scrollLeft;
structureWrap.addEventListener('mousedown', (e) => {
isDown = true;
structureWrap.classList.add('active');
startX = e.pageX - structureWrap.offsetLeft;
scrollLeft = structureWrap.scrollLeft;
});
structureWrap.addEventListener('mouseleave', () => {
isDown = false;
structureWrap.classList.remove('active');
});
structureWrap.addEventListener('mouseup', () => {
isDown = false;
structureWrap.classList.remove('active');
});
structureWrap.addEventListener('mousemove', (e) => {
if(!isDown) return;
e.preventDefault();
const x = e.pageX - structureWrap.offsetLeft;
const walk = (x - startX) * 2;
structureWrap.scrollLeft = scrollLeft - walk;
});