Centrar un DIV de manera desigual usando CSS

23

Estoy centrando un DIV dentro de otro DIV usando un flexbox. Piense en una ventana de diálogo que aparece en el centro de la pantalla cuando sea necesario.

Funciona bien, sin embargo, se vería mucho mejor si el espacio arriba y abajo del diálogo no fuera exactamente igual, teniendo el 40% del espacio restante arriba y el 60% debajo del diálogo. Se vuelve complicado porque la altura del diálogo varía con la cantidad de texto dentro.

Entonces, por ejemplo, si la altura del navegador es de 1000 px, y la altura de la ventana de diálogo es de 400 px, quiero que el espacio vertical restante (600 px) sea de 240 px arriba y 360 px debajo del cuadro de diálogo. Podría hacerlo con Javascript, pero tengo curiosidad por saber si hay alguna manera inteligente con CSS. Intenté agregar un margen inferior al #dialogBox DIV, pero eso no funciona cuando la altura del diálogo se acerca a la altura del 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
fuente
¿Necesita el panel exterior para cubrir toda la ventana gráfica? Si no, iría con la solución de css-tricks.com/centering-css-complete-guide , sección "Tanto horizontal como verticalmente / ¿Es el elemento de ancho y alto desconocido?", Y modificaría los valores de porcentaje de traducción. (E incluso si necesita el tamaño de ventana gráfica principal [¿telón de fondo?], Debería poder combinar ambos: eliminar las cosas flexibles, las estancias de descanso.)
04FS
Sí, tengo un efecto de atenuación en el panel exterior, por lo que debe cubrir toda la ventana gráfica. Pero podría agregar otro DIV dentro de él, y su solución funcionaría bien. Gracias 04FS!
Björn Morén
En aras de la precisión, estás hablando de alineación vertical, no de centrado.
Michael Benjamin

Respuestas:

11

Use el pseudo elemento y la dirección de la columna para simular el espacio en blanco. Simplemente ajuste el flex-growdel pseudo elemento para controlar cuánto espacio libre debería ocupar cada uno. Igual flex-grow dará igual espacio:

También puedes usar 2y 3. Simplemente necesitamos mantener la misma proporción:

Otra idea es usar el valor superior igual 40%y rectificar la posición con la traducción (la misma lógica con50% cuando se centra)

#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
fuente
Muchas gracias Temani! Ambas soluciones funcionan perfectamente y parecen idénticas, excepto por el caso especial donde el diálogo es más alto que el navegador. La primera solución mantiene la parte superior del diálogo alineada con la parte superior del navegador, recortando en la parte inferior. La segunda cosecha tanto en el fondo como en la parte superior. Solo una cuestión de preferencia.
Björn Morén
5

Esta solución utiliza display: grid, es una función nueva, así que asegúrese de consultar el soporte del navegador y haga clic aquí para obtener más información.

Esta es la línea que controla los espacios superior e inferior:

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

El contenido del texto del fragmento se puede editar para que verifique que el cuadro se mantenga centrado incluso si la altura cambia.

#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
fuente
1
Consideraría el uso de 4fr auto 6fr. Lo que tiene funciona pero con algo de desbordamiento ya que 40% + 60% + 1fr siempre será mayor que 100% y está centrado, por lo que el overlow se dividirá en partes iguales desde la parte superior e inferior: jsfiddle.net/cobutn0e/2 . También notará que no es 100% como se esperaba
Temani Afif
Acabo de cambiar el 1fr a automático, prefiero dejarlo como% para que coincida con los valores de las preguntas. ¡Muchas gracias por señalar el error!
rafaelcastrocouto
auto y 1fr darán el mismo resultado en su caso, el problema es el uso de porcentaje; 1fr=minmax(auto,1fr)y en su caso, le corresponderá a autoya que no hay espacio libre ya que el 40% + 60% = 100% (es por eso que siempre tendrán desbordamiento)
Temani Afif
1
Aquí hay otro violín para ilustrar mi punto: jsfiddle.net/cobutn0e/3 observe cómo los 3 primeros son iguales, el tercero está cayendo a 0 y el último es lo que sugerí
Temani Afif
Ahora lo entiendo, tiene sentido. Voy a usar 40fr y 60fr ya que es lo mismo al final del día. ¡Gracias de nuevo por tomarse su tiempo para enseñarme!
rafaelcastrocouto
4

Puede agregar espaciadores divs y establecer el crecimiento flexible con una relación de 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
fuente
Solo ahora vi la respuesta de @Temani Afif, pero funciona igual con "después" y "antes"
Itay Gal
0

De manera simple usando la posición y el margen, supuse que la altura de su diálogo siempre es el 40% de la altura del 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
fuente
Hola, bienvenido, la próxima vez que lea la pregunta detenidamente, dice: "la altura del diálogo varía con la cantidad de texto dentro".
rafaelcastrocouto
1
@rafaelcastrocouto: ahora lo controla a través de la altura máxima en porcentaje, ya que dejarlo sin altura no resolverá el propósito de la estética del espacio superior e inferior.
Anshul Chaurasia