Expanda div desde el centro en lugar de solo arriba y a la izquierda usando CSS


No estoy seguro de si esto es posible, pero pensé que sería genial usar transformaciones CSS para crear un efecto donde un div se expande desde su centro a una altura y anchura predeterminadas, en lugar de solo desde la esquina superior izquierda.

Por ejemplo, si tengo (demo)

<div id="square"></div>

Y (prefijos de proveedor omitidos por brevedad)

#square {
    width: 10px;
    height: 10px;
    background: blue;
    transition: width 1s, height 1s;
}
#square:hover {
    width: 100px;
    height: 100px;
}

On hover, esta se ampliará el cuadrado a la derecha y abajo a 100px. Me gustaría que se expandiera desde el medio.

Soy consciente de que probablemente podría usar transform: scale(x) (demo ), pero esto realmente no me proporciona un diseño muy "pixel perfecto" (ya que está basado en porcentajes), y tampoco afecta el diseño circundante (hacer que otros elementos que están en el flujo del documento se ajusten a su redimensionamiento). Esto es esencialmente lo que quiero hacer, excepto con el flujo de documentos afectado en consecuencia.

¿Alguien sabe de una manera de hacer esto sin javascript?

Author: Jason, 2011-12-10

4 answers

La clave es hacer la transición del margen por una fórmula. Hay un pequeño "meneo" que es molesto durante la transición si está flotando.

EDITED AÑADIENDO OPCIONES

Opción 1: Se expande dentro del espacio reservado a su alrededor http://jsfiddle.net/xcWge/14/:

#square {
    width: 10px;
    height: 10px;
    margin: 100px; /*for centering purposes*/
    -webkit-transition: width 1s, height 1s, margin 1s;
    -moz-transition: width 1s, height 1s, margin 1s;
    -ms-transition: width 1s, height 1s, margin 1s;
    transition: width 1s, height 1s, margin 1s;
}
#square:hover {
    width: 100px;
    height: 100px;
    margin: 55px; /* initial margin - (width change (and/or height change)/2), so here 100px is initial margin, and the change is (100px final W/H - 10px initial W/H = 90px change, so 100px - (90px / 2 [= 45px]) = 55px) */
}

Opción 2: Se expande sobre los elementos a su alrededor http://jsfiddle.net/xcWge/18/:

#square {
    width: 10px;
    height: 10px;
    margin: 0; /*for centering purposes*/
    -webkit-transition: width 1s, height 1s, margin 1s;
    -moz-transition: width 1s, height 1s, margin 1s;
    -ms-transition: width 1s, height 1s, margin 1s;
    transition: width 1s, height 1s, margin 1s;
}
#square:hover {
    width: 110px;
    height: 110px;
    margin: -50px; /* 0 - (110px - 10px [= 100px]) / 2 =  -50px */
}

Opción 3: Expande sobre elementos antes de él en flujo y desplaza elementos después de él http://jsfiddle.net/xcWge/22/:

#square {
    width: 10px;
    height: 10px;
    margin: 0;
    position: relative;
    top: 0;
    left: 0;
    -webkit-transition: width 1s, height 1s, top 1s, left 1s, margin 1s;
    -moz-transition: width 1s, height 1s, top 1s, left 1s, margin 1s;
    -ms-transition: width 1s, height 1s, top 1s, left 1s, margin 1s ;
    transition: width 1s, height 1s, top 1s, left 1s, margin 1s;
}
#square:hover {
    width: 110px;
    height: 110px;
    top: -50px; /* initial top[0] - (new height[110px] - initial height[10px] [=100px])/2 [=50px] = -50px) */
    left: -50px; /* initial left[0] - (new width[110px] - initial width[10px] [=100px])/2 [=50px] = -50px) */
    margin-right: -50px;
    margin-bottom: -50px;
}

EJEMPLO NO CUADRADO AÑADIDO

Se hizo un comentario esto no funciona para un no cuadrado (mismo ancho/alto), pero eso solo significa que uno tiene que ajustar de manera diferente para cada dirección durante la transición. Así que aquí está Opción 2 (con no cuadrado) que comienza como un rectángulo, y el ancho se expande el doble que la altura (por lo que cambia rectángulo shape even) durante la transición: Se expande sobre los elementos a su alrededor http://jsfiddle.net/xcWge/2131 /

#rectangle {
    width: 110px;
    height: 10px;
    margin: 0; /*for centering purposes*/
    -webkit-transition: width 1s, height 1s, margin 1s;
    -moz-transition: width 1s, height 1s, margin 1s;
    -ms-transition: width 1s, height 1s, margin 1s;
    transition: width 1s, height 1s, margin 1s;
}
#rectangle:hover {
    width: 310px;
    height: 110px;
    margin: -50px -100px; /* initial margin - ((initial margin - width change (or height change))/2) */
}

Si el width solo estuviera cambiando por 100px también (de 110px a 210px), entonces solo un margin: -50px habría funcionado.

 59
Author: ScottS,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-13 18:37:30

Tendrá que hacer una transición de su posición para hacer esto también, configurándolo en relativo/absoluto y cambiando el valor top a medida que se anima.

(editar basado en comentario)

En lugar de posicionamiento absoluto, podrías intentar hacer el mismo tipo de cosas con un margen superior negativo. Eso lo mantendría en el flujo de documentos. De alguna manera, sin embargo, necesita mover realmente el div, así como animar la altura/anchura.

 2
Author: idrumgood,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-12-09 21:30:34

Es posible que tenga que hacer que su posición div sea absoluta y luego ajustar la posición izquierda y superior en hover. jsFiddle ejemplo

 1
Author: ONYX,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-12-09 21:38:19

Hago esto ajustando la alineación superior e izquierda en hover también. Por ejemplo: agregaré 50 px al ancho y lo moveré a la izquierda 25px para dar el efecto de expansión desde el medio.

 0
Author: bennett_an,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-12-09 21:32:49