51 votes

Pourquoi la hauteur de ligne sans unité se comporte-t-elle différemment du pourcentage ou du em dans cet exemple ?

Je suis perplexe quant au comportement du CSS suivant, également illustré dans ce violon .

<style type="text/css">
p {
    font-size: 14px;
}

.percentage {
    line-height: 150%;
}

.em-and-a-half {
    line-height: 1.5em;
}

.decimal {
    line-height: 1.5;
}

.smaller {
    font-size:50%;
}

.caption {
    font-weight: bolder;
    font-size: 80%;
}

</style>

<p class="caption">default line spacing</p>

<p>This tutorial provides a brief introduction to the
programming <span class="">language</span> by using one of its picture-drawing
libraries. This tutorial provides a brief introduction to the programming language. This tutorial provides a brief introduction to the programming language.</p>

<p>This tutorial provides a brief introduction to the
programming <span class="smaller">language</span> by using one of its picture-drawing
libraries. This tutorial provides a brief introduction to the programming language. This tutorial provides a brief introduction to the programming language.</p>

<p class="caption">line-height: 150%</p>

<p class="percentage">This tutorial provides a brief introduction to the
programming <span class="">language</span> by using one of its picture-drawing
libraries. This tutorial provides a brief introduction to the programming language. This tutorial provides a brief introduction to the programming language.</p>

<p class="percentage">This tutorial provides a brief introduction to the
programming <span class="smaller">language</span> by using one of its picture-drawing
libraries. This tutorial provides a brief introduction to the programming language. This tutorial provides a brief introduction to the programming language.</p>

<p class="caption">line-height: 1.5em</p>

<p class="em-and-a-half">This tutorial provides a brief introduction to the
programming <span class="">language</span> by using one of its picture-drawing
libraries. This tutorial provides a brief introduction to the programming language. This tutorial provides a brief introduction to the programming language.</p>

<p class="em-and-a-half">This tutorial provides a brief introduction to the
programming <span class="smaller">language</span> by using one of its picture-drawing
libraries. This tutorial provides a brief introduction to the programming language. This tutorial provides a brief introduction to the programming language.</p>

<p class="caption">line-height: 1.5</p>

<p class="decimal">This tutorial provides a brief introduction to the
programming <span class="">language</span> by using one of its picture-drawing
libraries. This tutorial provides a brief introduction to the programming language. This tutorial provides a brief introduction to the programming language.</p>

<p class="decimal">This tutorial provides a brief introduction to the
programming <span class="smaller">language</span> by using one of its picture-drawing
libraries. This tutorial provides a brief introduction to the programming language. This tutorial provides a brief introduction to the programming language.</p>

Les deux premiers paragraphes ont un interlignage par défaut. Dans le deuxième paragraphe, un mot est plus petit. Mais cela n'affecte pas l'interlignage dans ce paragraphe. Non pas que cela devrait, mais

Les deux paragraphes suivants ont line-height: 150% . Encore une fois, le deuxième paragraphe a un mot qui est plus petit. Mais cette fois, pour des raisons peu claires, la police plus petite crée un espace supplémentaire entre les deux premières lignes (du moins dans Safari, Chrome, Firefox et Explorer). C'est le problème original dans mon CSS que j'essayais de corriger. (Je suppose que cela a quelque chose à voir avec le fait que le navigateur rétrécit le mot et le décale ensuite verticalement vers le bas pour réaligner les lignes de base).

Les deux paragraphes suivants ont line-height: 1.5em . Je crois savoir que 1.5em est la même chose que 150% . Et effectivement, le comportement est le même : espace supplémentaire entre les deux premières lignes du deuxième paragraphe.

Mais c'est là que ça devient bizarre les deux paragraphes suivants ont line-height: 1.5 - aucune unité n'est spécifiée. Cette fois, le problème de l'extra-espace disparaît.

En résumé, CSS semble donner des résultats cohérents en matière d'interlignage lorsque les hauteurs de ligne du parent et de l'enfant sont différentes (par héritage de la valeur sans unité), mais des résultats incohérents lorsque les hauteurs de ligne du parent et de l'enfant sont identiques.

D'où mes questions :

  1. Je sais qu'il y a une différence sémantique intentionnelle. dans la spécification CSS entre 1.5 y 150% ou son synonyme, 1.5em . (À savoir : une valeur sans unité est transmise à l'élément enfant et sa hauteur de ligne est calculée à l'aide de la taille de la police de l'enfant, alors qu'une valeur en pourcentage ou em entraîne le calcul d'une hauteur de ligne pour le parent, puis cette valeur calculée est transmise à l'enfant). Mais comment cela explique-t-il la différence de comportement observée ici ? D'où vient l'espace supplémentaire ? S'il s'agit d'une conséquence d'une règle de positionnement CSS, quelle est cette règle ?

  2. Ou, si ces exemples doivent tous s'afficher de la même manière, lequel est implémenté de manière incorrecte ? (Note sur Q2 : Le fait que la bizarrerie de l'affichage se produise de la même manière sur différents navigateurs suggère fortement qu'aucun d'entre eux n'est implémenté de manière incorrecte, ce qui vous ramène à la question (1)).

  3. En termes pratiques, y a-t-il un inconvénient à passer à des mesures sans unité comme 1.5 para line-height ? (Réponse : non)

39voto

Matthew Butterick Points 301

Sur la base d'indices dans les réponses proposées, je pense que le comportement de rendu vu dans ces exemples est contre-intuitif, mais correct, et mandaté par l'interaction de plusieurs règles dans la spécification, et l'ensemble des règles de l'UE. Modèle de boîte CSS .

  1. CSS calcule le L de tête nécessaire pour une boîte par la formule suivante line-height = L + AD, où AD est "la distance entre le sommet et le site bas" de la police. Ensuite, "la moitié de l'avance est ajoutée au-dessus de A et l'autre moitié au-dessous de D". moitié en dessous de D". Donc le texte qui a font-size:16px et line-height:24px aura 4px d'avance au-dessus et au-dessous. Texte que font-size:8px y line-height:24px aura 8px d'avance au-dessus et en dessous.

  2. Par défaut, cependant, "L'agent utilisateur doit aligner les glyphes ... par leur pertinents lignes de base". . Cela commence à expliquer ce qui se passe ici. Quand line-height est spécifié par un pourcentage ou un em, une valeur calculée est héritée par le enfant (ici, le smaller span). Autrement dit, le smaller l'étendue obtient la même line-height comme le bloc parent. Mais à cause de la formule L + AD, le texte de ce span a plus d'avance en haut et en bas. et en bas, et donc la ligne de base se trouve plus haut dans sa boîte. Le navigateur pousse la ligne de base vers le bas. smaller s'étendent verticalement pour correspondre aux lignes de base.

  3. Mais alors le navigateur a un nouveau problème - comment traiter la ligne l'espacement des lignes dans le bloc englobant, qui a été perturbé par ce processus d'ajustement de la ligne de base. processus d'ajustement de la ligne de base. La spécification résout également ce problème : le line-height d'un élément de niveau bloc "spécifie la hauteur minimale des cases de ligne dans l'élément l'élément" . Ce qui veut dire que CSS ne promet pas que vous obtiendrez votre exact line-height juste que vous obtiendrez au moins ce montant. Ainsi, le navigateur écarte les lignes dans le bloc englobant pour que le pour que le bloc enfant réaligné s'adapte.

La raison pour laquelle cela est contre-indiqué est que c'est le contraire du fonctionnement de la plupart des traitements de texte et des programmes de mise en page. Dans ces programmes, une plus petite portion de texte dans un paragraphe est alignée par sa ligne de base (comme CSS), mais la hauteur de ligne est imposée comme une distance entre les lignes de base, et non comme une boîte entourant le plus petit texte. Mais il ne s'agit pas d'un bogue - CSS est conçu autour d'une ligne de base. modèle de boîte . Donc, en fin de compte, nous pourrions dire que ce comportement d'espacement est une conséquence de ce modèle.

Il nous reste donc à expliquer le comportement de l'exemple avec la hauteur de ligne sans unité :

  1. Tout d'abord, notez que lorsque aucun line-height est spécifié, le navigateur appliquera par défaut une hauteur de ligne sans unité. Cette valeur est requis par le site spec : la valeur initiale de line-height es normal qui est défini comme suit a "la même signification que <number>", et la spécification recommande une valeur de valeur "entre 1.0 et 1.2". Et cela est cohérent avec ce que nous voyons dans les exemples ci-dessus, où les paragraphes avec line-height: 1.5 ont le même comportement que les paragraphes sans réglage de la hauteur de ligne (c'est-à-dire qu'ils obtiennent implicitement line-height: normal )

  2. Comme d'autres l'ont souligné, lorsque le paragraphe a line-height: 1.5 la hauteur de ligne calculée du paragraphe est de n'est pas héritée par le smaller l'étendue. Au contraire, le smaller span calcule sa propre hauteur de ligne en fonction de sa propre taille de police. Lorsque le paragraphe a line-height: 1.5; font-size: 14px alors son hauteur de ligne calculée est de 14px * 1,5 = 21px. Et si le smaller span n'a que la propriété font-size: 50% alors sa taille de police est 14px * 50% = 7px, et sa hauteur de ligne est de 7px * 1,5 = 10,5px (qui sera généralement arrondie à un pixel entier). Mais globalement, le smaller est la moitié de la taille du texte environnant.

  3. Comme précédemment, le navigateur alignera verticalement l'élément smaller span to la ligne de base adjacente. Mais cette fois, parce que la boîte autour de smaller est plus court que le texte environnant, ce réalignement n'a pas d'effets secondaires dans le bloc qui l'entoure. Il est déjà Il n'est donc pas nécessaire d'étaler les lignes du paragraphe parent, comme c'était le cas auparavant. comme c'était le cas auparavant.

Les deux cas représentent une implémentation cohérente de la spécification. C'est une bonne nouvelle, car cela signifie que nous pouvons prédire le comportement de l'espacement des lignes.

Cela nous ramène à la raison initiale de cette question. Bien que je comprenne maintenant que le modèle de boîte CSS exige ce comportement, en tant que typographe pratiquant, c'est rarement le comportement que je souhaite. Ce que je veux, c'est que les lignes d'un paragraphe aient un interlignage cohérent et exact, même si certaines parties du texte de ce paragraphe sont plus petites.

Malheureusement, il semble qu'il n'y ait aucun moyen d'imposer directement un interlignage exact dans les CSS comme on peut le faire dans un traitement de texte ou un programme de mise en page. Encore une fois, cela est dû au modèle de boîte CSS : il n'utilise pas de modèle d'interligne de base à base, et line-height est spécifié comme étant une mesure minimale, et non maximale.

Mais nous pouvons au moins dire que les valeurs de hauteur de ligne sans unité donnent les meilleurs résultats. approximation de l'espacement exact des lignes en CSS. Les typographes pointilleux comme moi devraient se sentir à l'aise de les utiliser, car les valeurs sans unité sont approuvé par le spec et ils produisent des résultats cohérents sur tous les navigateurs. Il ne s'agit pas d'un piratage, et elles ne sont pas dépréciées.

Le problème est qu'il ne s'agit toujours que d'une approximation. Les valeurs de hauteur de ligne sans unité ne modifient pas le modèle de boîte CSS sous-jacent, ni les règles de positionnement des boîtes CSS. Il est donc possible que dans certains cas limites, elles n'aient pas le résultat escompté. Mais la vigilance éternelle est le prix d'une bonne typographie. Soyez prudent.

5voto

Tom Pietrosanti Points 2299

EDIT

J'ai créé un codepen pour démontrer la conduite qui est créée en utilisant les différentes valeurs . J'espère que cela fournit une meilleure explication.


Je peux répondre à vos questions, mais seulement émettre une théorie (à ce stade) sur l'espacement supplémentaire que vous voyez (et fournir une solution de contournement potentielle).

Vos questions

Y a-t-il une différence sémantique intentionnelle en CSS entre 1,5 et 150 % qui explique la différence de comportement ?

Il y en a un, en fait !

Le facteur numérique (1,5 dans ce cas) est hérité et utilisé pour calculer la hauteur de ligne de chaque descendant, par rapport à sa taille de police.

Le facteur de pourcentage (150 %) est utilisé pour calculer la hauteur de ligne en fonction de la taille de la police de l'élément parent. La valeur résultante, précalculée, est ensuite héritée par ses descendants.

Ou, s'ils sont censés être identiques, lequel des deux est mis en œuvre de manière incorrecte ?

Ils sont intentionnellement différents. (Voir le Spécification du W3C )

En termes pratiques, y a-t-il un inconvénient à passer à des décimales brutes comme 1,5 pour la hauteur de ligne ?

En général, il est avantageux d'utiliser les valeurs décimales, car la hauteur de ligne héritée s'adaptera mieux. Mais il y a des cas où cela ne conviendra pas à vos besoins.


Problème d'espacement supplémentaire

J'ai remarqué que si je mets vertical-align sur votre petit texte pour middle o bottom le problème ne se pose pas. Mais ce n'est pas une très bonne solution.

Je suis deviner Cela est dû au fait que le plus petit texte utilise la hauteur de ligne calculée par héritage, ainsi que son emplacement sur la ligne. Étant donné que le texte est plus petit et qu'il est placé plus bas, mais qu'il a la même hauteur de ligne que la ligne qui l'entoure, le demi-alignement inférieur va en fait être poussé plus bas, et le demi-alignement supérieur ne sera pas aussi haut que le texte qui l'entoure.

Disons que la taille de la police de base est de 16px et que la hauteur de ligne est de 24px. L'avance sera de 4px de chaque côté ((24-16)/2). Lorsque la taille de la police est de 50 %, elle est de 8px, mais la hauteur de ligne reste de 24px. L'interlignage devient donc de 8px de chaque côté ((24-8)/2).

Les lignes de base du texte seront alignées, de sorte que, toutes choses égales par ailleurs, le texte plus petit devrait se situer 4px en dessous du texte normal. Mais comme le texte (et la zone de contenu correspondante) est plus petit, la demi-ligne de base commence plus loin en arrière, ce qui explique pourquoi vous ne voyez qu'un pixel ou deux de changement, et seulement à certains pourcentages (qui augmentent à mesure que vous rétrécissez - essayez).

Je devrais vraiment utiliser des images pour cela, mais je ne peux pas pour le moment... je pourrai peut-être en ajouter plus tard.

Je ne sais pas si ça aide du tout, mais j'ai définitivement une meilleure compréhension de comment line-height travaille en général maintenant !

Références : http://www.w3.org/wiki/CSS/Properties/line-height http://meyerweb.com/eric/thoughts/2006/02/08/unitless-line-heights/ http://www.maxdesign.com.au/articles/css-line-height/

0voto

klick.klonk Points 340

Il semble que la réponse simple à votre question serait : héritage . line-height: 150% y line-height: 1.5em dans votre exemple hérite de la valeur informatique de son parent, alors qu'une valeur numérique ne le fait pas.

Dans votre exemple, le parent <p> a une hauteur de ligne de 21px, si vous utilisez le pourcentage ou ems pour spécifier la hauteur de ligne de votre élément imbriqué <span class="small"> elle sera calculée sur la base de la valeur calculée héritée de 21px ; 21*1,5 = 31,5, mais si vous utilisez la valeur numérique pour la hauteur de ligne, elle sera calculée sur la base de la taille réelle de la police ; (14*0,5)*1,5 = 10,5.

Vous avez une réponse parfaite à votre question aquí .

0voto

Matthieu, essayez d'ajouter "line-height:1.5 em;" à la ".les petits" de la classe. Permet-il de résoudre le problème pour toutes les déclarations?

Je pense qu'il va et si oui, il doit être une question d'héritage. La différence entre 1.5 em/150% et de 1,5 (sans unité) est que les deux premiers calculer la valeur et de le fixer dans un absolu de la matière sur son élément, donc un enfant de cet élément sans sa propre hauteur de la ligne de la déclaration de hériteront de la valeur calculée, et non pas le pourcentage.

Déclarant la hauteur de la ligne sans unité, cependant, a un résultat différent pour que l'élément enfant parce que ce qui est effectivement hérité de ce nombre (1,5 – dans votre cas) qui sera calculé une fois de plus sur l'enfant de l'élément résultant d'une valeur liée à sa propre taille de police et non pas celle de son parent.

Vous dites que la spécification définit la version de la même manière et donc, le résultat devrait être le même, mais voici ce qui est réellement dit:

<number>

L'utilisé la valeur de la propriété est de ce nombre, multiplié par la taille de la police. Les valeurs négatives sont illégales. La valeur calculée est la même que la valeur spécifiée.

<percentage>

La valeur calculée de la propriété ce pourcentage est-il multiplié par l'élément est calculé de la taille de la police. Les valeurs négatives sont illégales.

C'est la différence: ce qui est en fait calculé. Lorsque vous déclarez à la ligne heght comme un pourcentage (ou en utilisant ems) la valeur calculée est la numerica valeur, alors que, dans le cas de la sans unités de déclaration, la valeur calculée est la même chose avec la valeur déclarée qui rend possible pour l'enfant de l'élément de recalculer.

Dans l'intervalle, j'ai fait le test et je pense que j'avais raison.

Lorsque vous déclarez la hauteur de la ligne comme un pourcentage (ou en utilisant ems), la valeur calculée est héritée par l'élément span. De sorte que la hauteur de la ligne de l'élément span seront 24px au lieu de 13,5 px. Mais, étant donné que la police-taille de l'élément span est en fait plus petit, le ci-dessous leader abouti sera plus grande que celle de son parent. (24px-9px)/2=7.5 px. Ainsi, vous obtiendrez de 7,5 px menant ci-dessous au lieu de (24 à 16)/2 (4px). Vous vous retrouvez avec un supplément de 7,5 px-4px (3.5 px) en tête.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X