Impedir que o conteúdo expanda itens de grade

153

TL; DR: Existe algo parecido table-layout: fixedcom grades CSS?


Tentei criar um calendário de exibição do ano com uma grande grade 4x3 durante os meses e aninhar grades 7x6 durante os dias.

O calendário deve preencher a página, para que o contêiner da grade do ano tenha uma largura e altura de 100% cada.

.year-grid {
  width: 100%;
  height: 100%;

  display: grid;
  grid-template: repeat(3, 1fr) / repeat(4, 1fr);
}

.month-grid {
  display: grid;
  grid-template: repeat(6, 1fr) / repeat(7, 1fr);
}

Aqui está um exemplo de trabalho: https://codepen.io/loilo/full/ryXLpO/

Por uma questão de simplicidade, todos os meses nessa caneta têm 31 dias e começam na segunda-feira.

Também escolhi um tamanho de fonte ridiculamente pequeno para demonstrar o problema:

Os itens de grade (= células do dia) são bastante condensados, pois existem várias centenas na página. E assim que os rótulos dos números do dia ficarem muito grandes (sinta-se à vontade para brincar com o tamanho da fonte na caneta usando os botões no canto superior esquerdo), a grade aumentará de tamanho e excederá o tamanho do corpo da página.

Existe alguma maneira de impedir esse comportamento?

Inicialmente, declarei que minha grade do ano tem 100% de largura e altura, então esse é provavelmente o ponto de partida, mas não consegui encontrar nenhuma propriedade CSS relacionada à grade que atendesse a essa necessidade.

Isenção de responsabilidade: estou ciente de que existem maneiras muito fáceis de estilizar esse calendário sem usar o CSS Grid Layout. No entanto, essa pergunta é mais sobre o conhecimento geral sobre o tema do que resolver o exemplo concreto.

Loilo
fonte
O que você quer que aconteça? A fonte em cada célula pode ter qualquer tamanho e nunca faz com que o tamanho da célula da grade aumente?
Michael Coker
1
Exatamente. Basicamente, é uma maneira mais conveniente do que aconteceria se eu definisse os tamanhos dos itens da grade de acordo com valores percentuais em vez de frações.
Loilo
Basicamente, eu estou procurando uma versão grid-layouty de table-layout: fixed (ver: codepen.io/loilo/pen/dvxpvq?editors=1100 )
Loilo
7
Esta é a maior dor em toda a especificação CSS Grid. Eles precisam ser um ambiente em que as áreas de grade não possam escapar das dimensões de qualquer um dos seus contêineres de grade pai! Como é, é um pesadelo para estruturas de grade profundamente aninhadas.
Lonnie Best

Respostas:

263

Por padrão, um item de grade não pode ser menor que o tamanho do seu conteúdo.

Os itens de grade têm um tamanho inicial de min-width: autoe min-height: auto.

Você pode substituir esse comportamento definindo itens grade para min-width: 0, min-height: 0ou overflowcom qualquer valor diferente de visible.

Das especificações:

6.6 Tamanho mínimo automático de itens de grade

Para fornecer um tamanho mínimo padrão mais razoável para itens de grade, esta especificação define que o autovalor de min-width/ min-heighttambém aplica um tamanho mínimo automático no eixo especificado aos itens de grade que overflowsão visible. (O efeito é análogo ao tamanho mínimo automático imposto aos itens flexíveis.)

Aqui está uma explicação mais detalhada sobre os itens flex, mas também se aplica aos itens da grade:

Esta postagem também aborda possíveis problemas com contêineres aninhados e diferenças de renderização conhecidas entre os principais navegadores .


Para corrigir seu layout, faça estes ajustes no seu código:

.month-grid {
  display: grid;
  grid-template: repeat(6, 1fr) / repeat(7, 1fr);
  background: #fff;
  grid-gap: 2px;
  min-height: 0;  /* NEW */
  min-width: 0;   /* NEW; needed for Firefox */
}

.day-item {
  padding: 10px;
  background: #DFE7E7;
  overflow: hidden;  /* NEW */
  min-width: 0;      /* NEW; needed for Firefox */
}

codepen revisado


1fr vs minmax(0, 1fr)

A solução acima opera no nível do item da grade. Para uma solução em nível de contêiner, consulte esta postagem:

Michael Benjamin
fonte
3
Uau. Isso é fascinante e interessante ao mesmo tempo, e eu definitivamente não teria pensado nisso apenas tentando. Você deu uma olhada nas especificações dessas informações? Porque depois de não saber para o que procurar no google, foi o que tentei antes, mas acabei lendo a seção errada (depois de concluir a causa errada do problema).
Loilo
1
Eu já havia enfrentado esse problema antes com itens flexíveis . Sendo que existem muitas semelhanças entre os itens flex e grid, imaginei que o comportamento poderia ser o mesmo e se concentrar nessa seção das especificações.
Michael Benjamin
1
Ele fixa a altura, mas continua a crescer na direção horizontal, min-width: 0;não ajuda. Estou esquecendo de algo?
usuário
2
Para grades aninhadas, precisamos aplicar isso a todos os níveis. Mas eu realmente vim aqui para upvote e obrigado ..
Knack
2
@PragyAgarwal .. stackoverflow.com/users/3597276/michael-b?tab=answers :-)
Michael Benjamin
57

A resposta anterior é muito bom, mas eu também queria mencionar que não é um equivalente layout fixo para as redes, você só precisa escrever minmax(0, 1fr)em vez de 1frcomo o seu tamanho pista.

FremyCompany
fonte
6
Eu recomendo essa abordagem em relação à resposta anterior aceita.
Thierry Prost
Embora isso funcione, eu não entendo um pouco disso ... Você poderia explicar por que isso funciona? O que minmax (0, 1fr) está fazendo? Isso nem sempre deve ser 0? Estou confuso :(
BAERUS
2
minmax(0, 1fr)funciona porque 1fré realmente uma abreviação de minmax(auto,1fr), que não é o valor correto para a pergunta original.
Mikko Rantalainen 07/02/19
Para obter detalhes adicionais, consulte github.com/w3c/csswg-drafts/issues/1777
Mikko Rantalainen
1

As respostas existentes resolvem a maioria dos casos. No entanto, deparei-me com um caso em que precisava estar o conteúdo da célula da grade overflow: visible. Eu o resolvi posicionando-o absolutamente dentro de um invólucro (não ideal, mas o melhor que eu sei), assim:


.month-grid {
  display: grid;
  grid-template: repeat(6, 1fr) / repeat(7, 1fr);
  background: #fff;
  grid-gap: 2px;  
}

.day-item-wrapper {
  position: relative;
}

.day-item {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 10px;

  background: rgba(0,0,0,0.1);
}

https://codepen.io/bjnsn/pen/vYYVPZv

bjnsn
fonte
0

uma coisa mais fácil de fazer é definir a largura máxima do item de grade da seguinte maneira:

//for the container
.gridContainer{
    display: grid;
    grids-templates-column: repeat (12, 1fr);
 }

 //for the grid item
 .gridItem{
       max-width: 100%;
       grid-column: span 4  //4 can be any number from1-12 as we specified in the grid template
  }
Pedro JR
fonte
Estou um pouco confuso para ser honesto. Seu código não se parece com a pergunta original e aplicar max-width: 100% aos itens da grade (em vez de min-width: 0 da solução aceita) não resolverá o problema ...
Loilo
max-width impedirá que ele se reajuste em relação à sua largura filho
Pedro JR
Eu tentei reproduzir o seu código, e ele realmente funciona, mas não parece ser por causa da largura máxima: 100%, mas por causa da coluna da grade: extensão 4; sem definir uma coluna inicial. Defina uma coluna inicial (por exemplo, usando grid-column: 1 / span 4;) e ele quebrará o layout novamente. (Esse comportamento é meio estranho, mas tenho certeza de que há um canto em alguma parte da especificação em que isso é definido.)
Loilo
tudo certo, combinado. mas você não considera um voto positivo para mim ainda
Pedro JR
Para ser franco: 1. Esse é um problema resolvido há mais de três anos. 2. sua resposta não foi testada corretamente (seu CSS contém vários erros de digitação que precisam ser corrigidos antes que o navegador reconheça sua grade). E 3. sua resposta não atendeu ao exemplo da minha pergunta (caso contrário, você teria percebido que sua solução não funcionava com ela). - Então não, desculpe, mas não estou considerando um voto positivo.
Loilo