02
Dec
2017

Casse-tête CSS

Par Manu ·  Etiquette(s) : CSS

Le problème

Un ami m'a envoyé le problème de CSS suivant :

J'ai un souci HTML/CSS avec IE11 (forcément…). Pas de souci sous Chrome ou Firefox.

Ce dont j'ai besoin, c'est d'avoir ça (affichage de Firefox):

C'est à dire une colonne qui fait toute la hauteur de la page, une ligne de header de hauteur limitée, et un bloc "contenu" qui est collé en haut.

IE me fait ça :

Le code :

<table style="" width="100%">  
    <tr>
        <td rowspan="2" style="width: 112px" valign="top">
            <div style="display:block;">
                Lorem ipsum […]
            </div>
        </td>
        <td style="width: 50%; height: 40px;" valign="top" align="left">
            Header 1
        </td>
        <td align="right" style="width: 50%; height: 40px;" valign="top">
            Header 2
        </td>
    </tr>
    <tr>
        <td valign="top" colspan="2">
            <span>Contenu de ma page</span>
            <div>
                […]
            </div>
        </td>
    </tr>
</table>  

IE semble ignorer la hauteur des cellules définies et semble interpréter height: 40px comme height: 40%. Chelou.

Ce problème en apparence simple cache quelques joyeusetés du développement web.

Apparté(s)

Du point de vue de la sémantique, il est nécessaire de préciser que ce code est horrible. Il faudrait par exemple utiliser des <th> plutôt que des <td> pour faire les headers. En même temps, vu qu'on est en train d'utiliser une <table> pour faire de la mise en page, on ne va pas pinailler :)

Une autre bonne pratique™ serait d'utiliser un CSS Reset, voire un CSS Normalizer : ce sont des feuilles de style qui gomment les différences entre les styles par défaut des différents navigateurs. J'ai d'abord pensé que le problème venait de là, mais malheureusement ces feuilles de styles ne changent rien au problème.

Début de solution :

Je commence par retirer les attributs deprecated tels que align ou valign. Aujourd'hui il faut tout faire dans style, comme l'indique ce tableau de css-tricks :

Deprecated Attributes, css-tricks.com

En faisant ces modifications, j'obtiens alors :

<td style="vertical-align: top; width: 50%; height: 40px; float: left;">  
    Header 1
</td>  
<td style="vertical-align: top; width: 50%; height: 40px; float: right;">  
    Header 2
</td>  

ce qui me donne :

C'est mieux 👍.

Il y a un petit souci de largeur des cases : En effet, les 2 <td> sont trop larges pour rentrer dans la ligne : le « 50 % » veut dire « 50 % de la largeur de la table », et on a déjà la largeur de la première colonne qui mange quelques pourcents.

En réduisant un peu leur largeur :

<td style="vertical-align: top; width: 49.6%; height: 40px; float: left;">  
    Header 1
</td>  
<td style="vertical-align: top; width: 49.6%; height: 40px; float: right;">  
    Header 2
</td>  

On obtient :

« Et là vous allez me dire, il reste un cratère. » #LesNuls

Épilogue tragique :

C'est à ce moment-là que je me rends compte que c'est la première colonne, avec son rowspan=2, qui nous met dans le [poop emoji]. Pour IE, les 2 lignes doivent avoir la même hauteur, même si on précise autre chose (Chrome & Firefox ont fait un choix différent).

Mais comment est-ce possible, il n'y a pas de spec. ? Eh bien non, il n'y en a pas :

(j'ai trouvé le lien suivant sur Stackoverflow, en réponse à une question du même genre : https://stackoverflow.com/a/19703263/113305 )

CSS 2.1 does not define how the height of table cells and table rows is calculated when their height is specified using percentage values. CSS 2.1 does not define the meaning of 'height' on row groups.

https://www.w3.org/TR/CSS21/tables.html#height-layout

Pas de spec., donc chaque navigateur fait ce qu'il veut.

👉 La solution la plus simple au problème initial est donc de séparer la zone à gauche du reste du tableau.

Manu