Overblog Suivre ce blog
Editer l'article Administration Créer mon blog
24 septembre 2009 4 24 /09 /septembre /2009 11:09

détail du 'Dragon' de Max Escher

On progresse. Le premier article donnait les bases et traitait le cas du rectangle coloré, le deuxième examinait de plus près l'emploi d'une image de fond et une seule, nous voilà à parler d'images extensibles. L'important, contrairement à ce qu'on pourrait penser, n'est pas l'extensibilité dans une direction ou dans deux mais l'éloignement du modèle primitif, à savoir le rectangle à fond uni (éventuellement encadré). Allons du plus proche au plus éloigné.


Petite note : tout comme dans le deuxième article, il est essentiellement question ici de peinturlure de background. Tout comme dans le deuxième article, les infobulles sont donc fixes pour vous épargner de balader votre curseur partout. L'art et la manière de rendre ces bulles escamotables sont expliqués dans le premier article.


Quatre coins carrés

Ça, c'est déjà vu : le rectangle à fond uni. Très sommaire (une couleur de fond, une à quatre couleurs pour les quatre bords) mais très simple à produire.

Nous ne l'avons pas exploité à fond : si on utilise une image assez grande ( trop  grande), elle pourra  tapisser  des bulles de dimensions très variées sans que leur contenu déborde de l'image. Avec un peu de réflexion et un balisage inchangé on peut déjà produire un effet intéressant… lisez le chapitre qui vient.

Un seul coin modifié

Regardez cette image :

C'est une  bulle  dont le coin supérieur gauche est un peu  travaillé  (=pas un angle droit). Elle se prolonge  à l'infini  vers la droite et vers le bas. Notez aussi qu'elle est bordée d'un trait gris en haut et à gauche mais ni en bas ni à droite. Maintenant regardez ce CSS :

 .infotexte {padding:12px; background: transparent url(http:gnagnagna/bulleCoin.gif) scroll no-repeat top left; border-style:solid; border-color: #888; border-width:0 1px 1px 0;  color:black; font-weight:normal; font-style:normal; font-family:sans-serif; font-size:12px;line-height:normal; text-decoration:none; position:absolute; margin-top:1em; margin-left:-999em } a:hover .infotexte {margin-left:-1em} 

L'image sert de fond (c'était à prévoir) et il y a un pixel de bordure, mais seulement en bas et à droite (les indications sur fond grisé, toujours les mêmes, ne seront plus répétées dans la suite). Voilà le résultat :

Voici un lien une ligne un peu longue, juste pour voir muni d'une infobulle un peu longue et un autre lien plusieurs
lignes
et encore une
à bulle multi-lignes

Plaisant, non ? Toute l'astuce réside dans une définition soigneuse des bordures (n'en mettre aucune sur les côtés du coin  spécial ) combinée au fait que le fond ne déborde jamais du rectangle de remplissage. Ça nous a contrariés dans l'article précédent, il est juste que ça nous rende service dans celui-ci ! Si vous préférez que le coin  spécial  ne soit pas celui du haut à gauche il suffira, après avoir préparé une autre image  infinie , de remplacer top left par autre chose et d'ajuster les bordures.

Mais pour aller plus loin, pour des formes moins proches du rectangle pur, il faut compliquer un peu le HTML et le CSS.


Principe

Les images de fond déformables ça n'existe pas : il n'existe pas un format spécial de fichier image ni des propriétés magiques de CSS pour indiquer que les coins sont immuables, que chaque bord s'étire dans un seul sens et le centre dans les deux sens.

Au lieu de quoi nous allons combiner deux images de fond (pour commencer). Oui mais… on ne peut indiquer qu'une seule background-image par élément de page ? Très juste, c'est bien pourquoi nous utiliserons deux éléments HTML.

Jusqu'ici l'infobulle ne comportait qu'un seul élément HTML : le span de classe infotexte. Pour des raisons qui apparaîtront dans la suite, l'élément supplémentaire sera emboîté dans l'infobulle plutôt que placé avant, après, ou autour.

Trêve de parlotes : depuis deux articles nous utilisons ce code HTML :

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

Il s'agit d'un span de classe infotexte contenant le texte de la bulle. Maintenant nous le complétons comme ceci :

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

Il s'agit d'un span de classe infotexte contenant un deuxième span sans classe particulière, lequel contient le texte de la bulle. Cherchez le changement. Très très compliqué, hein ? :-). Première vision :

Voici un lien qui vous enverra je ne sais où ! muni d'une infobulle.

Les deux fonds gris, provisoires, montrent l'assemblage. Dans le CSS, juste une nouvelle ligne :

 .infotexte {padding:0; /* etc. */} .infotexte span {display:block} 

Le display:block permettra de cuisiner tranquillement la géométrie de ce nouveau span. Le span principal est déjà, implicitement, en display:block du fait de son positionnement absolu, sans quoi il faudrait le dire explicitement. Maintenant, au boulot !

Une bulle extensible en largeur

Avertissement : cette technique donne un résultat comique sous IE6, je propose plus bas un replâtrage pour IE6 qui marche aussi avec les navigateurs décents. Mais commençons par travailler proprement…


Voici les deux images que nous utiliserons :

Demi-bulle gauche
16x32 pixels
Corps de bulle  infini  vers la gauche et demi-bulle droite
484x32 pixels

Qui utiliser comme fond de quoi ? Puisque les deux spans sont superposés, la question n'est pas sotte. Mettons le corps de bulle, qui se verra derrière le texte, en fond du span interne. Tant qu'on y pense, et puisque l'image fait 32 pixels de hauteur, choisissons height et padding de ce span pour totaliser 32 :

 .infotexte {padding:0;} .infotexte span {display:block height:16px; padding:8px 0;/* 16+8+8=32*/ background: transparent url(http:gnagnagna/bulleDlongue.gif) scroll no-repeat top right } 

Voici un lien qui vous enverra je ne sais où ! muni d'une infobulle.

Notez le top right dans le CSS pour que le coin supérieur droit de l'image soit dans le coin supérieur droit du span, sans quoi on est mal. Autre chose : le texte s'arrête au ras de la bulle, logique puisqu'il n'y a pas de padding à droite. Le demi-cercle de droite est large de 16 pixels, corrigeons le CSS en conséquence et voyons ce que ça donne :

 .infotexte {padding:0;} .infotexte span {display:block height:16px; padding:8px 0;padding-right:16px; background: transparent url(http:gnagnagna/bulleDlongue.gif) scroll no-repeat top right } 

Voici un lien qui vous enverra je ne sais où ! muni d'une infobulle.

Maintenant, la partie gauche. Elle va servir de fond au span principal, bien sûr, mais si on s'en tient là on ne verra rien : elle sera sous le corps de bulle parce que, actuellement, le span emboîté remplit tout le span principal. Pour dégager la vue ajoutons un peu de padding-left à ce span principal en même temps que la deuxième image de fond:

 .infotexte {padding-left:16px; background: transparent url(http:gnagnagna/bulleG.gif) scroll no-repeat top left } .infotexte span {display:block height:16px; padding:8px 0;padding-right:16px; background: transparent url(http:gnagnagna/bulleDlongue.gif) scroll no-repeat top right } 

Résultat avec seulement le padding à gauche (fond gris) :

Voici un lien qui vous enverra je ne sais où ! muni d'une infobulle.

Résultat avec l'image :

Voici un lien qui vous enverra je ne sais où ! muni d'une infobulle.

Et, comme promis, c'est extensible :

Voici un lien court ! muni d'une infobulle.

Voici un lien trèèèèèèèèèèèèèèèèèèèèèèèèèèèèèèèèèèèèèèèèès long ! muni d'une infobulle.

Voilà tout le secret…

Long live IE6 !

Sous IE6 la fin du paragraphe précédent donne ceci :

… qui est amusant, pour le dire aimablement. En repartant du modèle simple (le rectangle coloré à un seul span) et en le complétant progressivement, on observe ceci :
  • rectangle coloré ou rectangle avec image de fond : correct, bien qu'IE6 ne place pas correctement la bulle au chargement de la page ;

IE ne place pas correctement la bulle au chargement de la page ? Faites l'essai en remplaçant le -999em qui l'envoie hors champ par 0, par exemple. On voit la bulle se placer d'abord contre le bord gauche de l'article (alors qu'elle devrait rester juste après le texte du lien), puis à la place attendue (en léger retrait du lien) lorsqu'on survole le lien, enfin revenir à l'aplomb du lien lorsqu'on cesse de le survoler (là où elle aurait dû se trouver dès le début). Cela vient, je pense, de ce que le lien est un élément  inline  : IE6 ne le prend pas en compte en faisant sa mise en page de la bulle. Au survol du lien il se réveille :  Ah tiens, je devrais placer cet absolu d'une certaine manière  et dès lors reste dans les clous. Par chance, dans le cas de notre infobulle, ce placement initial incorrect ne se remarque pas : -999em ou -1004em, c'est de toute façon hors champ. Mais tout de même…

Continuons, continuons, ça va devenir franchement rigolo. D'après le W3C, mettre la bulle en position absolue a deux conséquences :

  • elle passe automatiquement en display : block,
  • mais sa largeur, contrairement à celle des  blocks  ordinaires qui sont aussi larges que possible, est aussi faible que possible : adaptée au contenu de la bulle.

Cette adaptation de la largeur au contenu est justement ce qui rend la bulle extensible en largeur, elle est à la base du procédé. Quand on ajoute le span interne, lui aussi affiché comme un  block  mais sans positionnement absolu (vous saisissez la finesse ?), il se rend aussi large que possible dans les limites de son contenant, à savoir la bulle, bulle dont la largeur dépend… de ce qu'il y a dans ce nouveau span ! Comment IE6 s'en débrouille-t-il ?

  • ajouter le span intérieur : pas de changement ;
  • mettre ce span en display:block : toujours pas de changement.

Seulement il faut bien préciser la géométrie de ce span interne. Essayons :

  • préciser padding et margin du span interne: OK
  • fixer sa hauteur : ça explose, la bulle est soudain aussi large que l'article !

Les propriétés height (et width) ne sont pertinentes que pour un élément  block  (en gros). Ici, tout se passe comme si IE6 se disait  Ça alors, c'est vraiment un bloc ! Faut que je le formatte dans les règles ! Pleine largeur, zou !  en oubliant totalement que ce span se trouve dans un élément  absolu  et que  pleine largeur  signifie donc  largeur de la bulle . Largeur qui, du fait du placement absolu, dépend justement de ce span intérieur…

N'accablons pas davantage le pécheur. La Providence permet qu'on s'en sorte à moindres frais en n'utilisant surtout pas height: 16px mais font-size: 16px;line-height: 16px. Tout ça pour ça ? Ben oui, c'est IE, que voulez-vous…

Quelle différence entre ces deux propriétés ? height est une dimension d'un  block , un rectangle à l'intérieur duquel on fourre ce qu'on veut, gros ou petit. À l'opposé line-height est une propriété du texte, apparentée à la taille de la police de caractères : hauteur complète d'une ligne de texte, c'est elle qui détermine l'  interlignage  du texte, l'espacement vertical entre lignes. En rendant les deux identiques on supprime l'interlignage. Normalement ces deux propriétés sont indépendantes mais j'ai observé qu'IE6, sûrement pour simplifier la vie des auteurs de pages Web, limite l'interlignage selon la taille de la police. Donc ceinture ET bretelles, autant imposer les deux.

Une bulle extensible en hauteur

Exactement le même principe, avec les mots width, top et bottom au lieu de height, left et right (ici pas de souci avec IE6 car les largeurs sont fixées, on ne définit pas les hauteurs, il se sent beaucoup mieux). Les deux images :

Demi-bulle haut
16x192 pixels
Très haut corps de bulle et demi-bulle bas
112x192 pixels

Le CSS :

 .infotexte {padding-top:16px; background: transparent url(http:gnagnagna/bulleH.gif) scroll no-repeat top left } .infotexte span {display:block width:176px; padding:0 8px; padding-bottom:16px; background: transparent url(http:gnagnagna/bulleB.gif) scroll no-repeat bottom left } 

Le résultat :

Voici un lien une ligne muni d'une infobulle et un autre lien plusieurs
lignes
et encore une
muni d'une infobulle.

Où ça devient
beau (attention aux bulles ! baissez la tête),
où ça devient beau c'est que le HTML est rigoureusement identique dans ces deux cas, même pas besoin d'une classe supplémentaire tant que le texte ne contient pas à son tour d'autres span. Transformer une bulle horizontale en une verticale ne demande ainsi que des modifications de CSS, c'est toujours plus commode quand on perfectionne le design de son site.

Extensible en hauteur et largeur, mais avec au moins deux coins normaux

Ça, c'est le principe des infobulles dans mes modules. Ce cas est lui aussi IE6-proof.

Bord gauche
12x128 pixels
Corps de bulle et bord droit
376x128 pixels

C'est un hybride de la bulle à un seul coin spécial (mais ici tout le côté G est spécial) et de la bulle extensible en largeur (mais on va gagner de l'élasticité en hauteur). Voici les particularités :

  • chaque image est  infinie  dans une direction verticale, vers le bas ou vers le haut (ici, vers le bas pour les deux images) ;
  • de plus, l'image de D est  infinie  dans une direction horizontale, ici vers la droite (on en a profité pour caser un petit motif jaune en haut à G : coin  spécial ).

Le résultat :

 .infotexte {padding-left:12px; background: transparent url(http:gnagnagna/infiniG.gif) scroll no-repeat top left } .infotexte span {display:block padding: 8px; border-style:solid; border-color: #888; border-width:0 1px 1px 0; background: transparent url(http:gnagnagna/infiniD.gif) scroll no-repeat bottom left } 

Voici un lien un mot avec infobulle et un autre lien Les deux images sont infinies vers le bas.
Celle du texte est  spéciale  en haut à G (motif jaune) et  infinie  à D.
Les bordures viennent fermer les côtés  infinis .
doté d'une infobulle plus copieuse.

En changeant le choix des directions  infinies  on peut produire divers effets, on est cependant obligé de conserver au moins deux coins  normaux .

C'est du chinois ? Voici un autre exemple :

Bord gauche
8x128 pixels
Corps de bulle et bord droit
377x128 pixels
 .infotexte {padding-left:8px;padding-top:6px; background: transparent url(http:gnagnagna/coinsHGBD-G.gif) scroll no-repeat top left } .infotexte span {display:block padding: 10px; border-style:solid; border-color: #888; border-width:1px 0 0 0; background: transparent url(http:gnagnagna/coinsHGBD-D.gif) scroll no-repeat bottom right } 

Toujours un lien un mot avec infobulle et un autre lien Image  infinie  vers le haut et la gauche.
Notez le placement en bottom right
et la définition des bordures,
notez aussi le padding-top ajouté au span principal.
muni d'une infobulle.

Totalement libre

Ce cas-là, je crois que je le garde pour un prochain article : celui-ci est bien assez long, vous ne trouvez pas ?


commentaires

Martine 01/02/2012 22:22

Merci, c'est très gentil à vous.

Demain matin, à tête reposée, je vais faire des essais.

Vous avez de quoi occuper vos loisirs avec cette magnifique bibliothèque bien pleine :-) :-)

Bonne fin de soirée et merci encore.

Martine 01/02/2012 21:02

Bonjour,
Je passe tout à fait par hasard, je cherche un code css pour un demi rond.
Je n'ai pas trouvé mon bonheur, c'est trop "savant" pour mes modestes connaissances mais je voulais juste vous dire que votre fond d'écran m'a vraiment séduite, très original et puis ça bouge,
vraiment super et du pas vu, félicitations !

AïmD ! 01/02/2012 22:10



Merci ! Je ne voudrais pas vous laisser dans la débine, cependant.


CSS3 (non utilisé dans cet article) permet de définir les rayons de courbure des coins. Si on pousse l'idée un peu loin :


un div de dimensions nulles mais avec d'épaisses bordures apparaîtra comme un carré (ou un rectangle) plein, dont les quatre côtés peuvent avoir des couleurs différentes

on peut arrondir les coins de ce carré (avec les propriétés CSS3)

si on arrondit les coins jusqu'à ce que leur rayon soit égal à la largeur de la bordure, on obtient un cercle. Chaque quart du cercle est le raccord de deux bordures.

en mettant à zéro certaines largeurs et certains rayons, on produira un demi-cercle ou un quart de cercle



petit exemple :


.demirond {border:20px solid red;border-width:20px 20px 0 ; border-radius:20px 20px 0 0;width:0;height:0 }


Alors





sera rendu comme un demi-cercle rouge de rayon 20px


Tous les détails CSS3 pour approfondir la question. Bien sûr, je ne
garantis pas que ça marche pour tous les navigateurs. Si vous tenez vraiment à votre demi-cercle, faites une image !


Bon courage et bons essais ;-)



Syl 11/10/2009 20:31


Autant pour moi ! Je n'avais pas réalisé que c'était voulu ! Dans le menu en haut ca marche.

Mais on tombe si souvent sur des tutos qui en fait ne fonctionnent pas ou plus...

Quoiqu'il en soit merci pour cet article, très bien écrit, et votre réponse si rapide.


AïmD ! 11/10/2009 20:55


Tant mieux si ce n'est que ça - je compléterai l'article dans la soirée. Tout ce qu'il faut pour rendre les bulles mobiles est expliqué dans le 1er article (et n'a rien de très sorcier).
La réponse rapide est un pur coup de chance : jouez au Loto, c'est le jour ! Mais il y a toujours une réponse.
Je m'efforce de tenir en état de marche ce que je propose, mais on n'est jamais à l'abri d'une erreur, j'apprécie toujours qu'on me les signale.
Et si, par-dessus le marché, cet article vous a plu, alors... nirvana !


syl 11/10/2009 19:59


Les exemples de la page ne marchent pas sous IE 8. Qu'en pensez-vous ?


AïmD ! 11/10/2009 20:11


Que je voudrais bien avoir une url pour me rendre compte :-)

Sur la page du présent article les bulles ne sont pas 'à éclipse', simplement pour épargner au lecteur de promener son curseur partout (je l'avais précisé dans le précédent article, je
devrais sans doute le rappeler dans celui-ci aussi). Est-ce cela qui vous tracasse ou bien avez-vous un pb pour réaliser cette bulle sur une de vos pages ?

Les bulles du module "Orientation", en haut à d, appliquent cette technique. Elles marchent ?


Archives