sticky nav bar (and other position considerations)

November 26, 2022 - Reading time: 4 minutes

Une autre chose avec laquelle j'ai un peu lutté, c'est de mettre deux éléments l'un en-dessous de l'autre (<nav> et <main>) sans que le texte présent dans <main> passe sous la barre de <nav> qui a un positionnement forcé.

Fragment de la page html sur laquelle je travaille :

<body>
<nav>
nav bar
</nav>
<main>
<section>
<h2>section 1</h2>
<p>Ut consectetur eros efficitur, convallis tortor ut, placerat sapien.</p>
</section>
<section>
<h2>section 2</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
</section>
</main>
</body>

Proposition de solution pour garder la partie de navigation en haut de page :

body {
margin: 0;
}

nav {
position: -webkit-sticky; /* Safari */
position: sticky;
height: auto;
top: 0;
background-color: #251D3A;
color: #E04D01;
}

main {
overflow: hidden;
background-color: #FF7700;
color: #2A2550;
}

Explications :

Il y a plusieurs valeurs possibles pour la propriété position qui indique la façon dont un élément doit être positionné dans le document. Par défaut, le flux du document se déroule de haut en bas. On peut sortir un élément du flux avec la position absolute par exemple, pour rendre le positionnement de l'élément relatif à son élément parent ou encore la position fixed si on veut le positionner relativement à la fenêtre du navigateur. La valeur sticky quant à elle permet d'aller de la valeur relative (ici, relatif à <body> qui remplit 100% de l'espace) à un positionnement fixe (par exemple : top: 0, soit haut de page) en fonction du défilement du document.

Attention : Internet Explorer ne gère pas le positionnement sticky et Safari a besoin d'un préfixe -webkit.

Elle est complétée par la propriété overflow de l'élément suivant avec une valeur hidden pour que le contenu remplisse tout l'espace disponible avec possibilité de défilement sans barre de défilement.

Il y a peut-être des façons de faire plus propres mais pour l'exemple en question ça fonctionne, en plus d'être très court ce qui est appréciable. On pourra ajouter des marges intérieures (padding) pour que ce soit un peu moins moche, par exemple :

padding: 0 1em;

pour <body> et <main> et

padding: 1em;

pour <nav>.

(si deux valeurs : la première est valable pour haut/bas du bloc, la deuxième pour droite/gauche. Si une seule valeur : valable pour les quatre côtés)