Highlight current tab after page refresh – HTML, Javascript, PHP
Suppose you are creating a tab layout where there are multiple tabs and each tab has its own content. You click on the tab button and its content is displayed.
But when you refresh the page, it starts from the first tab again. How can you make so that when you refresh the page, it keeps the last active tab as “active” ?
Bootstrap Tabs
Following code will display a tab layout with 3 tabs in Bootstrap 5:
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.3/css/bootstrap.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.3/js/bootstrap.min.js"></script>
<ul class="nav nav-tabs" id="myTab" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link active" id="home-tab" data-bs-toggle="tab" data-bs-target="#home" type="button" role="tab" aria-controls="home" aria-selected="true">Home</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="profile-tab" data-bs-toggle="tab" data-bs-target="#profile" type="button" role="tab" aria-controls="profile" aria-selected="false">Profile</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="contact-tab" data-bs-toggle="tab" data-bs-target="#contact" type="button" role="tab" aria-controls="contact" aria-selected="false">Contact</button>
</li>
</ul>
<div class="tab-content" id="myTabContent">
<div class="tab-pane fade show active" id="home" role="tabpanel" aria-labelledby="home-tab">Home</div>
<div class="tab-pane fade" id="profile" role="tabpanel" aria-labelledby="profile-tab">Profile</div>
<div class="tab-pane fade" id="contact" role="tabpanel" aria-labelledby="contact-tab">Contact</div>
</div>
Right now it makes the “Home” tab active. When you click on other tabs, you will see their content. But once you refresh the page, it will again make the home tab active regardless of which tab you clicked last time.
Updating URL
Next step is to set the value of current tab in the URL when user changes the tab. So on each tab button, we will add an onclick listener that will call a function to update the URL in the browser.
<ul class="nav nav-tabs" id="myTab" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link active" onclick="changeTab('home')" id="home-tab" data-bs-toggle="tab" data-bs-target="#home" type="button" role="tab" aria-controls="home" aria-selected="true">Home</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" onclick="changeTab('profile')" id="profile-tab" data-bs-toggle="tab" data-bs-target="#profile" type="button" role="tab" aria-controls="profile" aria-selected="false">Profile</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" onclick="changeTab('contact')" id="contact-tab" data-bs-toggle="tab" data-bs-target="#contact" type="button" role="tab" aria-controls="contact" aria-selected="false">Contact</button>
</li>
</ul>
Next we will create that Javascript function that will handle the onclick listener:
function changeTab(tab) {
const urlSearchParam = new URLSearchParams(window.location.search)
urlSearchParam.set("tab", tab)
const newPath = window.location.pathname + "?" + urlSearchParam.toString()
history.pushState(null, "", newPath)
}
If you want to learn more about this in detail, you can read this article.
If you change the tabs now, you will see that the “tab” query will be appended in the URL and its value will be the tab clicked. But if you refresh the page now, the tab will not be highlighted yet. This is because we are setting the “tab” query in URL but not reading it.
Highlight current tab as active
Last step is to get the current tab from the URL and highlight it.
<?php
$tab = $_GET["tab"] ?? "home";
?>
This is get the “tab” query from URL parameter. If it does not exists in the URL, then the default value of $tab variable will be “home”.
Following is the updated code that will highlight the tab button and also will show its content.
<ul class="nav nav-tabs" id="myTab" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link <?php echo $tab == 'home' ? 'active' : ''; ?>" onclick="changeTab('home')" id="home-tab" data-bs-toggle="tab" data-bs-target="#home" type="button" role="tab" aria-controls="home" aria-selected="true">Home</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link <?php echo $tab == 'profile' ? 'active' : ''; ?>" onclick="changeTab('profile')" id="profile-tab" data-bs-toggle="tab" data-bs-target="#profile" type="button" role="tab" aria-controls="profile" aria-selected="false">Profile</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link <?php echo $tab == 'contact' ? 'active' : ''; ?>" onclick="changeTab('contact')" id="contact-tab" data-bs-toggle="tab" data-bs-target="#contact" type="button" role="tab" aria-controls="contact" aria-selected="false">Contact</button>
</li>
</ul>
<div class="tab-content" id="myTabContent">
<div class="tab-pane fade <?php echo $tab == 'home' ? 'show active' : ''; ?>" id="home" role="tabpanel" aria-labelledby="home-tab">Home</div>
<div class="tab-pane fade <?php echo $tab == 'profile' ? 'show active' : ''; ?>" id="profile" role="tabpanel" aria-labelledby="profile-tab">Profile</div>
<div class="tab-pane fade <?php echo $tab == 'contact' ? 'show active' : ''; ?>" id="contact" role="tabpanel" aria-labelledby="contact-tab">Contact</div>
</div>
Complete code: Highlight current tab
Following is the complete code that displays 3 tabs along with their contents. On change, will set the query parameter in the URL. After refresh will highlight the tab last selected.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Highlight Current Tab after Page Refresh</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.3/css/bootstrap.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.3/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container mt-5">
<div class="row">
<div class="col-12">
<?php
$tab = $_GET["tab"] ?? "home";
?>
<script>
function changeTab(tab) {
const urlSearchParam = new URLSearchParams(window.location.search)
urlSearchParam.set("tab", tab)
const newPath = window.location.pathname + "?" + urlSearchParam.toString()
history.pushState(null, "", newPath)
}
</script>
<ul class="nav nav-tabs" id="myTab" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link <?php echo $tab == 'home' ? 'active' : ''; ?>" onclick="changeTab('home')" id="home-tab" data-bs-toggle="tab" data-bs-target="#home" type="button" role="tab" aria-controls="home" aria-selected="true">Home</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link <?php echo $tab == 'profile' ? 'active' : ''; ?>" onclick="changeTab('profile')" id="profile-tab" data-bs-toggle="tab" data-bs-target="#profile" type="button" role="tab" aria-controls="profile" aria-selected="false">Profile</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link <?php echo $tab == 'contact' ? 'active' : ''; ?>" onclick="changeTab('contact')" id="contact-tab" data-bs-toggle="tab" data-bs-target="#contact" type="button" role="tab" aria-controls="contact" aria-selected="false">Contact</button>
</li>
</ul>
<div class="tab-content" id="myTabContent">
<div class="tab-pane fade <?php echo $tab == 'home' ? 'show active' : ''; ?>" id="home" role="tabpanel" aria-labelledby="home-tab">Home</div>
<div class="tab-pane fade <?php echo $tab == 'profile' ? 'show active' : ''; ?>" id="profile" role="tabpanel" aria-labelledby="profile-tab">Profile</div>
<div class="tab-pane fade <?php echo $tab == 'contact' ? 'show active' : ''; ?>" id="contact" role="tabpanel" aria-labelledby="contact-tab">Contact</div>
</div>
</div>
</div>
</div>
</body>
</html>
If you face any problem in following this, kindly do let me know.