La propriété CSS3 calc() pour arrêter avec les balises HTML imbriquées inutilement

Dans de nombreux cas, on utilise des balises superflus pour gérer ;

  • la largeur total d'une grille avec les éléments externes et
  • l'espacement entre chaque balise avec l'élément interne. Parfois même,
  • pour appliquer de la couleur de fond, on utilise une troisième balise !

C'est notamment le cas avec le framework CSS Bootstrap qui se fait vieux. Si vous vous ventez de ne plus suporter IE8 parce qu’il à fait son temps, alors il est également temps d'arrêter d'utiliser des balises inutiles !

Voici un exemple d'ancienne pratique et son équivalence avec la propriété CSS3 calc().

La Grille

Exemple old school à la Bootstrap

HTML :

Avec le HTML suivant :

<div class="container">
    <div class="row">
        <div class="col-xs-4">
            <div class="item">Zone 1</div>
        </div>
        <div class="col-xs-4">
            <div class="item">Zone 2</div>
        </div>
        <div class="col-xs-4">
            <div class="item">Zone 3</div>
        </div>
    </div>
    <div class="row">
        <div class="col-xs-6">
            <div class="item">Zone 4</div>
        </div>
        <div class="col-xs-6">
            <div class="item">Zone 5</div>
        </div>
    </div>
</div>

et avec la CSS suivante :

CSS :

* {
    box-sizing: border-box;
}
.container {
    max-width: 1200px;
    padding-left: 15px;
    padding-right: 15px;
    margin-bottom: 15px;
}
.row {
    margin-top: 15px;
    margin-left: -15px;
    margin-right: -15px;
}
.row:after {
    content: "";
    display: block;
    clear: left;
}
.col-xs-6 {
    padding-left: 15px;
    padding-right: 15px;
    width: 50%;
    float: left;
}
.col-xs-4 {
    padding-left: 15px;
    padding-right: 15px;
    width: 33.33333333%;
    float: left;
}
.item {
    background-color: #e8e8e8;
    padding: 15px;
}

nous obtenons :

Résultat :

Zone 1
Zone 2
Zone 3
Zone 4
Zone 5

Même exemple avec calc() en CSS3

Avec le HTML suivant :

HTML :

<ul class="component">
    <li>Zone 1</li>
    <li>Zone 2</li>
    <li>Zone 3</li>
    <li>Zone 4</li>
    <li>Zone 5</li>
</ul>

et avec la CSS suivante :

CSS :

* {
    box-sizing: border-box;
}
.list {
    padding: 0;
    max-width: 1200px;
    margin-top: 0;
    margin-bottom: 15px;
    margin-left: -15px;
    margin-right: -15px;
    list-style-type: none;
}
.list:after {
    content: "";
    display: block;
    clear: left;
}
.list li {
    margin-top: 15px;
    background-color: #e8e8e8;
    padding: 15px;
    float: left;
    margin-left: 15px;
    margin-right: 15px;
}
.list li:nth-child(n+5) {
    width: calc(50% - 30px);    
}
.list li:nth-child(n+3) {
    width: calc(33.33333333% - 30px);    
}

nous obtenons :

Résultat :

  • Zone 1
  • Zone 2
  • Zone 3
  • Zone 4
  • Zone 5

À propos de calc()

La grande force de calc() en CSS3 est qu'elle est capable de mélanger le calcul de plusieurs unités en même temps, et en temps réel. Cela permet en plus de conserver des proportions bonnes dès que la fenêtre change de taille.

Support des navigateurs

Support IE9

Comme dit en introduction, si vous souhaitez supporter calc() pour des versions plus vieille que IE8, il va falloir vous procurer un polyfill comme celui-ci. En ce qui concerne IE9, il est mentionné qu'elle est partiellement supportée. En réalité, cela vient du fait que si vous écrivez calc(50%-30px) cela fonctionnera partout sauf sur IE9 ou il faut bien mettre des espaces entre les symboles d'opération comme ceci : calc(50% - 30px).

Support propriétaire

Vous pouvez également supporter des versions plus vieille de la plupard des navigateurs avec les extensions propriétaires suivantes :

width: -webkit-calc(50% - 100px);
width:    -moz-calc(50% - 100px);
width:         calc(50% - 100px);

Support Less

En Less, la propriété calc() existe aussi, et c'est peut-être elle qui vous avait fait échouer vos tests si vous aviez déjà tenté le mélange d'unité car elle est incapable de le faire, aussi : width: calc(50% - 30px); donnera en sortie CSS width: 20%. Qui plus est, le calcul n'est pas effectué en temps réel. Pour réellement utiliser la propriété calc() CSS3 il va falloir écrire width: calc(~'50% - 30px'); ce qui donnera en sortie CSS width: calc(50% - 30px);.

Pour en savoir plus

Si vous voulez en savoir plus sur calc() et ses subtilités c'est par ici.

À vous de jouer !