Ce tutoriel vous permettra de créer des onglets fonctionnels avec du HTML, CSS et JavaScript. Nous ferons en sorte que vous puissiez ajouter les fichiers CSS et JavaScript à la page et appliquer certaines classes aux divs imbriqués pour que cela fonctionne. Nous essaierons également de le rendre sémantiquement correct en ajoutant des attributs ARIA aux éléments formels. Cependant, ne prenez pas cela trop au sérieux car je ne suis pas sûr de l’avoir fait correctement. Quoi qu’il en soit, il est toujours essentiel de donner un sens à votre HTML.
See the Pen Onglets HTLM/CSS/JS by Damien Flandrin (@dam62500) on CodePen.0
HTML des onglets ( tabs )
La structure potentielle de ces onglets pourrait ressembler à ceci. Nous aurions d’abord un div avec la classe tabs et ensuite deux divs à l’intérieur, un avec la classe tab-registers et un avec la classe tab-bodies. Le premier bouton à l’intérieur de tab-register est relié au premier élément dans l’élément tab-bodies. Nous pouvons éventuellement donner à l’un des boutons la classe active-tab pour qu’il devienne l’onglet actif.
<div class="tabs">
<div class="tab-registers">
<button class="active-tab">Tab 1</button>
<button>Tab 2</button>
<button>Tab 2</button>
</div>
<div class="tab-bodies">
<div style="display:block;">
Contenu Tab 1
</div>
<div style="display:none;">
Contenu Tab 2
</div>
<div style="display:none;">
Contenu Tab 3
</div>
</div>
</div>
JavaScript des onglets ( tabs )
Nous commençons par obtenir une collection HTML de tous les éléments avec la classe tabs, et nous bouclons dessus après l’avoir transformé en liste en utilisant Array.from(list_like). Le rappel de la boucle prend l’élément lui-même et l’index. Nous aurons besoin de l’index pour identifier ce groupe d’onglets de manière unique.
Array.from(document.querySelectorAll('.tabs')).forEach((tab_container, TabID) => {
...
})
Ensuite, nous enregistrons certains des éléments essentiels dans des variables, à savoir les éléments tabs-registers et tab-bodies.
const registers = tab_container.querySelector('.tab-registers');
const bodies = tab_container.querySelector('.tab-bodies');
En continuant, nous obtenons le registre actif, mais comme il pourrait être indéfini, nous le fixons au premier bouton si c’est le cas. Dans tous les cas, nous ajoutons la classe active-tab à l’élément.
let activeRegister = registers.querySelector('.active-tab');
activeRegister = activeRegister ? activeRegister : registers.children[0]
activeRegister.classList.add('active-tab')
Après cela, nous appelons la fonction changeBody(), qui, comme elle le dit, va masquer tous les corps sauf celui correspondant au registre/onglet actuel. Nous appelons également cette fonction à chaque fois que l’onglet est modifié.
Maintenant, nous bouclons également sur tous les éléments directement à l’intérieur du conteneur de registres. Ce sont les boutons/onglets. Nous définissons ensuite l’attribut aria-controls, qui indique quel autre élément est contrôlé par celui-ci. Nous devons également définir un id pour le corps correspondant. Nous utilisons l’id de l’onglet et l’index du bouton de l’onglet pour construire un id unique.
Ensuite, nous ajoutons un écouteur d’événements au bouton, nous supprimons la classe d’onglet active du registre actuel et nous remplaçons le contenu de la variable par le nouveau registre actuel, nous devons donc également ajouter la classe d’onglet active. Enfin, nous appelons la fonction changeBody().
Array.from(registers.children).forEach((el, i) => {
el.setAttribute('aria-controls', `${TabID}_${i}`)
bodies.children[i]?.setAttribute('id', `${TabID}_${i}`)
el.addEventListener('click', (ev) => {
let activeRegister = registers.querySelector('.active-tab');
activeRegister.classList.remove('active-tab')
activeRegister = el;
activeRegister.classList.add('active-tab')
changeBody(registers, bodies, activeRegister)
})
})
Passons maintenant à la fonction changeBody(). Dans celle-ci, nous bouclons à nouveau sur les registres enfants. Nous obtenons également l’Index de chaque itération. Ensuite, si le corps à cet indice existe, nous décidons si sa propriété d’affichage est block ou none en fonction du registre actuel. Nous faisons cette vérification pour qu’il puisse y avoir plus de registres que de corps. Ensuite, nous définissons également l’attribut aria-expanded pour le bouton, qui indique à l’utilisateur si le contenu de ce panneau ou du bouton qui mène à un panneau est développé ou non.
function changeBody() {
Array.from(registers.children).forEach((el, i) => {
if (bodies.children[i]) {
bodies.children[i].style.display = el == activeRegister ? 'block' : 'none'
}
el.setAttribute('aria-expanded', el == activeRegister ? 'true' : 'false')
})
}
CSS des onglets
.tabs {
font-family: 'Lucida Sans', sans-serif;
font-size: 20px;
}
.tabs .tab-registers {
display: flex;
background-color: RGB(255, 255, 255);
}
.tabs button {
padding: 0.5em;
background-color: RGB(255, 255, 255);
border: none;
font: inherit;
}
.tabs .tab-registers button:hover {
cursor: pointer;
}
.tabs .tab-bodies {
padding: 0.5em;
background-color: RGB(235, 235, 235);
flex-grow: 1;
overflow-y: auto;
}
.tabs button.active-tab {
background-color: rgb(235, 235, 235);
}