CSS3 box-sizing: margin-box; Pourquoi pas?

139

Pourquoi n'avons-nous pas box-sizing: margin-box;? Habituellement, lorsque nous insérons box-sizing: border-box;nos feuilles de style, nous entendons vraiment les premières.


Exemple:

Disons que j'ai une mise en page à 2 colonnes. Les deux colonnes ont une largeur de 50%, mais elles ont l'air plutôt moche car il n'y a pas de gouttière (espace au milieu); Voici le CSS:

.col2 {
    width: 50%;
    float: left;
}


Pour appliquer une gouttière, vous pourriez penser que nous pourrions simplement définir une marge droite sur la première des 2 colonnes; quelque chose comme ça:

.col2:first-child {
    margin-right: 24px;
}

Mais cela ferait en sorte que la deuxième colonne s'enroule sur une nouvelle ligne, car ce qui suit est vrai:

50% + 50% + 24px > 100%

box-sizing: margin-box;résoudrait ce problème en incluant une marge dans la largeur calculée de l'élément. Je trouverais cela très utile sinon plus utile que box-sizing: border-box;.

Web_Designer
la source
30
"Pourquoi pas box-sizing: margin-box;?" Parce que si les marges horizontales ne s'effondrent pas, une telle proposition interférerait sérieusement avec l'effondrement vertical des marges. Quoi qu'il en soit, si vous souhaitez proposer quelque chose pour la standardisation, Stack Overflow n'est pas le bon endroit. Essayez les listes de diffusion.
BoltClock
16
Dans certaines situations, vous pouvez contourner ce problème en utilisant border: xxx solid transparent;, car la bordure est incluse dans border-box. Cela cassera cependant d'autres choses, telles que box-shadow.
Nathan Osman
28
Sommes-nous en train de fermer toutes les questions sur les normes comme "non constructives"? C'est une question juste à poser, et elle a même une réponse simple: nous ne l'avons pas box-sizing: margin-boxparce que cela ne fonctionnerait pas avec l'effondrement des marges.
thomasrutter
@thomasrutter: Il n'y avait pas de raison mieux formulée à cela au moment où je l'ai fermé, il y a plus d'un an. Quoi qu'il en soit, "non constructif" est parti maintenant (ce qui signifie non, nous ne fermons plus rien comme non-constructif), et puisque le tout "j'ai une idée, voici comment ça marche, faisons-en un standard!" chose a été supprimée depuis sa dernière fermeture, cela ressemble maintenant à un "pourquoi X ne peut-il pas fonctionner?" question. C'est toujours une question incroyablement spéculative (mon raisonnement ci-dessus n'est en réalité rien de plus qu'une supposition éclairée), mais je ne commenterai pas davantage à ce sujet.
BoltClock
pourquoi ne pas simplement avoir un intérieur-wrap / div si vous voulez un espacement: codepen.io/chriscoyier/pen/eGcLw
ashley

Réponses:

55

Tu ne pourrais pas utiliser width: calc(50% - 24px);pour tes cols? Ensuite, définissez vos marges.

Slouch
la source
5
Il dépend fortement du navigateur. Probablement vers 2020, le ie15 le supportera et vous serez également autorisé à l'utiliser dans votre travail :-(
peterh - Réintégrer Monica
1
Cela ne semble pas fonctionner aussi bien dans Firefox? (ou quelque chose d'autre que j'ai fait n'est pas)
Laurengineer
@Morgan Feeney: Oui, mais le dimensionnement de la boîte n'a pas de valeur appelée margin-box (ce qui est le but de cette question). Même si une telle valeur a été introduite maintenant, comment proposez-vous de la patcher / polyfilling / shimming dans les navigateurs existants?
BoltClock
Ouais mais ... répondant spécifiquement à une réponse suggérant calc () comme solution de contournement.
Morgan Feeney
Je ne sais pas si cela s'applique à l'exemple spécifique, mais un inconvénient majeur à l'utilisation de calc () dans notre scénario (comme à FF 53.0.3) est que son comportement n'est pas analogue à celui de width: X%; D'après ce que nous pouvons voir, "calc" se fait au moment du rendu initial sur un Xpx statique. Cela signifie que contrairement à width: X%, la colonne calculée ne se redimensionnera pas automatiquement avec le redimensionnement du conteneur.
Pancho
16

Je pense que nous pourrions avoir un box-sizing: margin-box. Le modèle de boîte css montre exactement quelles sont les positions des marges des cadres.

Il y a des problèmes mineurs - par exemple, les cases de marge peuvent se chevaucher - mais ils ne sont pas difficiles à résoudre.

Je pense que la situation est la même, comme nous pouvons le voir avec les combinaisons overflow-x& overflow-y, avec les divs positionnés absolus dans les cellules de tableau, avec la combinaison de min | max-width | height avec le box-sizing, et ainsi de suite.

Il y a des fonctionnalités, des fonctionnalités vraiment simples, que les développeurs de navigateurs ne développent tout simplement pas.

IMHO, box-sizing: margin-boxétaient une fonctionnalité très utile. Une autre fonctionnalité utile était le box-sizing: padding-box, il existe au moins dans la norme, mais il n'a été implémenté dans aucun des principaux navigateurs. Pas même dans le dernier chrome!


Note: Commentaire de @Oriol: Firefox a implémenté box-sizing: padding-box. Mais d'autres non, et il a été retiré de la spécification. Firefox le supprimera dans la version 50. Triste.

peterh - Réintégrer Monica
la source
2
Firefox l'a mis en œuvre box-sizing: padding-box. Mais d'autres non, et il a été retiré de la spécification. Firefox le supprimera dans la version 50. Triste.
Oriol
6

Le gars en haut demande d'ajouter une marge à la largeur totale, y compris le rembourrage et la bordure. Le fait est que la marge est appliquée à l'extérieur de la boîte et que le remplissage et la bordure ne le sont pas lors de l'utilisation border-box.

J'ai essayé de réaliser l' border-marginidée. Ce que j'ai trouvé, c'est que si vous utilisez une marge, vous pouvez soit ajouter une classe de .lastau dernier élément (avec une marge, puis appliquer une marge de zéro, soit utiliser :last-child/:last-of-type). Ou ajoutez des marges égales tout autour (similaire à la version de remplissage ci-dessus).

Voir des exemples ici: http://codepen.io/mofeenster/pen/Anidc

border-boxcalcule la largeur de l'élément + son remplissage + sa bordure comme la largeur totale. Donc, si vous avez 2 divs qui ont une largeur de 50%, ils seront adjacents. Si vous leur ajoutez un 8pxrembourrage, vous aurez une gouttière de 16px. Combinez cela avec un élément enveloppant - qui a également un rembourrage de 8px- vous aurez une grille bien aménagée avec des gouttières égales tout autour.

Voir cet exemple ici: http://codepen.io/mofeenster/pen/vGgje

Cette dernière est ma méthode préférée.

Morgan Feeney
la source
4

Je suis sûr que tout cela est évident, mais je vais tout de même le taper parce que ... enfin, j'ai besoin de l'exercice. Le résultat suivant ne serait-il pas aussi efficace que box-sizing: margin-box;:

.col2 {
    width: 45%;
    height: 90%;
    margin: 5% 2.5%;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
    float: left;
}

http://jsfiddle.net/Fg3hg/

box-sizingest utilisé pour contrôler à partir de quel point le remplissage et la bordure sont évalués par rapport à la taille globale de l'élément. Ainsi, même s'il n'est pas casher d'inclure des pxmarges avec une %largeur (comme c'est généralement toujours le cas), il est plus facile de calculer ce que le pourcentage relatif devrait être car vous n'avez pas à incorporer de remplissage et de bordures à la largeur définie.

Plummer
la source
9
Le cas d'utilisation de quelque chose comme margin-box est de permettre de mélanger des largeurs de pourcentage avec des marges de pixels. Si vous voulez deux boîtes de 50% avec une marge de 1px entre elles, cela ne peut pas être accompli avec une marge de pourcentage de 1% de similaire - certaines petites tailles d'écran arrondiront 1% à 0 pixels et soudainement vous n'avez aucune marge. Ce dont nous avons vraiment besoin, c'est de plus de support du navigateur pour calc () comme le montre @Slouch, ou le modèle flexbox.
1
Si tel est le cas, le conteneur parent ferait moins de 100 pixels, et j'espère que certains éléments de conception seront repensés à ce stade. Il y a d'autres choses que vous pourriez faire avec des éléments imbriqués et autres, mais, oui, avoir des calculs de variables serait assez stupide. Si vous aimez les choses comme sass ou moins, je pense qu'ils font beaucoup de choses. J'ai joué avec eux, mais je ne suis pas encore Jedi.
Plummer le
2
Ce que vous proposez, c'est une solution. Ce n'est pas un moyen idéal d'écrire du CSS lorsque vous travaillez avec des mises en page complexes. Vous supposez que le concepteur ou l'auteur souhaite utiliser des pourcentages dans sa conception. Indépendamment de ce problème, même si vous utilisez la fonction calc () pour calculer l'espacement à l'aide de marges de pixels, cela limite toujours le concepteur car il doit prédéterminer ce qu'est la gouttière, plutôt que de lui permettre d'être écrasée à l'aide de CSS.
boucle illimitée du
Je ne comprends pas votre point. Le problème à résoudre était que l'inclusion de px et% provoquait des sauts de ligne car la marge n'est pas incluse dans le calcul de la taille. Une marge n'est pas incluse dans la taille d'un élément, c'est l'espace que vous souhaitez voir apparaître autour d'un élément. De plus, comment margin-boxgérer les calculs de marge multidimensionnels? @mediapoints d'arrêt, max-widthet min-widthfonctionne très bien. Je suppose que cela margin-boxpourrait réduire certains ballonnements, mais j'ai aussi des raisons pour lesquelles cela peut être considéré comme redondant.
Plummer
Pourquoi personne ne mentionne que cette marge Pourcentage VALUE est le pourcentage de largeur pour une raison quelconque ... peu importe la hauteur ou la largeur. La largeur du parent est utilisée. Ce qui est pour le moins bizarre ... donc le code ci-dessus ne devrait pas fonctionner et ne fonctionne pas. sauf si vous rendez la hauteur et la largeur égales.
Muhammad Umer
4

En effet, l'attribut box-sizing fait référence à la taille d'un élément après le calcul des valeurs spécifiques à la dimension (remplissage, bordures). "box-sizing: border-box" définit la hauteur / largeur d'un élément et prend en compte le remplissage ainsi que la largeur de la bordure. La portée de la marge d'un élément est plus grande que l'élément lui-même, ce qui signifie qu'il modifie le flux de la page et de ses éléments environnants, modifiant ainsi directement la façon dont l'élément s'intègre dans son parent par rapport à ses éléments frères. En fin de compte, une valeur d'attribut "margin-box" poserait des problèmes majeurs et revient essentiellement à définir directement la hauteur / largeur des éléments.

Ryan
la source
1
mes excuses, mais je ne comprends pas en quoi l'inclusion du remplissage, de la bordure et de la marge dans le calcul spatial via "margin-box" différerait conceptuellement de l'inclusion de remplissage et de bordure via "border-box". C'est sûrement juste une variation sur le même thème?
Pancho
1

Sur Codrops, il y a quelques bons articles sur le thème de l'effet des marges et des lignes forcées de déborder. Ils suggèrent d'utiliser l'unité rem ou em avec un normaliseur css définissant la taille de la police à 100% pour tous les navigateurs, puis lorsque vous définissez les largeurs et les marges, il est facile de suivre l'effet sur la largeur de la ligne en faisant simplement une note dans les commentaires pour la largeur totale. Une conversion de 16px en 1 em est le moyen de calculer le witdh total des fenêtres ciblées.

En travaillant comme ça pour la phase de développement au moins, puis si vous voulez des modèles `` réactifs '', vous pouvez convertir les largeurs en%, y compris les largeurs de marge.

L'autre façon souvent plus simple qu'ils suggèrent de manipuler les gouttières est d'utiliser le pseudo après et le content: '';sur chacune de vos colonnes qui, je trouve, fonctionne très bien. Si vous définissez une classe div qui est la dernière colonne définie telle que end, vous pouvez alors cibler cette classe pour ne pas avoir le pseudo après ou pour en avoir une plus large; qui convient le mieux à votre mise en page.

L'avantage supplémentaire de l'utilisation de cette méthode de pseudo-éléments est qu'elle vous donne également une cible pour les ombres qui peuvent également donner un effet plus 3D et une plus grande profondeur à l'image plate sur le moniteur du lecteur. J'expérimente cet effet en ce moment en augmentant les effets utilisés sur les boutons, en «ajustant» les dégradés et le z-index.

Mauvaises herbes101
la source
1

Les dimensions des éléments non remplacés au niveau du bloc dans un écoulement normal doivent satisfaire

margin-left + border-left-width + padding-left + width + padding-right + border-right-width + margin-right = largeur du bloc conteneur

Lorsqu'ils sont surcontraints, les navigateurs doivent ajuster la marge gauche ou droite. Je pense que cela signifie que la largeur de la zone de marge doit être égale à la largeur du bloc contenant (c'est-à-dire 100%).

Pour votre cas, les bordures transparentes box-sizing: border-boxpeuvent fonctionner un peu comme des marges .

sam
la source
1

Peut-être définir la bordure à 0% d'opacité en utilisant RGBA et utiliser la bordure comme marge.

user3236407
la source
Cela ressemble à un hack, mais ferait le travail.
Morgan Feeney
Cela peut s'avérer utile si vous ne souhaitez pas utiliser d'encapsuleurs pour réaliser le travail.
boucle illimitée
... sauf si vous avez réellement besoin d'une frontière
FrancescoMM
@FrancescoMM - un peu "bruyant", mais vous pouvez faire une boîte avec une bordure transparente "margin-width" (et pas de marge bien sûr) et à l'intérieur de cela placez une boîte avec une bordure visible de la largeur que vous voulez afficher (encore une fois sans marge)
Pancho
1
Je ne peux tout simplement pas suivre ce genre de pensée. Y a-t-il quelque chose de plus naturel que de dire que je veux deux boîtes 1pxséparées, chacune occupant l' 50%espace disponible? C'est exactement ce que margin-boxferait. Ou oubliez la zone de marge et pensez à l'espace disponible. Pas 50% du conteneur parent, mais 50% de ce qui reste. Pas de "calc", pas de "marge de 5%", pas de tel gâchis ...
maaartinus
0

Il existe une situation intéressante lors de l'utilisation de la taille de la boîte à l' intérieur du contenu du corps

aucun contenu aucune boîte de bordure ne donne aucune valeur sur la marge gauche-droite% recomptage de ces deux algoritms de recomptage de boîte

  .body{
    box-sizing: border-box;
    margin:0 3%;
  }

Les versions de Firefox antérieures à 57 prenaient également en charge la valeur padding-box pour le dimensionnement de la boîte, bien que cette valeur ait été supprimée de la spécification et des versions ultérieures du navigateur.

Donc margin-box même pas prévu ...

Dmytro Yurchenko
la source