I am learning bootstrap, and I want to have an x
next to each tab name to close it:
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
<ul class="nav nav-tabs" id="myTab" role="tablist">
<li class="nav-item" id="tab-li-1">
<button
class="nav-link active"
data-bs-toggle="tab"
data-bs-target="#tab-1"
type="button"
>
First
<button
class="btn-close"
onclick="
document.getElementById(`tab-li-1`).remove();
document.getElementById(`tab-1`).remove();
"
></button>
</button>
</li>
<li class="nav-item" id="tab-li-2">
<button
class="nav-link"
data-bs-toggle="tab"
data-bs-target="#tab-2"
type="button"
>
Second
<button
class="btn-close"
onclick="
document.getElementById(`tab-li-2`).remove();
document.getElementById(`tab-2`).remove();
"
></button>
</button>
</li>
</ul>
<div class="tab-content" id="myTabContent">
<div class="tab-pane fade show active" id="tab-1" tabindex="0">Some text here for `First`</div>
<div class="tab-pane fade" id="tab-2" tabindex="0">More text here for `Second`</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" crossorigin="anonymous"></script>
I was able to hack something around nesting another button inside my first button and then:
document.getElementById(tabId).remove();
document.getElementById(tabContentId).remove();
but I have found online that it is not valid to nest a button inside another button
Is there a better alternative that people can suggest?
You don't need to nest buttons. You don't have to use a buttons for your tabs and can just use a normal div
. For accessibility reasons, you should use role="button"
therefor.
Instead of hardcoding the buttons you could simply use JS to create the close buttons on every tab.
Your script should remove not only the tab itself but also the connected tab-pane:
window.addEventListener('DOMContentLoaded', function() {
const TABS = document.querySelectorAll('.nav-link');
//adds clsoe button to all tabs
TABS.forEach(tab => {
let closeBtn = document.createElement('button');
closeBtn.ariaLabel = 'Close Button';
closeBtn.textContent = 'X';
closeBtn.addEventListener('click', removeTab);
tab.appendChild(closeBtn);
})
//removes the tab and the tab-pane
function removeTab() {
let tabId = this.closest('.nav-link').dataset.bsTarget;
let tabPaneElement = document.querySelector(tabId);
let liElement = this.closest('li');
tabPaneElement.remove();
liElement.remove();
}
})
.nav-link {
&:hover {
cursor: pointer;
}
button {
margin-left: 1em;
}
}
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
<ul class="nav nav-tabs" id="myTab" role="tablist">
<li class="nav-item" id="tab-li-1">
<div class="nav-link active" data-bs-toggle="tab" data-bs-target="#tab-1" role="button">First</div>
</li>
<li class="nav-item">
<div class="nav-link" data-bs-toggle="tab" data-bs-target="#tab-2" role="button">Second</div>
</li>
</ul>
<div class="tab-content" id="myTabContent">
<div class="tab-pane fade show active" id="tab-1" tabindex="0">Some text here for `First`</div>
<div class="tab-pane fade" id="tab-2" tabindex="0">More text here for `Second`</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" crossorigin="anonymous"></script>