Learn how to create 5 stylish animated bottom navigation bars with HTML, CSS, and JavaScript. Add smooth transitions and improve your site’s navigation!

Table of Contents
Navigation bars are an essential part of any website or mobile app. They provide an easy way for users to navigate and access different sections of the website or app. However, a navigation bar doesn't just have to be functional; it can also be visually appealing and engaging.
In this article, we will explore five cool types of animated bottom navigation bars you can create using HTML, CSS, and JavaScript. These navigation bars not only provide an easy way for users to navigate your website or app but also add some fun and interactivity to the user experience.
We will provide step-by-step instructions for creating each type of navigation bar, as well as highlight the benefits and drawbacks of each design. Whether you're a beginner or an experienced web developer, you can easily create these customizable navigation bars with the help of this article.
So, let's dive into the world of animated bottom navigation bars and discover some new and exciting designs for your website or app.
Prerequisites:
Before starting this tutorial, you should have a basic understanding of HTML, CSS, and JavaScript. Additionally, you will need a code editor such as Visual Studio Code or Sublime Text to write and save your code.
Source Code
Step 1 (HTML Code):
To get started, we will first need to create a basic HTML file. In this file, we will include the main structure for our bottom navigation bar. We will use the container element to hold all of our elements.
After creating the files, just paste the following codes into your file. Remember that you must save a file with the .html extension.
Step 2 (CSS Code):
Next, we will create our CSS file. In this file, we will use some basic CSS rules to create our animated bottom navigation bar.
This will give our navigation bar an upgraded presentation. Create a CSS file with the name of styles.css and paste the given codes into your CSS file. Remember that you must create a file with the .css extension.
@import url("https://fonts.googleapis.com/css2?family=Roboto&display=swap");
@import url("https://fonts.googleapis.com/icon?family=Material+Icons+Outlined");
:root {
--accent-color: #1fa8f5;
--accent-color-fg: #fefefe;
--backdrop-color: #89d4fe;
--app-content-background-color: #c0d8ec;
--inset-shadow: rgba(7, 43, 74, 0.3);
--outset-shadow: rgba(223, 240, 255, 0.25);
--clay-box-shadow: rgba(7, 43, 74, 0.3);
--clay-background-color: #c0d8ec;
--clay-fg-color: #444;
}
body {
background-color: var(--backdrop-color);
font-size: 10px;
font-family: "Roboto", sans-serif;
}
.flex-center {
display: flex;
justify-content: space-around;
align-items: center;
}
.container {
padding: 1rem 1rem 1.5rem;
}
.stage {
max-width: 400px;
width: 400px;
margin: 0 auto;
}
.home.active {
color: var(--accent-color);
}
.home-style {
--app-content-background-color: #c0d8ec;
}
.products.active {
--outset-shadow: rgba(247, 167, 103, 0.45);
--inset-shadow: rgba(149, 62, 8, 0.45);
--clay-box-shadow: rgba(211, 69, 20, 0.4);
--clay-background-color: #d34514;
--clay-fg-color: #f1f2f3;
color: #690c0c;
}
.products-style {
--app-content-background-color: #d36e5a;
}
.services.active {
--outset-shadow: rgba(255, 159, 40, 0.45);
--inset-shadow: rgba(88, 54, 13, 0.45);
--clay-box-shadow: rgba(88, 54, 13, 0.4);
--clay-background-color: #ed9426;
--clay-fg-color: #f1f2f3;
color: #cf5c0f;
}
.services-style {
--app-content-background-color: #ed9426;
}
.about.active {
--outset-shadow: rgba(93, 255, 85, 0.45);
--inset-shadow: rgba(28, 78, 26, 0.45);
--clay-box-shadow: rgba(28, 78, 26, 0.4);
--clay-background-color: #4dd146;
--clay-fg-color: #f1f2f3;
color: #4dd146;
}
.about-style {
--app-content-background-color: #4dd146;
}
.help.active {
--outset-shadow: rgba(230, 230, 230, 0.45);
--inset-shadow: rgba(81, 81, 81, 0.45);
--clay-box-shadow: rgba(81, 81, 81, 0.4);
--clay-background-color: #a3a3a3;
--clay-fg-color: #f1f2f3;
color: #783896;
}
.help-style {
--app-content-background-color: #a3a3a3;
}
.tabbar {
background-color: var(--app-content-background-color);
border-bottom-left-radius: 1rem;
border-bottom-right-radius: 1rem;
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2);
height: 120px;
display: flex;
flex-direction: column;
box-sizing: content-box;
position: relative;
overflow: hidden;
transition: background-color 0.4s;
}
.tabbar ul,
.tabbar li {
list-style-type: none;
margin: 0;
padding: 0;
}
.tabbar ul {
position: absolute;
bottom: 0;
width: 100%;
background-color: #f9f8fa;
align-self: flex-end;
justify-content: center;
height: 50px;
}
.tabbar li {
display: flex;
justify-content: center;
align-items: center;
font-size: 1rem;
margin-right: 5px;
transition: all 0.4s;
background-color: #f9f8fa;
width: 60px;
height: 60px;
position: relative;
color: #888;
cursor: pointer;
}
.tabbar li:last-child {
margin-right: 0;
}
.tab-style1 ul {
justify-content: center;
}
.tab-style1 li {
display: flex;
justify-content: center;
align-items: center;
top: 1px;
left: 0;
width: 60px;
height: 50px;
transition: top 0.2s ease-out, width 0.4s, border-radius 0.4s, box-shadow 0.4s;
}
.tab-style1 li.follow {
position: absolute;
border-radius: 100%;
content: " ";
width: 60px;
height: 60px;
border: 10px solid var(--app-content-background-color);
background-color: var(--app-content-background-color);
top: -3rem;
transition: left 0.4s ease-in, background-color 0.4s, border-color 0.4s;
}
.tab-style1 li.follow:before, .tab-style1 li.follow:after {
content: " ";
position: absolute;
top: 27px;
right: -27px;
border-top: 11px solid var(--app-content-background-color);
background-color: #f9f8fa;
width: 20px;
height: 20px;
box-sizing: border-box;
transition: border-color 0.4s;
}
.tab-style1 li.follow::after {
border-top-left-radius: 100%;
}
.tab-style1 li.follow:before {
left: -27px;
right: unset;
border-top-right-radius: 100%;
}
.tab-style1 li:nth-child(1).active ~ .follow {
left: 12px;
}
.tab-style1 li:nth-child(2).active ~ .follow {
left: 75px;
}
.tab-style1 li:nth-child(3).active ~ .follow {
left: 140px;
}
.tab-style1 li:nth-child(4).active ~ .follow {
left: 205px;
}
.tab-style1 li:nth-child(5).active ~ .follow {
left: 270px;
}
.tab-style1 .active {
z-index: 100;
width: 60px;
height: 60px;
top: -2rem;
border-radius: 100%;
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 8px 16px 0 rgba(0, 0, 0, 0.2);
}
.tab-style2 ul {
justify-content: center;
}
.tab-style2 li {
border-top-left-radius: 100%;
border-top-right-radius: 100%;
display: flex;
justify-content: center;
align-items: center;
top: 1px;
left: 0;
width: 60px;
height: 50px;
}
.tab-style2 .active {
width: 60px;
height: 60px;
top: -1rem;
}
.tab-style2 .active span {
font-size: 2rem;
}
.tab-style2 .active:before, .tab-style2 .active:after {
position: absolute;
content: " ";
width: 13px;
height: 13px;
border-bottom: 4px solid #f9f8fa;
top: 8px;
}
.tab-style2 .active:before {
border-bottom-right-radius: 100%;
left: -7px;
}
.tab-style2 .active:after {
border-bottom-left-radius: 100%;
right: -7px;
}
.tab-style3 li {
top: -8px;
width: 60px;
height: 35px;
background-color: transparent;
padding-top: 3px;
}
.tab-style3 li.follow {
position: absolute;
top: 0;
display: flex;
border-top: 3px solid #333;
width: 60px;
height: 1px;
transition: all 0.3s ease-out;
}
.tab-style3 li:nth-child(1).active ~ .follow {
left: 20px;
z-index: 20;
}
.tab-style3 li:nth-child(2).active ~ .follow {
left: 88px;
z-index: 20;
}
.tab-style3 li:nth-child(3).active ~ .follow {
left: 149px;
z-index: 20;
}
.tab-style3 li:nth-child(4).active ~ .follow {
left: 216px;
z-index: 20;
}
.tab-style3 li:nth-child(5).active ~ .follow {
left: 283px;
z-index: 20;
}
.tab-style4 li {
width: 60px;
height: 40px;
flex-direction: column;
overflow: hidden;
}
.tab-style4 li span {
position: relative;
top: 3px;
transition: top 0.4s ease-out, font-size 0.2s ease-out;
text-shadow: inset 2px 2px 4px var(--clay-box-shadow);
}
.tab-style4 li:after {
width: 100%;
height: 10px;
text-transform: uppercase;
text-align: center;
font-size: 8px;
font-weight: bold;
position: relative;
bottom: -30px;
opacity: 0;
transition: bottom 0.2s ease-out, opacity 0.4s ease-out;
}
.tab-style4 li.active:after {
opacity: 1;
bottom: 2px;
text-shadow: inset 2px 2px 8px var(--clay-box-shadow);
}
.tab-style4 li:nth-child(1):after {
content: "home";
}
.tab-style4 li:nth-child(2):after {
content: "products";
}
.tab-style4 li:nth-child(3):after {
content: "services";
}
.tab-style4 li:nth-child(4):after {
content: "company";
}
.tab-style4 li:nth-child(5):after {
content: "help";
}
.tab-style4 .active span {
font-size: 1.1rem;
top: -4px;
}
.tab-style5 ul {
justify-content: center;
}
.tab-style5 li {
display: flex;
justify-content: center;
align-items: center;
top: 1px;
left: 0;
width: 60px;
height: 50px;
transition: top 0.4s ease-out, border-radius 0.4s ease-out, box-shadow 0.4s ease-out;
}
.tab-style5 .active {
width: 60px;
height: 60px;
border-radius: 100%;
top: -1rem;
background-color: var(--clay-background-color);
box-shadow: 1px 2px 4px 0 var(--clay-box-shadow), 2px 4px 8px 0 var(--clay-box-shadow), inset 2px 2px 8px var(--outset-shadow), inset -2px -2px 8px var(--inset-shadow);
color: var(--clay-fg-color);
}
.tab-style5 .active span {
font-size: 2rem;
}
Step 3 (JavaScript Code):
Finally, we will add some JavaScript code to ensure that our bottom navigation bar animation works correctly.
The JavaScript code selects all the unordered lists (ULs)
in a webpage and adds a click event listener to each list item (LI)
within those ULs
.
When a user clicks on an LI
element, the event listener function first prevents the default action and stops the event from propagating to other elements. It then retrieves the class of the parent UL
element and all the LI
elements within that UL
.
Next, the function checks whether the clicked LI
element already has the active
or follow
class. If it does, the function immediately returns without doing anything else.
If the clicked LI
element does not have the active
or follow
class, the function adds a new class to the parent UL
element that is a combination of the original class and the value of the data-where
attribute of the clicked LI
element followed by -style
. This new class is used to style the parent UL
element.
The function then removes the active
class from all the LI
elements within the parent UL
element and adds the active
class to the clicked LI
element.
Finally, the function calls two helper functions: clearClass
and setClass
. The clearClass
function removes a specified class from a given node, while the setClass
function adds a specified class to a given node. These helper functions are used to remove the active
class from all the other LI elements and to add the active
class to the clicked LI element.
Create a JavaScript file with the name of script.js
and paste the given codes into your JavaScript file and make sure it's linked properly to your HTML document so that the scripts are executed on the page. Remember, you’ve to create a file with .js extension.
Created by: Chris Codespud Bautista
const uls = document.querySelectorAll("ul");
uls.forEach((ul) => {
const resetClass = ul.parentNode.getAttribute("class");
const lis = ul.querySelectorAll("li");
lis.forEach((li) => {
li.addEventListener("click", (e) => {
e.preventDefault();
e.stopPropagation();
const target = e.currentTarget;
if (
target.classList.contains("active") ||
target.classList.contains("follow")
) {
return;
}
ul.parentNode.setAttribute(
"class",
`${resetClass} ${target.getAttribute("data-where")}-style`
);
lis.forEach((item) => clearClass(item, "active"));
setClass(target, "active");
});
});
});
function clearClass(node, className) {
node.classList.remove(className);
}
function setClass(node, className) {
node.classList.add(className);
}
Final Output:

Conclusion:
In this article, we have explored five different types of animated bottom navigation bars that you can create using HTML, CSS, and JavaScript. By following our step-by-step instructions, you can create a customized navigation bar that fits the design and aesthetic of your website or app. You can add CSS animation effects to each navigation bar design, making it more visually appealing and interactive.
It's important to keep in mind the benefits and drawbacks of each navigation bar design. While some designs may be more visually appealing, they may also be less functional or difficult to implement. Therefore, it's essential to choose a design that not only looks great but also provides a seamless and intuitive user experience.
We hope this article has provided you with the inspiration and knowledge to create a cool and functional navigation bar for your website or app. With these navigation bars, you can enhance the user experience and make your website or app stand out from the rest.
That’s a wrap!
I hope you enjoyed this post. Now, with these examples, you can create your own amazing page.
Did you like it? Let me know in the comments below 🔥 and you can support me by buying me a coffee
And don’t forget to sign up to our email newsletter so you can get useful content like this sent right to your inbox!
Thanks!
Faraz 😊