Le problème des cadres à coins arrondis est vieux comme le Web. En HTML et CSS, alors qu'il est très simple de faire des cadres rectangulaires qui se redimensionnent tout seuls, il n'existe pas de façon simple de faire le même genre de cadres avec des coins arrondis ou plus généralement des cadres composés d'images.

En attendant la prochaine version de CSS qui devrait apporter une solution propre, il faut se résoudre à utiliser un contournement. Sur ce point il y a deux écoles : ceux qui utilisent des éléments TABLEs et ceux qui utilisent des DIVs avec du CSS. Aucune de ces deux méthodes n'est satisfaisante. La première car elle détourne l'élément TABLE de son usage normal (représenter des données tabulaires). La seconde car elle introduit une multitude d'éléments DIV qui ne portent aucun sens et polluent le HTML. En outre, les inconvénients existent aussi bien du côté client (code HTML pollué donc plus lourd et moins accessible) que du côté serveur (on se retrouve avec du spaghettiware HTML à maintenir).

Cet article présente un exemple d'utilisation d'une technique qui ne résout pas tous ces problèmes mais qui permet de faciliter la maintenance du code HTML. Cet exemple ne prend pas non plus parti dans la querelle des pro-DIV contre les pro-TABLE, mais arbitrairement, il s'appuie sur un layout en TABLEs. L'objectif est d'avoir un code HTML non pollué par la mise en forme, du point de vue du développeur (on ne peut hélas pas grand chose pour le client...).

Le principe consiste à utiliser du Javascript pour décorer le code HTML en ajoutant là où on le souhaite les fameux cadres à coins arrondis. Pour développer commodément la chose et s'assurer de la portabilité du code, le recours à la librairie Prototype n'est pas inintéressant, aussi ne s'en privera-t-on pas.

Voici donc une page d'exemple : page_sans_cadre.html dont le code source est le suivant :

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="fr_FR">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<p>Ceci est une page qui parle pour ne rien dire</p>
<div class="important">
<p>Ceci est une zone encadrée que j'aimerais bien voir encadrée</p>
<p>Et puis, je préfère les coins arrondis car c'est plus joli !</p>
</div>
<p>Ceci est le bas de la page...</p>
</body>
</html>

Le but du jeu est de faire un cadre à bord arrondis autour de la section importante (celle de class "important"). On peut bien sûr faire cela directement dans le code HTML, à coups de TABLE et CSS et en utilisant des images pour le cadre. On aboutit au code HTML suivant :

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html lang="fr_FR" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link href="./cadre.css" type="text/css" rel="stylesheet" />
</head>
<body>
<p>Ceci est une page qui parle pour ne rien dire</p>
<table>
<tbody>
<tr>
<td class="coin_haut_gauche"/>
<td class="bord_haut"/>
<td class="coin_haut_droit"/>
</tr>
<tr>
<td class="bord_gauche"/>
<td class="coeur'>
<div class="important">
<p>Ceci est une zone encadrée que j'aimerais bien voir encadrée</p>
<p>Et puis, je préfère les coins arrondis car c'est plus joli !</p>
</div>
</td>
<td class="bord_droit"/>
</tr>
<tr>
<td class="coin_bas_gauche"/>
<td class="bord_bas"/>
<td class="coin_bas_droit"/>
</tr>
</tbody>
</table>
<p>Ceci est le bas de la page...</p>
</body>
</html>

avec la feuille style suivante : cadre.css

Le résultat peut être visualisé ici : page_avec_cadre.html

Cela fonctionne, mais le fichier a doublé de volume, et c'est un devenu un cauchemar pour celui qui doit maintenir ce code...

La technique de décoration avec Javascript permet de revenir à un code très voisin du code d'origine. C'est en Javascript que le DOM sera modifié pour ressembler au code complexe ci-dessus. Avec Prototype, il suffit de quelques lignes pour enrober dans une table la section "importante". Voici le code utilisé :

function decore(){
	var element = $$('.important')[0];
	var td = element.wrap('td');
	td.addClassName('coeur');
	var tr= td.wrap('tr');
	td.insert({before : '<td class="bord_gauche"></td>'});
	td.insert({after : '<td class="bord_droit"></td>'});
	var tbody = tr.wrap('tbody');
	tbody.wrap('table');
	tr.insert({before : '<tr><td class="coin_haut_gauche"></td><td class="bord_haut"></td><td class="coin_haut_droit"></td></tr>'});
	tr.insert({after : '<tr><td class="coin_bas_gauche"></td><td class="bord_bas"></td><td class="coin_bas_droit"></td></tr>'});
}
Event.observe(window,'load',decore,false);

Voici la nouvelle forme du fichier HTML :

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="fr_FR">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<script type="text/javascript" src="./prototype.js"></script>
<script type="text/javascript" src="./test.js"></script>
<link href="./test.css" type="text/css" rel="stylesheet" />
</head>
<body>
<p>Ceci est une page qui parle pour ne rien dire</p>
<div class="important">
<p>Ceci est une zone encadrée que j'aimerais bien voir encadrée</p>
<p>Et puis, je préfère les coins arrondis car c'est plus joli !</p>
</div>
<p>Ceci est le bas de la page...</p>
</body>
</html>

Vous remarquerez que l'on est revenu à une structure simple, non polluée par la mise en forme. Seule différence avec le code d'origine : les deux entités script de l'entête et bien sûr la feuille de style. Le résultat peut être vu ici : page_avec_cadre_decore.html