web-dev-qa-db-fra.com

3 divs en ligne avec une largeur exacte de 33% convenant pas au parent

C'est un problème courant, mais je ne comprends pas pourquoi cela se produit.

J'ai un div parent et à l'intérieur de ce div j'ai 3 divs avec largeur définie à 33% (exactement, pas 33,3%!) Et display: inline-block.

Cela fonctionne bien dans Chrome, mais pas dans Mozilla et Opera (je ne l'ai pas encore testé dans IE). Je pensais que le problème pourrait être lié à l'algorithme utilisé par les navigateurs pour calculer le dimensionnement des pixels à partir de pourcentages. Mais lorsque j'ai vérifié les mesures DOM, j'ai constaté que la largeur du parent était de 864 pixels et celle de l'enfant de 285 pixels (c'est exact: 864 * .33 = 285.12). Mais pourquoi ne convient-il pas au parent? 285 * 3 = 855, soit 9 pixels de moins que la largeur du parent!

Oh, oui, le remplissage, la marge et la bordure de tous les divs sont réglés sur 0 et les métriques DOM le confirment.

18
Roman Bekkiev

Espace dans le code source HTML

Dans le code source HTML, lorsque vous avez des lignes de texte ou d'images, ou des éléments qui sont inline-block, s'il y a un espace entre eux (espaces vides, onglets ou nouvelles lignes), un seul caractère d'espace vide est ajouté entre eux la page est rendue. Par exemple, dans le code HTML suivant, un espace vide apparaîtra entre chacun des quatre éléments de contenu:

one
two
<img src="three.png"/>
<span style="display: inline-block;">four<span>

Ceci est très utile pour les lignes de texte, ainsi que pour les petites images ou les éléments HTML qui apparaissent à l'intérieur d'une ligne de texte. Mais cela devient un problème lorsque inline-block est utilisé à des fins de mise en page, plutôt que comme moyen d’ajouter du contenu dans un paragraphe de texte.

Suppression de l'espace supplémentaire

Le moyen le plus sûr et multi-navigateur d'éviter les 4 pixels supplémentaires, entre les éléments inline-block, consiste à supprimer les blancs du code source HTML entre les balises HTML.

Par exemple, si vous avez une ul avec 3 balises flottantes li:

<-- No space, tabs, or line breaks between </li> and <li> -->
<ul>
    <li>...</li><li>...</li><li>...</li>   
</ul>

Malheureusement, la maintenance du site Web est compromise. En plus de rendre le code illisible, il compromet gravement la séparation des données et le formatage.

Si un autre programmeur se présente plus tard et décide de placer chaque balise li sur une ligne distincte du code source (ignorant pourquoi les balises se trouvaient sur la même ligne, ou éventuellement en l'exécutant via HTML Tidy, sans même avoir la possibilité de remarquer les modifications associées. Commentaires HTML), le site Web a soudainement un bogue de mise en forme qui peut être difficile à identifier.

Considérons plutôt les éléments flottants

Le comportement des espaces blancs suggère fortement qu'il peut ne pas être approprié d'utiliser inline-block à des fins de mise en page générales, de l'utiliser pour autre chose que l'ajout de contenu dans le flux d'un paragraphe de texte.

De plus, dans certains cas, le contenu de inline-block est très difficile à styler et à aligner, en particulier sur les anciens navigateurs. 

Résumé rapide d'autres solutions

  1. Placez la balise de fermeture sur la même ligne que la balise ouverte suivante, sans espace entre eux.
  2. Utilisez les commentaires HTML pour remplir tous les espaces entre la balise de fermeture et la balise ouverte suivante (comme suggéré par @Arbel).
  3. Ajoutez une marge gauche négative à chaque élément (généralement -3px ou -4px, en fonction de la taille de la police). Je ne recommande pas cette approche particulière.
  4. Définissez le font-size pour l'élément conteneur sur 0 ou 0.01em. Cela ne fonctionne pas dans Safari 5 (pas sûr des versions ultérieures) et peut interférer avec les sites Web Responsive Design, ou avec tout autre site Web utilisant une unité font-size autre que px.
  5. Supprimez les nœuds de texte ne contenant que des espaces du conteneur à l'aide de JavaScript ou de jQuery. Cela ne fonctionne pas dans IE8 et les versions antérieures, car les nœuds de texte ne sont pas créés dans ces navigateurs lorsqu'il n'y a que des espaces entre les éléments, même si de l'espace est toujours ajouté entre les éléments.
  6. Définissez letter-spacing et Word-spacing pour le conteneur (comme suggéré par @PhillipWills). Plus d'infos . Cela nécessite la normalisation de em tailles sur le site Web, ce qui peut ne pas être une option raisonnable pour tous les sites Web.
  7. Ajoutez text-space-collapse: discard; au conteneur (précédemment appelé white-space-collapse). Malheureusement, ce style CSS3 n'est pas encore supporté par les navigateurs, et la norme n'a pas été complètement définie.
38
Matt Coughlin

Si vous ne voulez pas gâcher le formatage HTML, par exemple, en ayant tous les éléments avec inline-block écrits sur une seule ligne pour une meilleure lisibilité et également supprimer l'espace blanc supplémentaire ajouté entre eux, vous pouvez "commenter" l'espace blanc.

Par exemple, dans votre code, cela résoudra le problème, cela fonctionnera même avec 33,3% au lieu de 33%:

.parent {
    width: 100%;
 }
.child{
    display: inline-block;
    width: 33.3%;
}

/ \

<div class="parent">
       <div class="child">bla-bla1</div><!-- 
    --><div class="child">bla-bla2</div><!-- 
    --><div class="child">bla-bla3</div>
</div>
6
Arbel

Ajouter float:left;

.parent{
    width: 100%
}
.child{
    float:left;
    display: inline-block;
    width: 33%

}

http://jsfiddle.net/H6Whc/1/

4
Avin Varghese

Un espace est ajouté entre les divs internes. Il y a du CSS voodoo pour corriger ce problème:

div {
    letter-spacing: -.31em;
    Word-spacing: -.43em;
}
div div {
    letter-spacing: normal;
    Word-spacing: normal;
}

Bien sûr, vous préférerez probablement utiliser des classes ou quelque chose pour différencier les parents des enfants.

4
philwills

Quelqu'un at-il essayé d'afficher: table? Si ce n'est pas une bonne idée, pourquoi pas? Cela fonctionne dans tous les navigateurs modernes et je l'ai testé jusqu'à IE9.

.parent{  
    display: table;
    width: 100%;
}
.containers {
    box-sizing: border-box;
    border: 1px solid #000;
    height: 50px;
    width: 33.3%;
    display: table-cell;
}
2
eaglejs

Ceci est mentionné par un certain nombre de commentaires et par @Avin, mais supprimer display: inline-block et le remplacer par float: left fonctionne.

.parent{
    width: 100%
}
.child{
    float:left;
    width: 33%
}
1
bvpb