132 votes

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

Si vous regardez le Spécifications du modèle de boîte CSS vous observerez ce qui suit :

Le pourcentage de la [marge] est calculé par rapport à la largeur du bloc contenant la boîte générée. Notez que cela s'applique également à "margin-top" et "margin-bottom". Si la largeur du bloc contenant dépend de cet élément, la mise en page résultante est indéfinie en CSS 2.1. (c'est moi qui souligne)

C'est en effet vrai. Mais por qué ? Qu'est-ce qui pourrait bien pousser quelqu'un à le concevoir de cette façon ? Il est facile de penser à des scénarios où l'on veut, par exemple, qu'une certaine chose soit toujours 25% plus bas que le haut de la page, mais il est difficile de trouver une raison pour laquelle on voudrait 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/

0 votes

La taille verticale de la page ou le fenêtre ? Ils ne sont presque jamais de la même taille. J'imagine que cette ambiguïté explique en grande partie pourquoi.

0 votes

La taille verticale de l'élément contenant (potentiellement le corps, bien sûr.) J'ai ajouté un exemple dans JSFiddle pour aider à illustrer.

0 votes

Je ne sais pas. Mais cette question mérite une étoile "Favorite" de ma part, un +1, et du temps passé à faire des recherches (et peut-être, si je ne trouve rien de convenable, à envoyer un courriel à quelqu'un comme Eric Meyer).

60voto

Ryan Kinal Points 8903

Je transfère mon commentaire à une réponse, parce que c'est logique. Cependant, veuillez noter qu'il s'agit d'une conjecture sans fondement. Le raisonnement réel de la raison pour laquelle la spécification est écrite de cette façon est toujours, techniquement, inconnu.

La hauteur de l'élément est définie par la hauteur des enfants. Si un élément possède un padding-top : 10% (relatif à la hauteur du parent ), cela va affecter la hauteur du parent. Puisque la de l'enfant dépend de la hauteur du parent, et que la hauteur du parent du parent, et que la hauteur du parent dépend de la hauteur de l'enfant, nous aurons soit une hauteur inexacte, soit une boucle infinie. Bien sûr, cela n'affecte que affecte seulement 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 ne sont peut-être pas tout à fait exactes. La hauteur de l'élément leaf (enfant sans enfant) a un effet sur la hauteur de tous les éléments au-dessus de lui, donc cela affecte beaucoup de situations différentes.

1 votes

Notez qu'il existe des exceptions à cette règle - la section 10.6 de CSS2.1 couvre presque tous les cas de calcul de la hauteur de divers types de boîtes. Et en effet, les cas qui impliquent une codépendance entre le parent et l'enfant en matière de hauteur ont tendance à conduire à un comportement non défini.

0 votes

Je ne comprends pas pourquoi c'est encore le cas. Les CSS sont des cascades, non ? Alors pourquoi la nouvelle hauteur totale ne remplace-t-elle pas simplement l'ancienne ? N'est-ce pas ainsi que la largeur est calculée ?

0 votes

@sanjaypoyzer : Oui, mais la hauteur ne peut pas toujours être calculée de la même manière que la largeur, simplement en raison de la nature de la circulation du contenu.

30voto

Chuck Kollars Points 884

Pour que la marge (et le remplissage) de "n%" soit la même pour margin-top/margin-right/margin-bottom/margin-left, les quatre doivent être relatifs à la même base. Si "top/bottom" utilisait une base différente de "left/right", alors "n%" de marge (et de padding) n'aurait pas la même signification sur les quatre côtés.

(Il convient également de noter que les marges supérieure et inférieure sont relatives à l'espace de travail. largeur permet un piratage CSS bizarre qui vous permet de spécifier une boîte avec un rapport d'aspect inchangé ... même si la boîte est redimensionnée).

0 votes

...une réponse étonnamment simple. Bien que toutes les conjectures ci-dessus soient fondées, c'est un bon point. Il est possible que plusieurs solutions soient correctes et qu'ils aient choisi la plus probable, une.... peut-être ?

1 votes

Je suppose qu'il serait agréable d'avoir un élément supplémentaire dans la syntaxe pour pouvoir écrire par exemple padding: n [type] . Donc vous auriez padding: 5% logical (ce que suggère le PO) par opposition à padding: 5% width le deuxième paramètre étant par défaut "width" pour des raisons de rétrocompatibilité.

6 votes

"n% de marge (et de padding) ne signifierait pas la même chose sur les quatre côtés" - Mais pourquoi cela poserait-il un problème ?

4voto

Joy Points 6712

Je vote pour la réponse de @ChuckKollars après avoir joué avec ceci JSFiddle (sur Chrome 46.0.2490.86) et en se référant à ce poste (écrit en chinois).


Une raison majeure contre le calcul infini La conjecture est la suivante : en utilisant width fait face à la même calcul infini problème.

Jetez un coup d'œil à ceci JSFiddle le parent L'affichage est inline-block qui permet de définir des marges et des renforts. Le site child a une valeur marginale 20% . Si nous suivons le calcul infini conjecture :

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

Mais en conséquence, Chrome arrête le calcul quelque part, résultant :

enter image description here

Si vous essayez d'étendre horizontalement le panneau "résultats" sur le JSFiddle, vous constaterez que la largeur de ceux-ci ne changera pas. Veuillez noter que le contenu du panneau child est enveloppé dans deux lignes (pas, disons, une ligne), pourquoi ? Je suppose que Chrome le code en dur quelque part. Si vous modifiez le child le contenu pour le rendre plus ( JSFiddle ), vous constaterez que tant qu'il y a de l'espace supplémentaire à l'horizontale, Chrome conserve le contenu sur deux lignes.

Donc on peut voir : il y a un moyen d'empêcher le calcul infini .


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

ce poste (écrit en chinois) propose également une autre raison : c'est à cause de l'orientation de la lecture/typographie. Nous lisons de haut en bas, avec une largeur fixe et une hauteur infinie (virtuellement).

3voto

VKK Points 576

Je réalise que l'OP demande por qué La spécification CSS définit les pourcentages de marge haut/bas comme un % de la largeur (et non, comme on pourrait le supposer, de la hauteur), mais j'ai pensé qu'il pourrait également être utile de poster une solution potentielle.

La plupart des navigateurs modernes prennent en charge vw et vh, qui vous permettent de spécifier les marges par rapport à la largeur et à la hauteur de la fenêtre d'affichage.

100vw/100vh équivaut à 100 % de largeur/100 % de hauteur (respectivement) s'il n'y a pas de barre de défilement ; s'il y a une barre de défilement, les chiffres de la fenêtre d'affichage n'en tiennent pas compte (alors que les chiffres en % le font). Heureusement, presque tous les navigateurs utilisent des barres 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'il n'y ait pas de barre de défilement horizontale, une marge supérieure de 50 % de la hauteur pourrait être définie comme "margin-top : 50vh ;". Avec une barre de défilement horizontale, elle pourrait être définie comme suit : "margin-top : calc(0.5 * (100vh - 17px)) ;" (n'oubliez pas que les opérateurs moins et plus dans calc nécessitent des espaces des deux côtés !)

1voto

AleksandrH Points 148

Je sais que cette question est un peu ancienne, mais j'aimerais la rafraîchir pour CSS3. S'il est vrai que la spécification CSS2.1 stipule que les pourcentages de remplissage et de marge sont définis par rapport à la largeur du bloc qui les contient, ce n'est pas siempre l'affaire. Cela dépend du mode d'écriture. Cela vient directement de la Spécifications CSS3 :

En corollaire, les pourcentages des propriétés margin et padding, qui sont toujours calculés par rapport à la largeur du bloc contenant en CSS2.1, sont calculés par rapport à la taille en ligne du bloc contenant en CSS3.

J'en parle dans mon Tutoriel sur les rapports d'aspect avec CSS .

Plus précisément, il y a une section sur Pourcentage de remplissage en modes d'écriture horizontal et vertical . Par défaut, un élément a un mode d'écriture horizontal, où le texte circule horizontalement (dans le sens "inline") de gauche à droite. Cependant, en utilisant l'option writing-mode vous pouvez en fait définir le mode comme étant vertical (le texte s'écoulant soit de droite à gauche, soit de gauche à droite). Voici quelques diagrammes des modes d'écriture horizontal et vertical :

A horizontal writing mode, with text flowing vertically from top to bottom. An arrow points from left to right at the top of the document and is labeled as the inline direction. Another arrow points from top to bottom and is labeled as the block direction.

A vertical writing mode, with text flowing horizontally. The horizontal axis is labeled as the block direction, whereas the vertical axis is now labeled as the inline direction. Text is rendered sideways.

Ceux-ci sont tirés du Documents MDN sur les modes d'écriture .

Dans les modes d'écriture verticaux, le pourcentage de remplissage sera relatif à la hauteur du bloc contenant, et non à la largeur.

En voici la preuve :

.document {
  writing-mode: vertical-rl;
  width: 100%;
  height: 100vh;
}

.parent {
   width: 100%;
   height: 200px;
   background-color: black;
   color: white;
}

.child {
  padding: 10%;
  background-color: white;
  color: black;
  border: solid 1px;
}

<div class="document">
  <div class="parent">
    <div class="child">
      Child
    </div>
  </div>
</div>

L'enfant reçoit 20 px de remplissage, ce qui correspond à 10 % de la hauteur du bloc qui le contient (200 px).

Quant au pourquoi de la question, il a été bien traité dans les autres messages ici.

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