Système de panneau (sidebar) qui se retire de façon fluide sur un mobile, ou si la fenêtre est trop petite. Le tout en pure CSS et un « @Media Queries ». Plus un bouton « bascule » (toggle) pour afficher ou cacher le menu avec un simple petit JavaScript pour faire basculer la classe.
La complexité réside dans la structure selon la technique utilisée. Mais au début, deux calques, un bloc DIV dit « Panneau » à 20% et un « Contenu » à 80%. La façon simple, avec box-sizing: border-box
et le bon vieux float:left
1. Créer le panneau et le contenu
<style> div {box-sizing: border-box;float:left;width:100%;} .cPanneau. {width:20%;background: #444;} .cContenu {width:80%;background: #666;} </style> <div class="cPanneau">20%</div> <div class="cContenu">80%</div>
2. Adaptatif selon la résolution
Ajoutons le « mediaquery », mais attention, je renverse les rôles, « mobil first » oblige :
<style> div {box-sizing: border-box;float:left;width:100%;} /* Mobil first */ .cContenu {width:100%;background-color: #666;} .cPanneau {width:0;background-color: #444;} @media(min-width:768px) { /* Standard */ .cPanneau {width:20%;} .cContenu {width:80%;} } </style>
Hey, la moitié de la job est faite! Le panneau est ouvert uniquement pour une résolution supérieure à 767 pixels. Redimensionner votre écran pour voir le résultat.
3. Avec bouton bascule
Il ne manque que le bouton « bascule » pour ouvrir et fermer le panneau. Pour ce faire j’ajoute une classe, la classe « cBascule » qu’il suffit d’ajouter ou de supprimer lors d’un clic! Fait intéressant, l’ordre change selon la résolution. Sur un mobile, la classe « cBascule » indique que le panneau est ouvert, alors que la même classe indique au contraire que le panneau est fermé sur un 767px et plus!
/* J'ai ainsi ma classe « cBascule » pour mobile */ /* et un panneau ouvert (width:20%;) : */ .cPanneau.cBascule {width:20%;} .cContenu.cBascule {width:80%;} /* Et la même classe inversé : */ @media(min-width:768px) { .cPanneau.cBascule {width:0;} .cContenu.cBascule {width:100%;} }
Et le petit bout de JavaScript pour activer le bouton. Ah et le bouton, j’allais l’oublier :
<div class="cPanneau">50%</div> <div class="cContenu"><a id="oBascule" href="#">+</a> 50%</div> <script> // Pure JavaScript 5+ document.querySelector("#oBascule").addEventListener( "click", function() { document.querySelector('.cPanneau').classList.toggle('cBascule'); document.querySelector('.cContenu').classList.toggle('cBascule'); }); </script> // Exemple beaucoup plus simple (!) avec jQuery <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script> <script> $("#oBascule").click(function(e) { e.preventDefault(); $(".cPanneau").toggleClass("cBascule"); $(".cContenu").toggleClass("cBascule"); }); </script>
Exemple en ligne complet Noter qu’avec un conteneur, il suffirait d’une seule « bascule » sur le conteneur...
Le code complet (avec animation)
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>Panneau latéral de navigation Flex adaptatif sans jQuery - Trucsweb.com</title>
<meta name="dcterms.publisher" content="Conception Oznogco Multimédia (http://oznogco.com)" />
<style>
div {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
width:100%;
-webkit-transition: all 0.5s ease;
-moz-transition: all 0.5s ease;
-o-transition: all 0.5s ease;
transition: all 0.5s ease;
}
.cContenu {
width:100%;
float:left;
background-color: #666;
}
.cPanneau {
width:0;
float:left;
background-color: #444;
}
.cPanneau.cBascule {width:20%;}
.cContenu.cBascule {width:80%;}
@media(min-width:768px) {
.cPanneau {width:20%;}
.cPanneau.cBascule {width:0;}
.cContenu {width:80%;}
.cContenu.cBascule {width:100%;}
}
</style>
</head>
<body>
<div class="cPanneau">50%</div>
<div class="cContenu"><a id="oBascule" href="#">+</a> 50%</div>
<script>
document.querySelector("#oBascule").addEventListener( "click", function() {
document.querySelector('.cPanneau').classList.toggle('cBascule');
document.querySelector('.cContenu').classList.toggle('cBascule');
});
</script>
</body>
</html>
Tout est dans la marge!
C’est un exemple essentiellement basé sur le float:left;
. Le contenu et le panneau sont alignés à gauche, toujours avec une marge à gauche. L’avantage est un positionnement « relatif » beaucoup plus facile à intégrer. On pourrait utiliser une table HTML (fixed) et sa très grande flexibilité. Ou encore carrément un display:table;
. Une technique couramment utilisée est le positionnement absolu. Le contenu avec une marge à gauche et le panneau, de largeur équivalente à la marge du contenu, est positionné de façon absolue en haut à gauche. On a droit généralement à une horrible belle barre de défilement. De plus, on peut en arracher avec l’entête et le pied de page. Un exemple plus intéressant avec Flex, comme l’exemple suivant :
Exemple avec Flex
Même chose avec Flex à la différence cette fois de jouer sur la propriété flex: 1
ou flex: 0
. Un bel exemple avec balisage HTML5 :
#oPanneau {flex: 1;} #oPanneau.cBascule {flex: 0;}
<!doctype html>
<html lang="fr-CA">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>Panneau latéral Flex - Trucsweb.com</title>
<meta name="dcterms.publisher" content="Conception Oznogco Multimédia (http://oznogco.com)" />
<style>
html {margin:0;padding:0;}
body {margin: 0;padding:0;}
.flex-container {
padding: 0;
margin: 0;
-ms-box-orient: horizontal;
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -moz-flex;
display: -webkit-flex;
display: flex;
-webkit-justify-content: space-around;
justify-content: space-around;
-webkit-flex-flow: row wrap;
flex-flow: row wrap;
-webkit-align-items: stretch;
align-items: stretch;
}
.header,
.footer {flex: 1 100%; background: #5d625c;color:#fff;}
.sidebar {flex: 1; background: #c6c3bd;color:#000;}
.main {flex: 2; background: #d6d3ce;color:#000;}
.flex-item {padding: 10px;width: 100px;}
#oPanneau {
flex: 0;
padding:0;
border:0;
overflow:hidden;
-webkit-transition: all 0.5s ease;
-moz-transition: all 0.5s ease;
-o-transition: all 0.5s ease;
transition: all 0.5s ease;
}
#oPanneau.cBascule {flex: 1;}
@media(min-width:768px) {
#oPanneau {flex: 1;}
#oPanneau.cBascule {flex: 0;}
}
/* Bouton */
a[role="button"] {
color: #fff;
margin-left:-10px;
font-weight:bold;
background-color: #c6c3bd;
padding:10px;
text-decoration: none;
}
a[role="button"]:hover, [role="button"].bouton:focus {
color: #fff;
background-color: #b2b1af;
text-decoration: none;
}
</style>
</head>
<body>
<div class="flex-container">
<header class="flex-item header">Entête</header>
<aside id="oPanneau" class="flex-item sidebar">
<ul class="oMenu-nav">
<li><a href="#"><b>Trucsweb.com</b></a></li>
<li><a href="#" class="active">Accueil</a></li>
<li><a href="#">Nouvelle</a></li>
<li><a href="#">à propos</a></li>
<li><a href="#">Contact</a></li>
</ul>
</aside>
<main class="flex-item main" style="text-align: left;"><a id="oBascule" role="button" href="#">X</a> Texte principal
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi
</main>
<footer class="flex-item footer">Pied de page</footer>
</div>
<script>
document.querySelector( "#oBascule" ).addEventListener( "click", function() {
this.innerHTML = (this.innerHTML=='X') ? '≡':'X';
document.querySelector('#oPanneau').classList.toggle('cBascule');
});
</script>
</body>
</html>
Vous avez un problème de positionnement après une redimension, recharger la page (de la mémoire cache) :
// Rafraichissement de page après // une redimension de l'écran. // Compatible Firefox // Avec jQuery $(window).bind('resize', function(e) { if (window.RT) clearTimeout(window.RT); window.RT = setTimeout(function() { this.location.reload(false); /* false pour la mémoire cache */ }, 200); });
Conclusion
jQuery, JavaScript 5+, Flex, tout est question de compatibilité. Et peut-être aussi d’assaisonnement. Si la recette est toujours la même recette, tout dépend du plat principal.