La gestion des marges internes

Voici le code html qui va nous servir d'exemple :

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
	<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
	<title>test1</title>
	
	<style type="text/css" media="screen">
	
		body{
			margin:1em;
			padding:0;
			border:1px solid #F00;
		}
		
		p{
			margin:2em 0;
			background:#CCC;
		}
		
		strong{
			padding:10px;
			border:1px solid #00F;
		}
		
		a{
			padding:10px;
			border:1px dotted #F00;
			color:#00F;
		}
		
	</style>	
</head>
<body>
	
	<p>
		Lorem ipsum <strong><a href="#">dolor</a></strong> sit amet
	</p>
	
</body>

Cet exemple contient donc un paragraphe, dans lequel se trouve une emphase (strong) qui elle-même contient un lien, soit deux éléments en ligne imbriqués. En appliquant comme ici un padding de 10px sur l'élément strong et sur l'élément a, voici ce que l'on obtient sous Firefox :

Résultat sous Firefox

Et voici la même page sous Internet Explorer (6 et 7, même combat) :

Résultat sous IE

On constate ainsi plusieurs choses :

  • Un padding appliqué à un élément en ligne ne repousse pas les boites voisines (y compris les blocs parents)
  • Firefox (idem pour Opera et Safari) respecte ce principe, et donc les padding verticaux sur des éléments en ligne imbriqués se superposent
  • Sur IE au contraire ils s'ajoutent
  • Sur IE, un élément en ligne ne peut pas s'afficher en dehors d'un bloc parent possédant le layout (ici le body, entouré en rouge)

Ce dernier point peut être vérifié en forçant le layout sur le paragraphe conteneur (avec une propriété zoom:1), voici alors ce que l'on obtient :

Résultat sous IE, attention au layout !

Alors comment faire ?

Cette différence de rendu est plutôt contraignante et ne peux pas être résolue sans utiliser des styles différents pour IE et le reste du monde. Pas le choix, il va falloir annuler pour IE les paddings verticaux sur l'élément strong, pour éviter qu'ils ne s'ajoutent à ceux du lien. Encore une fois, les commentaires conditionnels sont à privilégier pour ce genre de chose :

<!--[if lte IE 7]>
<style type="text/css">		
	strong{
		padding-top:0;
		padding-bottom:0;
	}
</style>
<![endif]-->

Reste ensuite le problème du débordement, que l'on va régler en fixant la hauteur de ligne au niveau de l'élément strong, dans le code CSS principal. Vous pouvez calculer cette hauteur en additionnant la hauteur de ligne du lien + ses paddings haut et bas + un espace supplémentaire pour que le texte au dessus ou en dessous ne soit pas trop collé à l'élément.

strong{
	line-height:4em;
}

On assure ainsi que la boite crée par l'élément strong sera toujours à l'intérieur du bloc parent et que les lignes du dessous ne chevaucheront pas cet élément. Le résultat est maintenant identique sur tous les navigateurs :

Le résultat final

Mise en pratique

Une application assez courante est la création de boutons, à partir d'un lien, d'un span et de 2 images de fond :

Le bouton final

Voici le code html nécessaire :

<p>
  Cliquez sur ce bouton :  <a class="bouton"><span>Click me !</span></a>
</p>

Et ensuite le code CSS correspondant :

a.bouton{
	background:url("bouton-left.png") no-repeat center left;
	padding:12px 0 12px 20px;
	color:#666;
	line-height:4em;
}
a.bouton span{
	background:url("bouton-right.png") no-repeat center right;
	padding:12px 20px 12px 0;
}
a.bouton:hover{
	color:#000;
}

Et pour IE :

a.bouton{
	padding-top:0;
	padding-bottom:0;
}

Et voilà le travail, vous pouvez voir le résultat en ligne.