Welcome to a tutorial on how to create responsive tabs with pure HTML, CSS, and JS. Need to organize the information on your website a little better? Don’t want to load an entire library just for a simple tab plugin? Here is a sharing of my own, using only pure HTML CSS JS – Read on!
ⓘ I have included a zip file with all the source code at the start of this tutorial, so you don’t have to copy-paste everything… Or if you just want to dive straight in.
TABLE OF CONTENTS
DOWNLOAD & DEMO
Firstly, here is the download link to the example code as promised.
QUICK NOTES
If you spot a bug, feel free to comment below. I try to answer short questions too, but it is one person versus the entire world… If you need answers urgently, please check out my list of websites to get help with programming.
EXAMPLE CODE DOWNLOAD
Click here to download the source code, I have released it under the MIT license, so feel free to build on top of it or use it in your own project.
HOW TO USE & DEMO
<!-- (A) LOAD CSS + JS -->
<link href="tabs.css" rel="stylesheet">
<script src="tabs.js"></script>
<!-- (B) TABS WRAPPER -->
<div class="tabs">
<!-- (B1) HEADERS -->
<ul class="tabHead">
<li>First</li>
<li>Second</li>
<li>Third</li>
</ul>
<!-- (B2) CONTENTS -->
<ul class="tabBody">
<li>First content.</li>
<li>Second content.</li>
<li>Third content.</li>
</ul>
</div>
<!-- (C) INIT TABS -->
<script>
tabify();
</script>
- First
- Second
- Third
- First content.
- Second content.
- Third content.
For you guys who just want to use this as a “plugin”:
- Captain Obvious, load the CSS and Javascript.
- Define the tab
<div class="tabs">
, it only needs 2 sections:<ul class="tabHead">
The tab headers.<ul class="tabBody">
Respective content for each tab.
- Lastly, just call
tabify()
to create the tabs.
SIMPLE TABS
All right, let us now walk through how the Javascript tab works in more detail.
PART 1) THE JAVASCRIPT
function tabify () { for (let tab of document.querySelectorAll(".tabs")) {
// (A) GET HEADERS & BODY
let htabs = tab.querySelectorAll("ul.tabHead > li"),
btabs = tab.querySelectorAll("ul.tabBody > li");
if (htabs.length != btabs.length) {
console.error("Number of tabs do not match!");
continue;
}
// (B) CLICK TO TOGGLE TAB
for (let i=0; i<htabs.length; i++) {
htabs[i].onclick = () => {
for (let j=0; j<htabs.length; j++) {
if (i==j) {
htabs[j].classList.add("open");
btabs[j].classList.add("open");
} else {
htabs[j].classList.remove("open");
btabs[j].classList.remove("open");
}
}
};
}
// (C) OPEN FIRST TAB BY DEFAULT - IF NONE IS OPEN
if (tab.querySelector(".open") == null) {
htabs[0].classList.add("open");
btabs[0].classList.add("open");
}
}}
The entire tabs mechanism is contained within this tabify()
function. Looks complicated, but keep calm and look carefully.
for (let tab of document.querySelectorAll(".tabs"))
will get all the<div class="tabs">
on the page and loop through them.- (A) Get the header tabs and respective content.
- (B) Add
<li onclick="SWITCH TAB">
to the headers. We are pretty much just attaching anopen
CSS class to the selected tab. - (C) Set the first tab to open by default.
PART 2) CSS COSMETICS
/* (A) WRAPPER & SHARED */
.tabs {
max-width: 600px; /* optional */
border: 1px solid #d9d9d9;
}
ul.tabHead, ul.tabBody {
list-style: none;
padding: 0; margin: 0;
}
/* (B) HEADER TABS */
.tabHead {
display: flex;x
border-bottom: 1px solid #d9d9d9;
background: #efefef;
}
.tabHead li {
padding: 10px 20px;
cursor: pointer;
}
.tabHead li.open {
color: #fff;
background: #2a87d7;
}
/* (C) CONTENT TABS */
.tabBody li {
display: none;
padding: 20px;
max-height: 300px; overflow: auto; /* optional */
}
.tabBody li.open { display: block; }
These are mostly cosmetics. The only functional part I will say is:
- (C) Hide the contents by default
.tabBody li { display: none }
- (C) Show the content as the user clicks on a tab
.tabBody li.open { display: block }
EXTRA BITS & LINKS
That’s all for the code, and here are a few small extras that may be useful to you.
SETTING DEFAULT OPEN TAB
<div class="tabs">
<ul class="tabHead">
<li>First</li>
<li class="open">Second</li>
<li>Third</li>
</ul>
<ul class="tabBody">
<div>First content.</div>
<div class="open">Second content.</div>
<div>Third content.</div>
</ul>
</div>
As above, the first tab will open by default. If that is not the case, manually set a class="open"
on both the respective header and content.
LINKS & REFERENCES
Looking for more ways to organize your content? Check out my other guides:
- Pure CSS Accordion – Code Boxx
- Text Sliders – Code Boxx
- AJAX Tabs – Code Boxx
THE END
Thank you for reading, and we have come to the end of this guide. I hope that it has helped you to better organize the information in your project, and if you want to share anything with this guide, please feel free to comment below. Good luck and happy coding!
Very useful tutorial!
Would you give me a suggestion about implementing a cache function in the AJAX version (like in jQuery)? Thanks.
1) Add a new
tab.cache = {}
property.2) Modify
xhr.onload()
–tab.cache[url]=document.createElement("div"); tab.cache[url].innerHTML=this.response; tab.txt.innerHTML=""; tab.txt.appendChild(tab.cache[url]);
3) Lastly, change the entire
load()
function to read from the cache –if (tab.cache[url]===undefined) { DO AJAX } else { tab.txt.innerHTML=""; tab.txt.appendChild(tab.cache[url]); }