Skip to content

Instantly share code, notes, and snippets.

@ericoutinho
Created April 30, 2023 22:54
Show Gist options
  • Select an option

  • Save ericoutinho/18063baa29e8146b3de58d21dbb52c5c to your computer and use it in GitHub Desktop.

Select an option

Save ericoutinho/18063baa29e8146b3de58d21dbb52c5c to your computer and use it in GitHub Desktop.
Draggable tabs in Vanilla JS
<!DOCTYPE html>
<html lang="pt-br">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Dragging tabs</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" integrity="sha512-iecdLmaskl7CVkqkXNQ/ZH/XLlvWZOJyj7Yy7tcenmpD1ypASozpmT/E0iPtmFIB46ZmdtAc9eNBvH0H/ZpiBw==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<link rel="stylesheet" href="./styles" />
</head>
<body>
<div class="wrapper">
<button class="tab-button" id="left"><i class="fa-solid fa-chevron-left"></i></button>
<ul class="tab-box">
<li class="tab">Home</li>
<li class="tab">About</li>
<li class="tab">Contact</li>
<li class="tab">Services</li>
<li class="tab">Prices</li>
<li class="tab">Products</li>
<li class="tab">Documents</li>
<li class="tab">Profile</li>
<li class="tab">Settings</li>
<li class="tab">Users</li>
<li class="tab">Extras</li>
<li class="tab">Contact</li>
<li class="tab">Services</li>
<li class="tab">Prices</li>
</ul>
<button class="tab-button" id="right"><i class="fa-solid fa-chevron-right"></i></button>
</div>
<script src="./scripts.js"></script>
</body>
</html>
"use strict"
let isDragging = false
const tabBox = document.querySelector(".tab-box")
const tabButton = document.querySelectorAll(".tab-button")
const buttonHandle = (scrollWidth) => {
let maxScrollableWidth = tabBox.scrollWidth - tabBox.clientWidth;
tabButton[0].style.visibility = scrollWidth <= 0 ? "hidden" : "visible"
tabButton[1].style.visibility = ((maxScrollableWidth - scrollWidth) <= 1) ? "hidden" : "visible"
}
tabButton.forEach( (button) => {
button.addEventListener("click", (event) => {
let scrollWidth = tabBox.scrollLeft += (button.id === "left") ? -200 : 200
buttonHandle(scrollWidth)
})
})
const dragStart = (event) => {
isDragging = true
}
const dragStop = () => {
tabBox.classList.remove("in-dragging")
isDragging = false
}
const dragMove = (event) => {
if (!isDragging) return
tabBox.classList.add("in-dragging")
tabBox.scrollLeft -= event.movementX
buttonHandle(tabBox.scrollLeft)
}
tabBox.addEventListener("mousedown", dragStart)
tabBox.addEventListener("mousemove", dragMove)
document.addEventListener("mouseup", dragStop)
*
{
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: system-ui, sans-serif;
}
body
{
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
.wrapper
{
display: flex;
gap: 10px;
flex-wrap: nowrap;
max-width: 450px;
}
.tab-button
{
border: none;
background: transparent;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
}
.tab-box
{
scroll-behavior: smooth;
/* scroll-snap-type: x mandatory; */
list-style: none;
overflow-x: scroll;
display: flex;
flex-wrap: nowrap;
gap: 10px;
}
.tab-box::-webkit-scrollbar
{
width: 0;
height: 0;
}
.tab-box::-webkit-scrollbar-track {
display: none;
}
.tab-box.in-dragging
{
/* scroll-snap-type: none; */
scroll-behavior: auto;
cursor: grabbing;
}
.tab-box.in-dragging .tab
{
pointer-events: none;
/* scroll-snap-align: none; */
}
.tab
{
scroll-snap-align: start;
user-select: none;
white-space: nowrap;
padding: 8px;
border: 1px solid #888;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment