Centralize um DIV de maneira desigual usando CSS

23

Estou centralizando um DIV dentro de outro DIV usando um flexbox. Pense em uma janela de diálogo que aparece no centro da tela quando necessário.

Funciona bem, no entanto, ficaria muito melhor se o espaço acima e abaixo da caixa de diálogo não fosse exatamente igual, tendo 40% do espaço restante acima e 60% abaixo da caixa de diálogo. Fica complicado porque a altura da caixa de diálogo varia com a quantidade de texto existente.

Por exemplo, se a altura do navegador é de 1000 px e a da janela de diálogo é de 400 px, quero que o espaço vertical restante (600 px) seja 240 px acima e 360 ​​px abaixo da caixa de diálogo. Eu poderia fazê-lo com Javascript, mas estou curioso para saber se existe alguma maneira inteligente com CSS. Tentei adicionar uma margem inferior ao #dialogBox DIV, mas isso não funciona quando a altura da caixa de diálogo está chegando à altura do navegador.

#dialogBoxPanel
  {
  position:absolute;
  display:flex;
  align-items:center;
  justify-content:center;
  left:0px;
  top:0px;
  width:100%;
  height:100%;
}
#dialogBox
  {
  width:350px;
}
<div id="dialogBoxPanel">
  <div id="dialogBox">Text</div>
</div>

Björn Morén
fonte
Você precisa do painel externo para cobrir toda a janela de exibição? Caso contrário, eu usaria a solução em css-tricks.com/centering-css-complete-guide , seção "Horizontal e verticalmente / é o elemento de largura e altura desconhecidas?" E modificaria os valores percentuais de conversão. (E mesmo se você precisar do tamanho da janela de visualização completa pai [pano de fundo?], Poderá combinar os dois
elimine
Sim, eu tenho um efeito de escurecimento no painel externo, portanto ele precisa cobrir toda a janela de exibição. Mas eu poderia adicionar outro DIV dentro dele, e sua solução funcionaria bem. Graças 04FS!
Björn Morén
Por uma questão de precisão, você está falando de alinhamento vertical, não de centralização.
Michael Benjamin

Respostas:

11

Use o pseudo elemento e a direção da coluna para simular o espaço em branco. Simplesmente ajuste o flex-growpseudo-elemento para controlar quanto espaço livre cada um deve ocupar. Flex-grow igual dará espaço igual:

Você também pode usar 2e 3. Simplesmente precisamos manter a mesma proporção:

Outra idéia é usar o valor superior igual a 40%e retificar a posição com translação (mesma lógica com a 50%centralização)

#dialogBoxPanel {
  position: absolute;;
  left: 0px;
  top: 0px;
  width: 100%;
  height: 100%;
  /* the center */
  background:linear-gradient(red,red) center/100% 1px no-repeat;
}

#dialogBox {
  position:relative;
  top:40%;
  width: 350px;
  transform:translateY(-40%);
  margin:auto;
  border:1px solid;
}
<div id="dialogBoxPanel">
  <div id="dialogBox">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc hendrerit diam eu nisl fringilla ornare. Pellentesque aliquam quam et tellus egestas sodales. Interdum et malesuada fames ac ante ipsum primis in faucibus. Proin bibendum,</div>
</div>

Temani Afif
fonte
Muito obrigado Temani! Ambas as soluções funcionam perfeitamente e parecem idênticas, exceto no caso especial em que a caixa de diálogo é mais alta que o navegador. A primeira solução mantém a parte superior da caixa de diálogo alinhada com a parte superior do navegador, cortando na parte inferior. As segundas colheitas inferior e superior. Apenas uma questão de preferência.
Björn Morén
5

Esta solução utiliza display: grid, é um novo recurso. Verifique o suporte do navegador e clique aqui para saber mais.

Esta é a linha que controla os espaços superior e inferior:

grid-template-rows: 40fr [content-start] auto [content-end] 60fr;

O conteúdo do texto do trecho pode ser editado para verificar se a caixa permanece centralizada, mesmo que a altura mude.

#dialogBoxPanel {
    display: grid;
    place-content: center;
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    grid-template-rows: 40fr [content-start] auto [content-end] 60fr;
}
#dialogBox {
    border: 1px solid;
    width: 350px;
    grid-area: content;
}
<div id="dialogBoxPanel">
   <div id="dialogBox" contenteditable>Text</div>
</div>

rafaelcastrocouto
fonte
11
Eu consideraria o uso de 4fr auto 6fr. O que você tem funciona, mas com algum estouro, já que 40% + 60% + 1fr sempre será maior que 100% e você está centralizando, de modo que o excesso será dividido igualmente da parte superior e inferior: jsfiddle.net/cobutn0e/2 . Você também notará que não é 100% como o esperado #
Temani Afif 24/11/19
Acabei de alterar o 1fr para automático, prefiro deixá-lo como% para corresponder aos valores da pergunta. Muito obrigado por apontar o erro!
Rafaelcastrocouto
auto e 1fr fornecerão o mesmo resultado no seu caso, o problema é o uso de porcentagem; 1fr=minmax(auto,1fr)e no seu caso vai cair para autocomo não há espaço livre desde 40% + 60% = 100% (é por isso que você sempre terá overflow)
temanitas Afif
11
aqui está outro violino para ilustrar meu argumento: jsfiddle.net/cobutn0e/3 observe como os 3 primeiros são iguais, o terceiro está caindo para 0 e o último é o que sugeri
temanitas Afif
Agora entendi, faz sentido. Vou usar 40fr e 60fr, pois é o mesmo no final do dia. Mais uma vez obrigado por dedicar seu tempo para me ensinar!
Rafaelcastrocouto
4

Você pode adicionar divs de espaçadores e definir o crescimento flexível com a proporção 4: 6.

#dialogBoxPanel {
  position: absolute;
  display: flex;
  flex-direction: column;
  align-items: center;

  left: 0px;
  top: 0px;
  width: 100%;
  height: 100%;
}

#dialogBox {
  width: 350px;
  border: 1px solid black;
}

.spacer-top{
  flex-grow: 4;
}
.spacer-bottom{
  flex-grow: 6;
<div id="dialogBoxPanel">
  <div class="spacer-top"></div>
  <div id="dialogBox">Text</div>
  <div class="spacer-bottom"></div>
</div>

Itay Gal
fonte
Só agora vi a resposta de @Temani Afif, mas funciona da mesma forma com "depois" e "antes" #
Itay Gal
0

Maneira simples usando a posição e a margem, assumi que a altura da caixa de diálogo é sempre 40% da altura do navegador.

.modal{
            max-height:50%;
            width:400px;
            margin: 10% auto 5% auto;
            position:absolute;
            top:0;
            bottom:0;
            right:0;
            left:0;
            overflow-y: auto
        }
        .modal-body{
            background-color: beige;
            padding: 20px;
            line-height: 21px
        }

HTML

<div class="modal">
 <div class="modal-body">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea </div>
</div>
Anshul Chaurasia
fonte
Olá, seja bem-vindo. Da próxima vez, leia a pergunta com atenção, ela afirma: "a altura da caixa de diálogo varia com a quantidade de texto existente".
Rafaelcastrocouto
11
@rafaelcastrocouto - agora controlá-lo via altura máxima em porcentagem, pois deixá-lo sem altura não resolverá as questões de estética estética do espaço superior e inferior.
Anshul Chaurasia