Expande div desde el centro en lugar de solo arriba e 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 un alto y ancho predeterminados, en lugar de solo desde la esquina superior izquierda.

Por ejemplo, si tengo ( demo )

y (prefijos del vendedor omitidos por brevedad)

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

Al pasar el mouse, esto expandirá el cuadrado hacia la derecha y hacia abajo hasta 100 px. Me gustaría que se expanda 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 perfect” (ya que está basado en porcentajes), y tampoco afecta el diseño circundante (hacer que otros elementos que se encuentran en el flujo de documentos 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 ?

La clave es hacer una transición del margen por una fórmula. Hay un pequeño “meneo” que es molesto durante la transición si se flota.

OPCIONES AÑADIDAS EDITADAS

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 : Se expande sobre los elementos antes de que fluya y cambia 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; } 

AÑADIDO EJEMPLO NO CUADRADO

Se hizo un comentario de que esto no funciona para un no cuadrado (mismo ancho / alto), pero eso solo significa que uno tiene que ajustarse de manera diferente para cada dirección durante la transición. Entonces aquí está la Opción 2 (con no cuadrados) que comienza como un rectángulo, y el ancho se expande dos veces tanto como la altura (por lo que cambia la forma del rectángulo, incluso) 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 cambiara 100px también (así que de 110px a 210px), entonces solo un margin: -50px hubiera funcionado.

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

(editar basado en el comentario)

En lugar de posicionamiento absoluto, podría 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, necesitas mover el div y animar el alto / ancho.

es posible que tengas que convertir tu posición div en absoluta y luego ajustar la posición izquierda y superior al desplazarte. Ejemplo jsFiddle

Hago esto ajustando la alineación superior e izquierda en el vuelo estacionario también. Por ejemplo, añadiré 50 px al ancho y lo moveré 25px a la izquierda para dar el efecto general de expandirlo desde el centro.