Tailwindcss Responsive Sidebar Exercise
This article will show how to make a responsive sidebar only using HTML, Tailwindcss, and javascript.
Sidebar and Content Concept
At first, we need to determine the concept. Here I choose to make the sidebar on a fixed position and I have a table with some data as a content. Before I make sidebar and content component, I’ll make a wrapper with no margin, no padding, and flex display.
<div id="wrapper" class="m-0 p-0 w-full flex">
</div>Then, I make position fixed sidebar inside the wrapper with a few navigation link. Remember, mobile first, so I decide to make the sidebar hidden. I’ll make it visible later in javascript.
<div id="wrapper" class="m-0 p-0 w-full flex">
<aside id="sidebar" class="w-60 h-screen m-0 py-5 px-3 fixed flex flex-col border-x shadow bg-white hidden">
<ul class="w-full flex flex-col">
<li>
<a href="#dashboard">Dashboard</a>
</li>
<li>
<a href="#posts">Posts</a>
</li>
<li>
<a href="#profile">Profile</a>
</li>
<li>
<a href="#logout">Logout</a>
</li>
</ul>
</aside>
</div>I added border bottom with indigo color when the nav link hovered.
<li class="hover:border-0 hover:border-b-2 hover:border-b-indigo-600 my-1 px-1">
<a href="#dashboard">Dashboard</a>
</li>I put a close button at the top-right sidebar. But, it hidden when the screen is large. The code placed before the <ul>. The “ml-auto” class will make the button go to the right.
<button class="ml-auto lg:hidden" id="sidebar-close">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
<ul class="w-full flex flex-col">
.....Now, the code will be like this:
<div id="wrapper" class="m-0 p-0 w-full flex">
<aside id="sidebar" class="w-60 h-screen m-0 py-5 px-3 fixed flex flex-col border-x shadow bg-white hidden">
<button class="ml-auto lg:hidden" id="sidebar-close">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"
class="w-6 h-6">
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
<ul class="w-full flex flex-col">
<li class="hover:border-0 hover:border-b-2 hover:border-b-indigo-600 my-1 px-1">
<a href="#dashboard">Dashboard</a>
</li>
<li class="hover:border-0 hover:border-b-2 hover:border-b-indigo-600 my-1 px-1">
<a href="#posts">Posts</a>
</li>
<li class="hover:border-0 hover:border-b-2 hover:border-b-indigo-600 my-1 px-1">
<a href="#profile">Profile</a>
</li>
<li class="hover:border-0 hover:border-b-2 hover:border-b-indigo-600 my-1 px-1">
<a href="#logout">Logout</a>
</li>
</ul>
</aside>
</div>It’s time I make the content part. first I put div right after the </aside>. because of the sidebar width is 240px (w-60), then I add margin-left as many as sidebar width later on javascript’s DOM.
.......
</aside>
<div id="content" class="m-0 bg-slate-50 w-full">
</div>
</div>
.......Get Leo Radhitya’s stories in your inbox
Join Medium for free to get updates from this writer.
I make navbar that contains burger menu and under that, I put table with some data inside the content.
<nav class="top-0 left-0 w-full mb-5 flex bg-white border-0 border-b py-5 px-3">
<button>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
<path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5" />
</svg>
</button>
<span class="ml-auto px-5">NAVBAR</span>
</nav>
<div id="content-data" class="p-3 bg-white mx-3">
<table class="bg-white w-full">
<thead>
<tr class="border-0 border-b-2 border-b-indigo-600">
<th class="py-2">No.</th>
<th class="py-2">Post</th>
<th class="py-2">Action</th>
</tr>
</thead>
<tbody>
<tr class="hover:bg-indigo-50">
<td class="p-3 text-center">1</td>
<td class="p-3 text-center">First Post</td>
<td class="p-3 text-center"><button class="mx-1 p-2 bg-blue-400 rounded text-white">Edit</button> <button class="mx-1 p-2 bg-red-400 rounded text-white">Delete</button></td>
</tr>
<tr class="hover:bg-indigo-50">
<td class="p-3 text-center">2</td>
<td class="p-3 text-center">Second Post</td>
<td class="p-3 text-center"><button class="mx-1 p-2 bg-blue-400 rounded text-white">Edit</button> <button class="mx-1 p-2 bg-red-400 rounded text-white">Delete</button></td>
</tr>
<tr class="hover:bg-indigo-50">
<td class="p-3 text-center">3</td>
<td class="p-3 text-center">Third Post</td>
<td class="p-3 text-center"><button class="mx-1 p-2 bg-blue-400 rounded text-white">Edit</button> <button class="mx-1 p-2 bg-red-400 rounded text-white">Delete</button></td>
</tr>
<tr class="hover:bg-indigo-50">
<td class="p-3 text-center">4</td>
<td class="p-3 text-center">Fourth Post</td>
<td class="p-3 text-center"><button class="mx-1 p-2 bg-blue-400 rounded text-white">Edit</button> <button class="mx-1 p-2 bg-red-400 rounded text-white">Delete</button></td>
</tr>
</tbody>
</table>
</div>The Javascript
Now, we move to javascript section. this section will used to detect screen width. First, we need to make a function like toggle for showing the sidebar or hide it. I put the script at the end of body tag. But before, we need a flag that tells us either the sidebar is open or close. So, I add another class “close” in sidebar element because, of course, mobile first.
<aside id="sidebar" class="close w-60 h-screen m-0 py-5 px-3 fixed flex flex-col border-x shadow bg-white hidden">and the javascript will be like:
function toggle(){
var sidebar = document.querySelector("#sidebar");
var content = document.querySelector("#content");
if(sidebar.classList.contains('open')){
sidebar.classList.remove("open");
sidebar.classList.add('close');
sidebar.classList.add("hidden");
content.classList.remove('lg:ml-60');
content.classList.add('lg:ml-0');
//content.classList.add("-translate-x-60");
}else if(sidebar.classList.contains('close')){
sidebar.classList.remove("close");
sidebar.classList.add("open");
sidebar.classList.remove("hidden");
content.classList.remove('lg:ml-0');
content.classList.add('lg:ml-60');
}
}The script will check if sidebar contains “open” or “close” class. Then, it will add or remove “hidden” class to sidebar and rearrange left margin of content section. After this function built, then I create event listener for burger menu and close button.
var burger = document.querySelector("#burger");
var cls = document.querySelector("#sidebar-close");
burger.addEventListener("click",function(){
toggle();
});
cls.addEventListener("click",function(){
toggle();
});Lastly, I added onload function to check the window width
window.onload = function(){
if(window.innerWidth >= 1024){
toggle();
}
}So the whole javascript will look like:
function toggle(){
var sidebar = document.querySelector("#sidebar");
var content = document.querySelector("#content");
if(sidebar.classList.contains('open')){
sidebar.classList.remove("open");
sidebar.classList.add('close');
sidebar.classList.add("hidden");
content.classList.remove('lg:ml-60');
content.classList.add('lg:ml-0');
//content.classList.add("-translate-x-60");
}else if(sidebar.classList.contains('close')){
sidebar.classList.remove("close");
sidebar.classList.add("open");
sidebar.classList.remove("hidden");
content.classList.remove('lg:ml-0');
content.classList.add('lg:ml-60');
}
}
var burger = document.querySelector("#burger");
var cls = document.querySelector("#sidebar-close");
burger.addEventListener("click",function(){
toggle();
});
cls.addEventListener("click",function(){
toggle();
});
window.onload = function(){
if(window.innerWidth >= 1024){
toggle();
}
}and all code will look like:
<!DOCTYPE html>
<html lang="en">
<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">
<script src="https://cdn.tailwindcss.com"></script>
<title>Sidebar Exercise</title>
</head>
<body>
<div id="wrapper" class="m-0 p-0 w-full flex">
<aside id="sidebar" class="close w-60 h-screen m-0 py-5 px-3 fixed flex flex-col border-x shadow bg-white hidden">
<button class="ml-auto lg:hidden" id="sidebar-close">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"
class="w-6 h-6">
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
<ul class="w-full flex flex-col">
<li class="hover:border-b hover:border-b-indigo-600 my-1 px-1 border-b border-b-white">
<a href="#dashboard">Dashboard</a>
</li>
<li class="hover:border-b hover:border-b-indigo-600 my-1 px-1 border-b border-b-white">
<a href="#posts">Posts</a>
</li>
<li class="hover:border-b hover:border-b-indigo-600 my-1 px-1 border-b border-b-white">
<a href="#profile">Profile</a>
</li>
<li class="hover:border-b hover:border-b-indigo-600 my-1 px-1 border-b border-b-white">
<a href="#logout">Logout</a>
</li>
</ul>
</aside>
<div id="content" class="m-0 bg-slate-50 w-full min-h-screen">
<nav class="top-0 left-0 w-full mb-5 flex bg-white border-0 border-b py-5 px-3">
<button id="burger">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
stroke="currentColor" class="w-6 h-6">
<path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5" />
</svg>
</button>
<span class="ml-auto px-5">NAVBAR</span>
</nav>
<div id="content-data" class="p-3 bg-white mx-3">
<table class="bg-white w-full">
<thead>
<tr class="border-0 border-b-2 border-b-indigo-600">
<th class="py-2">No.</th>
<th class="py-2">Post</th>
<th class="py-2">Action</th>
</tr>
</thead>
<tbody>
<tr class="border-b hover:bg-indigo-50">
<td class="p-3 text-center">1</td>
<td class="p-3 text-center">First Post</td>
<td class="p-3 text-center"><button class="mx-1 p-2 bg-blue-400 rounded text-white">Edit</button> <button
class="mx-1 p-2 bg-red-400 rounded text-white">Delete</button></td>
</tr>
<tr class="border-b hover:bg-indigo-50">
<td class="p-3 text-center">2</td>
<td class="p-3 text-center">Second Post</td>
<td class="p-3 text-center"><button class="mx-1 p-2 bg-blue-400 rounded text-white">Edit</button> <button
class="mx-1 p-2 bg-red-400 rounded text-white">Delete</button></td>
</tr>
<tr class="border-b hover:bg-indigo-50">
<td class="p-3 text-center">3</td>
<td class="p-3 text-center">Third Post</td>
<td class="p-3 text-center"><button class="mx-1 p-2 bg-blue-400 rounded text-white">Edit</button> <button
class="mx-1 p-2 bg-red-400 rounded text-white">Delete</button></td>
</tr>
<tr class="border-b hover:bg-indigo-50">
<td class="p-3 text-center">4</td>
<td class="p-3 text-center">Fourth Post</td>
<td class="p-3 text-center"><button class="mx-1 p-2 bg-blue-400 rounded text-white">Edit</button> <button
class="mx-1 p-2 bg-red-400 rounded text-white">Delete</button></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<script>
function toggle(){
var sidebar = document.querySelector("#sidebar");
var content = document.querySelector("#content");
if(sidebar.classList.contains('open')){
sidebar.classList.remove("open");
sidebar.classList.add('close');
sidebar.classList.add("hidden");
content.classList.remove('lg:ml-60');
content.classList.add('lg:ml-0');
//content.classList.add("-translate-x-60");
}else if(sidebar.classList.contains('close')){
sidebar.classList.remove("close");
sidebar.classList.add("open");
sidebar.classList.remove("hidden");
content.classList.remove('lg:ml-0');
content.classList.add('lg:ml-60');
}
}
var burger = document.querySelector("#burger");
var cls = document.querySelector("#sidebar-close");
burger.addEventListener("click",function(){
toggle();
});
cls.addEventListener("click",function(){
toggle();
});
window.onload = function(){
if(window.innerWidth >= 1024){
toggle();
}
}
</script>
</body>
</html>The result are shown in Fig. 1 for screen width ≥ 1024 pixels and Fig. 2 for less width.





