Dimensionamento de caixa CSS3: margem-caixa; Por que não?

139

Por que não temos box-sizing: margin-box;? Normalmente, quando colocamos box-sizing: border-box;em nossas folhas de estilo, realmente queremos dizer o primeiro.


Exemplo:

Digamos que eu tenha um layout de página de 2 colunas. Ambas as colunas têm uma largura de 50%, mas parecem feias porque não há sarjeta (lacuna no meio); Abaixo está o CSS:

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


Para aplicar uma calha, você pode pensar que podemos definir uma margem certa na primeira das 2 colunas; algo assim:

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

Mas isso faria a segunda coluna se agrupar em uma nova linha, porque o seguinte é verdadeiro:

50% + 50% + 24px > 100%

box-sizing: margin-box;resolveria esse problema incluindo margem na largura calculada do elemento. Eu consideraria isso muito útil se não mais útil que box-sizing: border-box;.

Web designer
fonte
30
"Por que não temos box-sizing: margin-box;?" Porque, embora as margens horizontais não colapsem, essa proposição interferiria seriamente no colapso vertical das margens. De qualquer forma, se você deseja propor algo para padronização, o Stack Overflow não é o lugar certo. Experimente as listas de discussão.
BoltClock
16
Em certas situações, você pode contornar isso usando border: xxx solid transparent;, pois a borda está incluída no border-box. Isso vai quebrar algumas outras coisas, como box-shadow.
Nathan Osman
28
Estamos encerrando todas as perguntas sobre os padrões como "não construtivas" agora? É uma pergunta justa, e até tem uma resposta direta: não temos box-sizing: margin-boxporque não funcionaria com o colapso da margem.
thomasrutter
@ thomasrutter: Não havia uma razão melhor para isso no momento em que a fechei, que foi há mais de um ano. De qualquer forma, "não construtivo" se foi agora (ou seja, não, na verdade, não fechamos mais nada como não construtivo) e, como todo "eu tenho uma idéia, aqui está como funciona, vamos fazer disso um padrão!" coisa foi removida desde a última vez que foi fechada, agora parece um prático "por que o X não funciona?" questão. Ainda é uma pergunta incrivelmente especulativa (meu raciocínio acima não passa de um palpite), mas não vou comentar mais sobre isso.
BoltClock
porque não basta ter um interior-wrap / div se você quiser espaçamento: codepen.io/chriscoyier/pen/eGcLw
ashley

Respostas:

55

Você não poderia usar width: calc(50% - 24px);para seus cols? Em seguida, defina suas margens.

Desleixo
fonte
5
É altamente dependente do navegador. Provavelmente por volta de 2020 o ie15 vai apoiá-lo e você terá permissão para usar isso em seu trabalho, também :-(
peterh - Reintegrar Monica
1
Não parece estar funcionando tão bem no Firefox? (ou qualquer outra coisa que eu fiz não é)
Laurengineer
@ Morgan Feeney: Sim, mas o tamanho da caixa não tem um valor chamado margin-box (que é o ponto principal desta questão). Mesmo que esse valor tenha sido introduzido agora, como você propõe aplicar patch / polyfilling / shimming nos navegadores existentes?
BoltClock
Sim, mas ... especificamente, respondendo a uma resposta sugerindo calc () como uma solução alternativa.
Morgan Feeney
Não tenho certeza se isso se aplica ao exemplo específico, mas o principal negativo do uso de calc () em nosso cenário (como no FF 53.0.3) é que seu comportamento não é análogo ao da largura: X%; Pelo que podemos ver, "calc" é feito no momento da renderização inicial para um Xpx estático. Isso significa que, diferentemente da largura: X%, a coluna calculada não é redimensionada automaticamente com o redimensionamento do contêiner.
Pancho
16

Eu acho que poderíamos ter um box-sizing: margin-box. O modelo de caixa de css mostra exatamente quais são as posições das margens dos quadros.

Existem problemas menores - por exemplo, as caixas de margem podem se sobrepor - mas não são difíceis de resolver.

Eu acho que a situação é a mesma, como podemos ver com as combinações overflow-x& overflow-y, com as divs posicionadas absolutas nas células da tabela, com a combinação de min | max-width | height com o tamanho da caixa e assim por diante.

Existem recursos, recursos realmente simples, que os desenvolvedores do navegador simplesmente não desenvolvem.

IMHO, box-sizing: margin-boxforam um recurso muito útil. Outro recurso útil foi o box-sizing: padding-box, ele existe pelo menos no padrão, mas não foi implementado em nenhum dos principais navegadores. Nem mesmo no mais novo cromo!


Nota: Comentário do @Oriol: o Firefox implementou o tamanho da caixa: caixa de preenchimento. Mas outros não, e foi removido das especificações. O Firefox irá removê-lo na versão 50. Triste.

peterh - Restabelecer Monica
fonte
2
O Firefox implementou box-sizing: padding-box. Mas outros não, e foi removido das especificações. O Firefox irá removê-lo na versão 50. Triste.
Oriol
6

O cara no topo está perguntando sobre como adicionar margem à largura geral, incluindo preenchimento e borda. O problema é que a margem é aplicada fora da caixa e o preenchimento e a borda não são, ao usar border-box.

Eu tentei alcançar a border-marginidéia. O que descobri é que, se estiver usando margem, você poderá adicionar uma classe .lastao último item (com margem, aplicar uma margem zero ou usar :last-child/:last-of-type). Ou adicione margens iguais a toda a volta (semelhante à versão de preenchimento acima).

Veja exemplos aqui: http://codepen.io/mofeenster/pen/Anidc

border-boxcalcula a largura do elemento + seu preenchimento + sua borda como a largura total. Portanto, se você tiver 2 divs com 50% de largura, eles serão adjacentes. Se você adicionar 8pxestofamento a eles, terá uma sarjeta 16px. Combine isso com um elemento de embalagem - que também possui preenchimento de 8px- você terá uma grade bem definida com calhas iguais a toda a volta.

Veja este exemplo aqui: http://codepen.io/mofeenster/pen/vGgje

O último é o meu método favorito.

Morgan Feeney
fonte
4

Tenho certeza de que tudo isso é óbvio, mas vou digitar mesmo assim porque ... bem, preciso do exercício. O resultado a seguir não seria tão eficiente quanto 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-sizingé usado para controlar a partir de qual ponto o preenchimento e a borda são avaliados para o tamanho geral do elemento. Portanto, embora não seja mais conveniente incluir pxmargens com uma %largura (como geralmente é sempre o caso), é mais fácil calcular qual deve ser o valor percentual relativo, porque você não precisa incorporar preenchimento e bordas à largura definida.

Plummer
fonte
9
O caso de uso para algo como caixa de margem é permitir misturar larguras de porcentagem com margens de pixel. Se você deseja duas caixas de 50% com uma margem de 1px entre elas, isso não pode ser feito com uma margem percentual de 1% da similar - alguns tamanhos de tela pequenos arredondam 1% para 0 pixels e de repente você não tem margem. O que realmente precisamos é de mais suporte ao navegador para calc (), como mostra o @Slouch, ou o modelo flexbox.
1
Se esse for o caso, o contêiner pai seria menor que 100px e eu espero que alguns elementos de design sejam repensados ​​nesse ponto. Existem outras coisas que você poderia fazer com elementos aninhados e similares, mas, sim, fazer cálculos de variáveis ​​seria muito bom. Se você gosta de coisas atrevidas ou menos, acho que elas fazem muitas dessas coisas. Eu brinquei com eles, mas ainda não sou Jedi.
Plummer
2
O que você está sugerindo é uma solução alternativa. Não é uma maneira ideal de escrever CSS quando você estiver trabalhando com layouts complexos. Você está assumindo que o designer ou autor deseja usar porcentagens em seu design. Além disso, independentemente desse problema, mesmo que você use a função calc () para calcular o espaçamento usando as margens de pixel, isso ainda limita o designer, pois deve predeterminar qual é a calha, em vez de permitir que ela seja substituída usando CSS.
limitlessloop
Eu não entendo o seu ponto. O problema em questão era que a inclusão de px e% causa quebras de linha porque a margem não está incluída no cálculo do tamanho. Uma margem não está incluída no tamanho de um elemento, é o espaço que você deseja que apareça ao redor de um elemento. Além disso, como margin-boxlidaria com cálculos de margens multidimensionais? @mediapontos de interrupção max-widthe min-widthfuncionam bem. Eu acho que margin-boxpode reduzir alguns inchaços, mas também tenho razões pelas quais pode ser considerado redundante.
Plummer
Por que ninguém menciona que essa margem Porcentagem VALUE é a porcentagem de largura por algum motivo ... não importa altura ou largura. A largura do pai é usada. O que é bizzare, para dizer o mínimo .. portanto, o código acima não deve funcionar e não funciona. a menos que você faça altura e largura iguais.
Muhammad Umer
4

Isso ocorre porque o atributo de dimensionamento de caixa se refere ao tamanho de um elemento após calcular os valores específicos da dimensão (preenchimento, bordas). "box-sizing: border-box" define a altura / largura de um elemento e leva em consideração o preenchimento e a largura da borda. O escopo da margem de um elemento é maior que o próprio elemento, o que significa que ele modifica o fluxo da página e de seus elementos circundantes, alterando diretamente a maneira como o elemento se ajusta ao seu pai em relação aos elementos irmãos. Por fim, um valor de atributo "caixa de margem" causaria grandes problemas e é essencialmente o mesmo que definir diretamente a altura / largura dos elementos.

Ryan
fonte
1
peço desculpas, mas não entendo como incluir preenchimento, borda e margem no cálculo espacial via "caixa de margem" diferiria conceitualmente de incluir preenchimento e borda via "caixa de borda". Certamente é apenas uma variação do mesmo tema?
Pancho
1

No Codrops, existem alguns bons artigos sobre o efeito de margens e linhas forçadas a transbordar. Eles sugerem o uso da unidade rem ou em com um css do normalizador configurando o tamanho da fonte para 100% para todos os navegadores; quando você define larguras e margens, é fácil acompanhar o efeito na largura da linha, simplesmente anotando nos comentários para a largura total. Uma conversão de 16px para 1 em é a maneira de calcular o total de viewports direcionadas com o total.

Trabalhando assim para o estágio dev pelo menos e, se você quiser modelos 'responsivos', poderá converter larguras em%, incluindo as larguras de margem.

A outra maneira, e muitas vezes mais simples, que eles sugerem para lidar com as sarjetas é usar o pseudo after e o content: '';em cada uma das suas colunas que eu acho que funciona muito bem. Se você definir uma classe div que é a última coluna definida, como end, poderá direcionar essa classe para não ter o pseudo depois ou ter uma mais ampla; que melhor se adapte ao seu layout.

O bônus adicional de usar esse método de pseudo-elemento é que ele também fornece um alvo para sombras que podem dar mais efeito 3D e maior profundidade à imagem plana no monitor dos leitores. No momento, estou experimentando esse efeito aumentando os efeitos usados ​​nos botões, 'ajustando' os gradientes e o índice z.

Weedy101
fonte
1

As dimensões dos elementos não substituídos no nível do bloco no fluxo normal devem satisfazer

margin-left + border-left-width + padding-left + width + padding-right + border-right-width + margin-right = largura do bloco que contém

Quando excessivamente restrito, os navegadores devem ajustar a margem esquerda ou direita. Eu acho que isso significa que a largura da caixa de margem deve ser igual à largura do bloco que contém (ou seja, 100%).

Para o seu caso, bordas transparentes com box-sizing: border-boxpodem funcionar como margens .

sam
fonte
1

Talvez defina a borda com 0% de opacidade usando RGBA e use a borda como uma margem.

user3236407
fonte
Parece um hack, mas faria o trabalho.
Morgan Feeney
Isso pode ser útil se você não quiser usar wrappers para realizar o trabalho.
limitlessloop
... a menos que você realmente precisa de uma fronteira
FrancescoMM
@FrancescoMM - um pouco "barulhento", mas você pode fazer uma caixa com borda transparente "largura da margem" (e sem margem, é claro) e dentro desse local uma caixa com uma borda visível da largura que você deseja exibir (novamente margem)
Pancho
1
Eu simplesmente não consigo seguir esse tipo de pensamento. Existe algo mais natural do que dizer que eu quero duas caixas 1pxseparadas, cada uma ocupando o 50%espaço disponível? É exatamente o margin-boxque faria. Ou esqueça a caixa de margem e pense no espaço disponível. Não 50% do contêiner pai, mas 50% do que resta. Sem "calc", sem "margem de 5%", sem essa bagunça ...
maaartinus 15/01/19
0

Existe uma situação interessante ao usar o tamanho da caixa dentro do conteúdo do corpo

sem conteúdo sem caixa de borda não fornece nenhum valor na recontagem de margem esquerda-direita% desses algoritmos de recontagem de duas caixas

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

As versões do Firefox anteriores a 57 também suportavam o valor padding box para o tamanho da caixa, embora esse valor tenha sido removido da especificação e das versões posteriores do navegador.

Então, caixa de margem, mesmo não planejada ...

Dmytro Yurchenko
fonte