Overblog Suivre ce blog
Editer l'article Administration Créer mon blog
27 octobre 2009 2 27 /10 /octobre /2009 13:32

détail du 'Dragon' de Max Escher

Nous voici au dernier article de la série.

  • Le premier, le seul vraiment intelligent, décrivait la mécanique de base et traitait au passage le cas du rectangle coloré.
  • Les suivants (dont celui-ci) ne sont qu'une revue de ce qu'on peut faire pour donner un fond à quelque chose – infobulle ou pas.
  • Le deuxième examinait de plus près l'emploi d'une image de fond et une seule, l'occasion de réviser quelques notions utiles.
  • Le troisième, en introduisant un span supplémentaire, permettait de combiner deux images de fond. On pouvait alors fabriquer des bulles extensibles dans une direction voire, avec des images bien construites et un emploi astucieux des bordures, dans deux directions.

Aujourd'hui c'est la totale : avec encore un étage de HTML on peut faire ce qu'on veut.

Bonne occasion de rappeler un principe essentiel et souvent oublié : si une solution simple vous convient, n'allez pas en chercher une plus compliquée. Et, pour savoir si une solution simple vous convient, le meilleur moyen est de réfléchir avant de vous y mettre, de déterminer ce qui est important à vos yeux et ce qui l'est moins.

Ainsi le présent article va (tenter de) décrire une manière générale (mais un peu complexe) de tapisser un rectangle. Ne croyez pas pour autant que c'est une manière universelle, au contraire : réservez-la aux cas où les méthodes plus simples déjà exposées ne vous suffisent pas. Parce qu'aujourd'hui nous allons sérieusement saloper développer le balisage HTML et alourdir enrichir le CSS…


Petite note : comme dans les deux derniers articles le sujet est essentiellement la peinturlure de background et donc, comme dans ces articles, les infobulles seront fixes pour simplifier la lecture. La manière de rendre ces bulles escamotables est expliquée dans le premier article (comment ça  je radote  ?).


Alourdir le HTML : avant de foncer

J'ai cherché à garder aussi longtemps que possible un seul span pour l'infobulle puis, ayant dû en introduire un autre, à en tirer le maximum. Mais là… faut y passer. Cette réticence a au moins deux raisons.

  1. Purisme ou rigueur, je préfère un balisage léger où les balises servent d'abord à organiser le contenu, pas à le mettre en forme. Introduire des div et des classes dans tous les coins simplement pour mettre un rectangle à côté d'un autre plutôt qu'au-dessus… j'aime pas trop.
  2. J'aime pas trop non plus d'un point de vue pratique : les pages sont difficiles à interpréter aussi bien pour leur concepteur (qui tremble à chaque modification) que pour le navigateur (qui peut ramer considérablement).

Bref : moins on en rajoute et mieux tout le monde se porte. Il n'y a en la matière que de mauvais choix, et le  bon sens  n'est pas un guide suffisant pour trouver le moins mauvais.

Le bon sens peut faire penser que la bulle se compose de trois parties dans le sens vertical : haut, milieu et bas, chacune se divisant à son tour en trois parties dans le sens horizontal : gauche, centre et droite. Quatre coins, quatre bords, un centre, neuf cellules : oh la jolie table !

Construire une table à trois lignes et trois colonnes pour une infobulle de quelques mots, est-ce bien raisonnable ? Emboîter huit ou neuf div ou span permet de se donner meilleure W3Conscience mais n'est guère plus léger.

Dans l'article précédent nous avions pu éviter cette division par trois en unissant milieu et bas (ou centre et droite) et en utilisant des images de fond  infinies  pour ces parties ainsi fondues – un peu le principe du trombone à coulisse.

En gardant cette idée, nous n'aurons plus que quatre morceaux au lieu de neuf :

Je ne vois pas comment faire moins.

Alourdir le HTML : action !

Voici le source de l'infobulle à deux span qui nous a servi dans l'article précédent.

 Voici <a href="..." >un lien <span class="infotexte"> <span>qui vous enverra je ne sais où !</span> </span> </a> muni d'une infobulle. 

Le découpage en quatre cantons conduit à ceci :

 Voici <a href="..." >un lien <span class="infotexte"> <span class="haut"> <span>&nbsp;</span> </span> <span class="bas"> <span>qui vous enverra je ne sais où !</span> </span> </span> </a> muni d'une infobulle. 

Boum ! On passe de deux à cinq span !  Développer le balisage , disions-nous…

L'infobulle (span qui enveloppe tous les autres) se divise en deux span (haut et bas) et chacun en contient un autre pour le centre et la partie droite. J'ai fourré, à tout hasard, un espace insécable dans le span supérieur droit pour qu'il ne soit pas complètement vide – des navigateurs susceptibles peuvent traiter bizarrement les éléments vides, ça s'est déjà vu.

Tout cela n'est pas très compact mais, au moins, on voit l'idée que tente de résumer cette figure (qui pourrait figurer dans le catalogue d'un marchand de meubles scandinave…) :

Notez que la décomposition haut/bas se fait en deux span superposés alors que, à chaque  étage , la décomposition gauche/droite est rendue par deux span emboîtés : autant éviter de mettre des flottants.

Le CSS de l'infobulle : un rappel

En plus de toute la mise en forme du texte de la bulle, on avait aussi écrit ceci :

 .infotexte span {display:block} 
pour que les span s'affichent comme des rectangles, comme des éléments  block , comme des div en somme.

Et pourquoi n'avoir pas utilisé directement des div ? Seulement parce que toute cette construction, qui doit devenir une infobulle, se trouve à l'intérieur d'un lien, un élément a. Et comme les liens sont des éléments  inline , ils n'admettent pas qu'on y fourre des éléments  block . Streng verboten. De là l'emploi de span et d'une ruse de CSS.

Cette complication est inutile quand on s'occupe de décorer un brave rectangle des familles, autant dans ce cas utiliser des div.

Bon. Donc nous manions des rectangles, c'est entendu.

Le CSS de l'infobulle : un début

Causons géométrie. Il s'agit de donner aux quatre parties de l'infobulle les dimensions de la figure, sachant que le texte peut avoir une hauteur et une largeur quelconques.

Les deux span supérieurs devront avoir la même hauteur, fixe et dépendant de l'image utilisée. Compte tenu de la structure du HTML il suffit de fixer la hauteur du span intérieur (l'autre s'adaptera) :

 .haut span {height:12px} /* 12px n'est qu'un exemple, bien sûr */ 

Si l'on a pitié d'IE6 (voir ces explications dans l'article précédent) on écrira plutôt :

 .haut span {line-height:12px;font-size:12px} /* Même valeur pour les deux */ 

On remarque aussi que les deux span les plus intérieurs doivent être décollés du bord gauche de leurs contenants. On peut mettre un padding-left aux contenants ou un margin-left aux contenus, le résultat sera le même. Je préfère le padding, par habitude et aussi parce qu'il n'y aura pas le choix, pour autre chose qui vient bientôt, entre margin de l'un et padding de l'autre. Donc :

 .haut, .bas {padding-left:15px} /* rien n'oblige à réutiliser les 12px précédents */ 

Du côté droit il faut laisser un peu de place après le texte (qui se trouve dans le span intérieur du bas) :

 .bas span {padding-right:14px} /* encore une valeur à votre choix */ 

Enfin il faut ménager de la place sous le texte. Ajoutons encore un padding bas dans ce même span :

 .bas span {padding-right:14px; padding-bottom:13px} 
et, là aussi, le span extérieur (= la partie basse de la bulle) s'adaptera pour digérer cette hauteur.

Regardons ce que ça va produire :

  • le span en bas à droite est large comme le texte + 14px, haut comme le texte + 13px ,
  • donc le span bas, qui contient le précédent, s'adapte : il prend la même hauteur et une largeur de 15px + (texte + 14px) ,
  • donc le span d'infobulle, qui contient le span bas, s'adapte aussi et prend la même largeur,
  • donc le span haut occupe toute cette largeur qu'on lui offre, et se trouve aussi large que le span bas,
  • donc le span intérieur haut occupe lui aussi toute cette largeur, sauf les 15px déjà réservés du côté gauche par son contenant. Sa hauteur étant imposée, il en découle que…
  • le span haut prend lui aussi cette hauteur.

De proche en proche le bloc de texte impose ses dimensions à toute la structure : la bulle est élastique. Magique !

Pour tapisser ça on peut préparer quatre images de fond :

  1. le coin supérieur gauche : 12 pixels de haut et 15 de large,
  2. le bord supérieur (centre et coin supérieur droit) : 12 pixels de haut et  beaucoup  de large,
  3. le bord gauche (milieu et coin inférieur gauche) :  beaucoup  de haut et 15 de large,
  4. le gros de la bulle (pavé central, bords droit et bas, coin inférieur droit):  beaucoup  dans les deux sens.

Le placement de chaque image dans chaque canton coule de source, le CSS résultant est, avec un effort de présentation :

 /* Propriétés communes aux quatre span */ .infotexte span { display:block; background-color: transparent; background-repeat: no-repeat} /* Les deux étages de l'infobulle */ .haut, .bas { padding-left: 15px} /* Détails de chaque canton*/ .haut { background-image: url(gnagna/bulle_HG.gif); background-position: top left} .haut span { font-size:12px; line-height:12px; /* pour IE6 - height:12px serait plus propre */ background-image: url(gnagna/bulle_HD.gif); background-position: top right} .bas { background-image: url(gnagna/bulle_BG.gif); background-position: bottom left} .bas span { padding-right: 14px; padding-bottom: 13px; background-image: url(gnagna/bulle_BD.gif); background-position: bottom right} 

À cela s'ajoute le CSS (déjà présenté dans le premier article) à propos de .infotexte pour styler le texte de la bulle et a:hover .infotexte pour la rendre escamotable.

Le CSS de l'infobulle : coup de théâtre

C'est bien beau, très convaincant (j'espère), et d'ailleurs ça marche, mais… où est l'exemple ?

Y en a pas. Y en a pas parce que fabriquer une belle bulle comme celle-ci…

… pour ensuite la couper en quatre…

… m'ennuie.

Cela m'ennuie : un peu parce que je suis sentimental et paresseux, beaucoup parce que ces quatre morceaux sont coupés au poil près: changer d'un pixel le placement du texte dans la bulle, donc toucher à l'une des longueurs définies dans le CSS, oblige à refaire deux ou trois images, ou les quatre, en veillant à ce que les morceaux se raccordent bien.

Alors j'ai cherché à utiliser la même image pour les quatre cantons. Le résultat est presque bon :

Un lien   et sa bulle.
Recliquez sur les coins pour rétablir l'image de fond.
. Cliquez sur les coins pour mieux voir les spans.

Presque bon mais ça bave du côté droit. En y réfléchissant un peu ça s'explique : les deux span haut et bas n'ont plus une image de fond préalablement rognée à la bonne largeur mais l'image complète. Cette image complète va donc jusqu'à leur bord droit, par dessous chaque span interne (quelques clics bien placés vous montreront la chose ; pour une raison que j'ai renoncé à trouver le coin supérieur gauche se comporte bizarrement sous IE6).

Cette démo (vous pouvez vous amuser à en examiner le source : une goutte de JavaScript et un seau de CSS) contient justement le principe de la solution : les quatre span sont en position : relative pour les faire bouger commodément. Pas besoin, pour un usage normal, d'aller aussi loin. Voici le raisonnement :

  1. au départ il y a un padding-left de, mettons, 30 pixels sur les deux span haut et bas. Ils sont donc plus larges de 30 pixels que les span intérieurs (et se voient derrière eux, dans les coins transparents) ;
  2. supprimons ce padding : les quatre span ont tous la même largeur, les coins transparents de droite sont toujours  pollués  ;
  3. Coup de gong ! faisons glisser les deux span intérieurs de 30 pixels vers la droite :
     .infotexte span span {position:relative;left:30px;} 
  4. ils vont à la place voulue en sortant de leur enveloppe (la bulle) plutôt qu'en élargissant cette enveloppe (comme au début) et donc :
  5. les coins transparents de droite ne sont plus superposés aux images de fond des span d'enveloppe.

Voilà le CSS définitif (avec effort de présentation) :

 .infotexte { font-weight:normal; font-style:normal; font-family:sans-serif; font-size:12px; line-height:normal; text-decoration:none position:absolute; margin-left:-999em; margin-top:1.5em;} a:hover .infotexte {margin-left:-30px} .infotexte span { /* concerne LES QUATRE spans */ display:block; background-image:url(la_bulle_complete.gif); background-repeat:no-repeat} .infotexte span span { position:relative; left:30px;} /* décale les deux spans internes*/ .haut span { line-height:30px;font-size:30px; /* cuisine IE6 - height:30px serait meilleur*/ background-position:top right} .bas { background-position:bottom left} .bas span { padding-bottom:30px; background-position:bottom right} 
… qui met en forme ce code HTML
 Un <a href="quelquepart.html">lien <span class="infotexte"> <span class="haut"><span>&nbsp;</span></span> <span class="bas"><span>... et sa plantureuse<br />infobulle</span></span> </span> </a> 
… pour donner ce résultat (léger trucage, la bulle est ici montrée dans sa position au survol) :

Un lien   ... et sa plantureuse
infobulle


Voilà. Si je vous disais que j'ai mis cette technique au point juste pour cet article, vous le croiriez ? Je n'aime pas trop les bulles compliquées, en réalité…


commentaires

DBardel 05/11/2009 11:09


Et avec l'arrivée progressive de CSS3, tout ça devient beaucoup plus simple et léger... Regarde, je pense que ça va t'intéresser :
http://www.alsacreations.com/tuto/lire/891-coins-arrondis-css-sans-images.html


Aïe aïe aïe mon CSS ! 06/11/2009 12:54


Merci pour le lien, je le connais.
Les coins arrondis étaient réclamés à cor et à cri par pas mal de monde, ils vont en effet être possibles sans images, aussi simplement qu'un rectangle encadré, et c'est un bien.
Mais le besoin subsistera dès qu'on voudra introduire des effets visuels léchés : ombres, dégradés de couleurs, formes irrégulières. Sans chercher très loin, je ne vois pas comment faire
aujourd'hui un phylactère, ou un rectangle avec une flèche sortant d'un coin, sans images.
C'est pourquoi j'ai pris la peine de présenter plusieurs techniques en commençant par montrer tout ce qu'on pouvait tirer des plus légères avant de sortir l'artillerie lourde...


Boobalechat 27/10/2009 17:11


honnêtement, tes articles sur les infobulles sont super mais je ne les utiliserais pas (t'as eu peur hein ;) ) , chui déjà entrain de reprendre tout mes articles pour rectifier certaines erreurs de
débutant (pas de balise title (justement!) ,police taille deifie dans le html...etc), donc les re-reprendre a nouveaux...bof...Mais je garde sous le coude pour un futur projet (t'imaginais pas t'en
tirer aussi facilement :p )


AïmD ! 27/10/2009 22:30


(gros soupir............)
-----------
Au passage, et puisque tu en es à nettoyer tous tes articles (travail fastidieux mais très bonne idée), profites-en pour stocker leur code source sur ta bécane si tu ne l'as pas déjà fait. Ca rend
des services pas croyables...


Le Runner Luron 27/10/2009 15:00


Effectivement, il vaut mieux réfléchir avant de se lancer d'autant plus que, je ne sais pas pourquoi, je fonctionne plutôt Shadock!!!!
Mes neurones sont bien trop gris maintenant pour assimilés tout ça. C'est pourtant pas l'envie qui manque vu la qualité de ton blog.
Un régal.


Aïe mes doigts ! 27/10/2009 22:26


"Quand une expérience rate, il faut la recommencer jusqu'à ce qu'elle réussisse" (Prof. Shadoko). C'est bien ça ?
Mes neurones sont d'un gris à peine moins prononcé (et mes poumons sûrement moins roses), donc : objection rejetée ! Faut produire ! :D


Archives