web-dev-qa-db-fra.com

Pourquoi les pourcentages de marge / remplissage dans CSS sont-ils toujours calculés par rapport à la largeur?

Si vous regardez le spécification de modèle de boîte CSS , vous observerez ce qui suit:

Le pourcentage [marge] est calculé par rapport à la largeur du bloc contenant de la boîte générée. Notez que ceci est également vrai pour 'margin-top' et 'margin-bottom'. Si la largeur du bloc conteneur dépend de cet élément, le paramètre la mise en page résultante n'est pas définie en CSS 2.1. (c'est moi qui souligne)

C'est vraiment vrai. Mais pourquoi? Qu'est-ce qui obligerait quelqu'un à le concevoir de cette façon? Il est facile de penser à des scénarios où vous voulez, par exemple Il est toujours certain que vous devez être à 25% du haut de la page, mais il est difficile de trouver une raison pour laquelle vous souhaitez que le remplissage vertical soit relatif à la taille horizontale du parent.

Voici un exemple du phénomène auquel je fais référence:

<div style="border: 1px solid red; margin: 0; padding: 0; width: 200px; height: 800px;">
  This div is 200x800.
  <div style="border: 1px solid blue; margin: 10% 0 0 10%;">
    This div has top-margin of 10% and left-margin of 10% with respect to its parent.
  </div>
</div>

http://jsfiddle.net/8JDYD/

125
mqp

Transférer mon commentaire en réponse, parce que cela a du sens. Cependant, veuillez noter qu'il s'agit d'une conjecture non fondée. Le raisonnement réel de la raison pour laquelle la spécification est écrite de cette manière est encore, techniquement, inconnu.

La hauteur de l'élément est définie par la taille des enfants. Si un élément a padding-top: 10% (par rapport à la hauteur du parent), cela affectera la hauteur du parent. Puisque la taille de l'enfant dépend de la taille du parent et que la hauteur du parent dépend de la hauteur de l'enfant, nous aurons soit une hauteur imprécise, soit une boucle infinie. Bien sûr, cela ne concerne que le cas où offset parent === parent, mais quand même. C'est un cas étrange qui est difficile à résoudre.

Mise à jour: Les deux dernières phrases peuvent ne pas être tout à fait exactes. La hauteur de l'élément feuille (enfant sans enfant) a un effet sur la hauteur de tous les éléments situés au-dessus de celui-ci, ce qui affecte donc de nombreuses situations différentes.

58
Ryan Kinal

Pour que la marge (et le remplissage) "n%" soit le identique pour la marge supérieure/la marge droite/la marge inférieure/la marge gauche, tous les quatre doivent être relatifs à la même base. Si top/bottom utilise une base différente de celle de left/right ', la marge (et le rembourrage) "n%" ne signifie pas la même chose des quatre côtés.

(Notez également que la marge supérieure/inférieure par rapport à width active un hack CSS étrange qui vous permet de spécifier une zone avec un rapport de format immuable ... même si la zone est redimensionnée.)

28
Chuck Kollars

Je vote pour la réponse de @ChuckKollars après avoir joué avec ceci JSFiddle (sur Chrome 46.0.2490.86)) et en faisant référence à cet article (écrit en chinois).


Une raison majeure contre la conjecture calcul infini est que: utiliser width fait face au même calcul infini.

Regardez ceci JSFiddle , l’affichage parent est inline-block, qui est éligible pour définir une marge/un remplissage. Le child a une valeur de marge 20%. Si nous suivons la conjecture calcul infini:

  1. La largeur de child dépend de parent
  2. La largeur de parent dépend de child

Mais en conséquence, Chrome arrête le calcul quelque part, ce qui entraîne:

enter image description here

Si vous essayez d'étendre le panneau "résultat" horizontalement sur le JSFiddle, vous constaterez que leur largeur ne changera pas. Veuillez noter que le contenu du child est encapsulé dans deux lignes (pas une ligne, par exemple), pourquoi? Je suppose que Chrome le coder en dur quelque part. Si vous éditez le contenu child pour le rendre plus ( JSFiddle ), vous constaterez que tant qu'il y a un espace supplémentaire horizontalement, Chrome conserve le contenu sur deux lignes.

Nous pouvons donc voir: il existe un moyen d'empêcher le calcul infini .


Je suis d'accord avec la conjecture que: cette conception est juste pour garder les quatre valeurs de marge/remplissage basées sur la même mesure.

this post (écrit en chinois) propose également une autre raison est la suivante: c’est en raison de l’orientation lecture/composition. Nous lisons de haut en bas, largeur fixe et hauteur infinie (virtuellement).

4
Joy

Je me rends compte que le PO demande pourquoi la spécification CSS définit les pourcentages de marge supérieure/inférieure en tant que% de largeur (et non, comme on supposerait, hauteur) , mais j’ai pensé qu’il pourrait également être utile d’afficher une solution potentielle.

La plupart des navigateurs modernes prennent maintenant en charge vw et vh, ce qui vous permet de spécifier des numéros de marge en fonction de la largeur et de la hauteur de la fenêtre.

100vw/100vh est égal à 100% largeur/100% hauteur (respectivement) s'il n'y a pas de barre de défilement; s'il existe une barre de défilement, les numéros de la fenêtre d'affichage ne le prennent pas en compte (contrairement aux% nombres). Heureusement, presque tous les navigateurs utilisent des tailles de barre de défilement de 17px ( voir ici ), vous pouvez donc utiliser la fonction css calc pour en tenir compte. Si vous ne savez pas si une barre de défilement apparaîtra ou non, cette solution ne fonctionnera pas.

Par exemple: en supposant qu’aucune barre de défilement horizontale ne soit définie, une marge supérieure de 50% de la hauteur pourrait être définie comme "margin-top: 50vh;". Avec une barre de défilement horizontale, cela pourrait être défini comme "margin-top: calc (0.5 * (100vh - 17px));" (Rappelez-vous que les opérateurs moins et plus dans calc exigent des espaces des deux côtés!).

3
VKK