Menu flexible en onglets en utilisant la propriété css3 border-image

N’en avez vous parfois pas marre des coins arrondis uniformes ? N’avez vous parfois pas envie de créer des formes plus complexes ? En règle générale, pour créer des formes plus complexes il faut recourir à des images, ce qui génère un problème de flexibilité. La solution consiste souvent à créer nos images plus longues que le titres / objets le plus long que l’on veut créer. Mais que se passe-t-il quand un jour une page est créée avec un titre encore plus long ? Il faut souvent alors re-créer une image plus grande. Voici mon idée expérimentale pour résoudre ce problème.

Cette idée m’est venue à l’esprit hier après midi. Une personne sur un forum demandait si il était possible d’avoir une propriété comme “border-image-left”. Cette propriété n’existe bien évidement pas, mais il est possible de la simuler en créant une image avec un bord gauche, et laissant les trois autres transparents. Cette discussion m’a fait jouer un peu avec la propriété css3 border-image et il m’est venu l’idée de l’utiliser pour créer un menu en onglets dont la taille changerait en fonction du texte, le rendant plus flexible.

Voir l’exemple      Télécharger le fichier

Pour ceux qui ne savent pas comment fonctionne la propriété border-image, un petit rappel  ici et  ici.

Pour mon exemple nous utiliserons l’image suivante :blue border used for tabs flexible navigationComme vous le savez sans doute, il nous faut découper l’image. Souvenons nous également que tout ce qui va être au milieu de notre image apparaîtra en  background pour notre bloc. Ce background sera utilisé comme couleur d’arrière plan sous nos liens de navigation, voici le découpage en détails :  slicing the border-imageL’idée de cette technique et d’utiliser les coins de l’image et d’étirer le milieu pour avoir un bord qui s’adapte au pixel près quelque soit la longueur de notre texte.

Etape 1: utiliser border-image pour créer des onglets de taille flexible

Voici notre html :

1
2
3
4
5
6
7
8
<div id="nav">
<ul>
<li> <a href="#"> Short title </a> </li>
<li> <a href="#"> A little longer title </a> </li>
<li> <a href="#"> A very very long title  !!!</a> </li>
<li> <a href="#"> title ?</a> </li>
</ul>
</div>

Et voici le css avec les découpages:

1
2
3
4
5
6
7
8
9
10
11
/*** Create the tabs **/
ul li a{    color:#fff;    text-decoration:none;}
#nav{    width:800px; clear:both;}
#nav ul li{ display:inline; padding:0px;}
#nav ul li a:link, #nav ul li a:visited{display:block; float:left; padding: 0 0px 0 5px;
border-width:10px 40px 10px 20px;
-webkit-border-image: url(img/blue_border.png) 10 50 20 20 stretch;
-moz-border-image: url(img/blue_border.png) 10 50 20 20 stretch;
border-image: url(img/blue_border.png) 10 50 20 20 stretch;
margin-left:-15px;
}

Les premières lignes sont du code basique pour mettre les éléments en ligne. Nous faisons de notre liste une liste inline et allons donner du padding aux éléments pour les décoller les uns des autres.

Expliquons désormais le border-image. Tout d’abord nous donnons les tailles de nos 4 bords. Le coins en haut gauche aura 10px de large. Pour le coin à droite, nous allons donner une taille un peu plus grande en raison de la forme étrange de nos onglets. Je n’avais tout d’abord pas donné de taille au bord du bas, mais le texte était collé au bas de l’image donc j’ai décidé de lui donner une taille de 10px pour ajouter un peu d’espacement. Le dernier bord aura quant à lui une taille de 20px.

La seconde partie est le découpage de l’image. Là il faut avouer que j’ai testé pas mal de valeurs pour avoir trouver l’équilibre. Il vous faut juste vous souvenir que si vous donnez les valeurs en pixels, le px est superflus, mais si les valeurs sont données en pourcentages alors il vous faudra ajouter le %.

Passons à la partie intéressante : la valeur “stretch”. C’est ici que cette technique prend tout son sens. Avec cette valeur, nous allons dire à notre navigateur d’étirer le milieu de notre image le long de notre texte (puisque nous appliquons cette technique à l’élément a). J’ai ajouté une margin-left:-15px pour faire passer les éléments les uns sous les autres et leur donner cet effet d’onglets.

Pour le moment, nous avons une navigation en onglets dont le premier élément est en dessus de tous les autres, mais nous voulons l’inverse.

Etape 2: réordonner les onglets avec z-index

Pour le moment, le dernier élément li créé est au dessus en raison de la cascade. Nous allons corriger cela avec une petite astuce de z-index  :

1
2
3
4
5
/*order the links !*/
ul>li a {    position:relative;    z-index:99;}
ul>li+li a{position:relative;    z-index:98;}
ul>li+li+li a{    position:relative;    z-index:97;}
ul>li+li+li+li a{    position:relative;    z-index:96;}

Comme vous le voyez, nous donnons au premier élément le z-index le plus élevé pour le faire passer au dessus, puis nous baissons le z-index. Nous utilisons le sélecteur + pour sélectionner du premier li. Le seul inconvénient de cette technique est qu’il faut ajouter une ligne de css à chaque fois que l’on ajoute un nouvel objet au menu.

Voici le résultat :

flexible tabs step2

Il ne nous reste plus qu’à ajouter une boite en dessous pour avoir un véritable effet d’onglets.

Etape 3: discipliner IE.

Pour le moment, nos morceaux de code ont un rendu pas génial sous IE <9 :

IE gets ugly

Puisque IE ne connait pas le propriété border-image, il ne met pas de fond à nos éléments, et le texte est collé en raison du margin-left:-15px. Nous allons corriger ça. J’utilise les commentaires conditionnels de Patrick O’Neill autour de la balise body. Le principe est de donner au body une classe en fonction de la version d’IE utilisée, et d’éviter les hack css / feuilles de style externes.

Nous allons utiliser ces classes pour donner à IE des onglets rectangulaires classiques :

1
2
3
4
5
/*** make old friend IE behave **/
.ie #nav ul{margin-left:-20px;}
.ie #nav ul li a:link,.ie #nav ul li a:visited{    padding:10px;    background:#265e7f;    margin-left:5px;}
.ie #nav ul li a:hover{    background:#fff;}
.ie #nav ul li a.active{ background:#fff;}

Les bénéfices de cette méthode :

Comme vous pouvez le voir dans l’exemple si dessous, cette méthode présente l’avantage d’être très flexible quelque soit la longueur du texte. Elle est également flexible car elle s’adapte à la taille de la police :

tabs at different font-sizes

Dans le fichier de démo, j’ai ajouté un second exemple essayant d’arriver au même rendu avec la propriété background-size. Comme vous pouvez le constater, celle ci pose quelques problèmes lorsque le texte devient trop long, l’image est distordue.

J’ai un peu chercher sur google mais je n’ai pas trouvé grand chose à propos de cette méthode. Je ne sais pas si je suis la seule à avoir eut l’idée d’utiliser cette méthode ou si l’idée est tellement mauvaise que personne n’a pris la peine d’en parler. Dans tous les cas n’hésitez pas à me donner vos retours,  problèmes et améliorations potentielles.

Besoin d'un designer ? D'un design de site ou d'application mobile ? De cartes de visites ou d'un logo ? Envie de travailler ensemble ? N'hésitez pas à consulter mes réalisations et à me contacter directement.

2 réflexions au sujet de « Menu flexible en onglets en utilisant la propriété css3 border-image »

  1. Bonjour William,

    Oui IE9 ne supporte pas border-image (et ie10 non plus il me semble), il faut donc utiliser le commentaire conditionnel pour ie9 pour avoir des angles droits qui lui supporte par contre les bords arrondis.