Solução
Use contêineres flexíveis aninhados.
Livre-se das alturas percentuais. Livre-se das propriedades da tabela. Livre-se vertical-align
. Evite posicionamento absoluto. Basta ficar com o flexbox todo o caminho.
Aplique display: flex
ao item flex ( .item
), tornando-o um contêiner flex. Isso define automaticamente align-items: stretch
, o que instrui o filho ( .item-inner
) a expandir toda a altura do pai.
Importante: Remova as alturas especificadas dos itens flexíveis para que este método funcione. Se uma criança tiver uma altura especificada (por exemplo height: 100%
), ela ignorará a align-items: stretch
vinda dos pais. Para que o stretch
padrão funcione, a altura da criança deve ser calculada como auto
(explicação completa ).
Tente isso (sem alterações no HTML):
.container {
display: flex;
flex-direction: column;
height: 20em;
border: 5px solid black
}
.item {
display: flex; /* new; nested flex container */
flex: 1;
border-bottom: 1px solid white;
}
.item-inner {
display: flex; /* new; nested flex container */
flex: 1; /* new */
/* height: 100%; <-- remove; unnecessary */
/* width: 100%; <-- remove; unnecessary */
/* display: table; <-- remove; unnecessary */
}
a {
display: flex; /* new; nested flex container */
flex: 1; /* new */
align-items: center; /* new; vertically center text */
background: orange;
/* display: table-cell; <-- remove; unnecessary */
/* vertical-align: middle; <-- remove; unnecessary */
}
<div class="container">
<div class="item">
<div class="item-inner">
<a>Button</a>
</div>
</div>
<div class="item">
<div class="item-inner">
<a>Button</a>
</div>
</div>
<div class="item">
<div class="item-inner">
<a>Button</a>
</div>
</div>
</div>
Demonstração do jsFiddle
Explicação
Meu problema é que .item-inner { height: 100% }
não está funcionando no webkit (Chrome).
Não está funcionando porque você está usando a porcentagem de altura de uma maneira que não está de acordo com a implementação tradicional da especificação.
10.5 Altura do conteúdo: a height
propriedade
porcentagem
Especifica uma altura percentual. A porcentagem é calculada em relação à altura do bloco contendo a caixa gerada. Se a altura do bloco que contém não for especificada explicitamente e esse elemento não estiver absolutamente posicionado, o valor será calculado como auto
.
auto
A altura depende dos valores de outras propriedades.
Em outras palavras, para que a altura percentual funcione em um filho em fluxo, o pai deve ter uma altura definida.
No seu código, o contêiner de nível superior tem uma altura definida: .container { height: 20em; }
O contêiner de terceiro nível tem uma altura definida: .item-inner { height: 100%; }
Mas entre eles, o contêiner de segundo nível - .item
- não tem uma altura definida. Webkit vê isso como um link ausente.
.item-inner
está dizendo ao Chrome: me dêheight: 100%
. O Chrome procura referência nos pais ( .item
) e responde: 100% do que? Não vejo nada (ignorando a flex: 1
regra que existe). Como resultado, aplica-se height: auto
(altura do conteúdo), de acordo com as especificações.
O Firefox, por outro lado, agora aceita a altura flexível de um pai como referência para a porcentagem de altura da criança. O IE11 e o Edge também aceitam alturas flexíveis.
Além disso, o Chrome aceitará flex-grow
como uma referência pai adequada se usado em conjunto comflex-basis
(qualquer valor numérico funciona ( auto
não funcionará), inclusive flex-basis: 0
). No momento da redação deste artigo, no entanto, essa solução falha no Safari.
#outer {
display: flex;
flex-direction: column;
height: 300px;
background-color: white;
border: 1px solid red;
}
#middle {
flex-grow: 1;
flex-basis: 1px;
background-color: yellow;
}
#inner {
height: 100%;
background-color: lightgreen;
}
<div id="outer">
<div id="middle">
<div id="inner">
INNER
</div>
</div>
</div>
Quatro Soluções
1. Especifique uma altura em todos os elementos pai
Uma solução confiável entre navegadores é especificar uma altura em todos os elementos pai. Isso evita a falta de links, que os navegadores baseados no Webkit consideram uma violação das especificações.
Observe que min-height
e max-height
não são aceitáveis. Deve ser a height
propriedade.
Mais detalhes aqui: Trabalhando com a height
propriedade CSS e os valores percentuais
2. Posicionamento relativo e absoluto do CSS
Aplique position: relative
aos pais e position: absolute
à criança.
Tamanho da criança com height: 100%
e width: 100%
ou use as propriedades de deslocamento: top: 0
, right: 0
, bottom: 0
, left: 0
.
Com o posicionamento absoluto, a altura percentual funciona sem uma altura especificada no pai.
3. Remova os contêineres HTML desnecessários (recomendado)
Há necessidade de dois contêineres por aí button
? Por que não remover .item
ou .item-inner
, ou ambos? Embora os button
elementos às vezes falhem como contêineres flexíveis , eles podem ser itens flexíveis. Considere criar button
um filho .container
ou .item
remover uma marcação gratuita.
Aqui está um exemplo:
.container {
height: 20em;
display: flex;
flex-direction: column;
border: 5px solid black
}
a {
flex: 1;
background: orange;
border-bottom: 1px solid white;
display: flex; /* nested flex container (for aligning text) */
align-items: center; /* center text vertically */
justify-content: center; /* center text horizontally */
}
<div class="container">
<a>Button</a>
<a>Button</a>
<a>Button</a>
</div>
4. Recipientes flexíveis aninhados (recomendado)
Livre-se das alturas percentuais. Livre-se das propriedades da tabela. Livre-se vertical-align
. Evite posicionamento absoluto. Basta ficar com o flexbox todo o caminho.
Aplique display: flex
ao item flex ( .item
), tornando-o um contêiner flex. Isso define automaticamente align-items: stretch
, o que instrui o filho ( .item-inner
) a expandir toda a altura do pai.
Importante: Remova as alturas especificadas dos itens flexíveis para que este método funcione. Se uma criança tiver uma altura especificada (por exemplo height: 100%
), ela ignorará a align-items: stretch
vinda dos pais. Para que o stretch
padrão funcione, a altura da criança deve ser calculada como auto
(explicação completa ).
Tente isso (sem alterações no HTML):
.container {
display: flex;
flex-direction: column;
height: 20em;
border: 5px solid black
}
.item {
display: flex; /* new; nested flex container */
flex: 1;
border-bottom: 1px solid white;
}
.item-inner {
display: flex; /* new; nested flex container */
flex: 1; /* new */
/* height: 100%; <-- remove; unnecessary */
/* width: 100%; <-- remove; unnecessary */
/* display: table; <-- remove; unnecessary */
}
a {
display: flex; /* new; nested flex container */
flex: 1; /* new */
align-items: center; /* new; vertically center text */
background: orange;
/* display: table-cell; <-- remove; unnecessary */
/* vertical-align: middle; <-- remove; unnecessary */
}
<div class="container">
<div class="item">
<div class="item-inner">
<a>Button</a>
</div>
</div>
<div class="item">
<div class="item-inner">
<a>Button</a>
</div>
</div>
<div class="item">
<div class="item-inner">
<a>Button</a>
</div>
</div>
</div>