Расширьте div посередине, а не только сверху и слева, используя CSS

Я не уверен, возможно ли это, но я подумал, что было бы здорово использовать CSS-преобразования для создания эффекта, при котором div расширяется от своего центра до заданной высоты и ширины, а не только от верхнего левого угла.

Например, если у меня есть (демонстрация)

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

и (префиксы производителей опущены для краткости)

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

При наведении это расширит квадрат вправо и вниз до 100 пикселей. Я бы хотел, чтобы он расширялся из середины.

Я знаю, что, вероятно, мог бы использовать transform: scale(x) (демонстрация), но на самом деле это не дает мне очень Макет "pixel perfect" (поскольку он основан на процентах), а также не влияет на окружающий макет (заставьте другие элементы, которые находятся в потоке документа, подстраиваться под его изменение размера). По сути, это то, что я хочу сделать, за исключением того, что поток документов будет затронут соответствующим образом.

Кто-нибудь знает способ сделать это без javascript?


person Jason    schedule 09.12.2011    source источник
comment
я думаю, вам понадобится javascript или jQuery, чтобы делать то, что вы хотите   -  person ONYX    schedule 10.12.2011


Ответы (4)


Ключ заключается в переходе поля по формуле. Есть небольшое «покачивание», которое раздражает во время перехода, если оно плавает.

ОТРЕДАКТИРОВАНО ДОБАВЛЕНИЕ ПАРАМЕТРОВ

Вариант 1: расширяется в пределах пространства, зарезервированного вокруг него 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) */
}

Вариант 2: расширяет элементы вокруг него 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 */
}

Вариант 3: расширяет элементы перед ним в потоке и сдвигает элементы после него 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;
}

ДОБАВЛЕН ПРИМЕР НЕПЛОЩАДЬ

Был сделан комментарий, что это не работает для неквадрата (одинаковая ширина/высота), но это просто означает, что во время перехода нужно настраивать по-разному для каждого направления. Итак, вот Вариант 2 (не квадратный), который начинается как прямоугольник, а ширина увеличивается в два раза по сравнению с высотой (поэтому изменяет даже форму прямоугольника) во время переход: расширяется по элементам вокруг него 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) */
}

Если бы width также менялось только на 100 пикселей (то есть со 110 пикселей до 210 пикселей), то margin: -50px все еще работало бы.

person ScottS    schedule 09.12.2011
comment
а если нет маржи? в моем реальном коде элемент не имеет полей:\ - person Jason; 10.12.2011
comment
@ Джейсон - вам нужно перейти на отрицательные поля. См. jsfiddle.net/xcWge/18. - person ScottS; 10.12.2011
comment
так что это потрясающе, и так близко к тому, что я ищу. последний бит - это не то, что материал вокруг него остается неподвижным, а то, что он фактически подстраивается под размер элемента. Я могу эффективно достичь того, что вы делаете с масштабом (по большей части). но я хочу, чтобы вещи вокруг него (в потоке) также корректировали свои позиции. - person Jason; 10.12.2011
comment
Я сомневаюсь, что вы можете получить это полностью. Для примера с плавающей запятой вы можете воздействовать на элементы после него, но не перед ним, вместо этого анимируя top и left: jsfiddle .net/xcWge/20. Проблема в том, что элементы до него определяют положение наводимых квадратов, а не определяют их. - person ScottS; 10.12.2011
comment
@Jason - проблема в том (как указано в моем комментарии выше), чтобы получить элемент выше и тот, который плавает влево для перемещения, к ним нужно применить отрицательное поле как часть перехода, но нет способа нацелить их через css при наведении на квадрат. - person ScottS; 10.12.2011
comment
на самом деле я не беспокоюсь о том, что было раньше, просто рядом и ниже :) я думаю, что смогу разобраться с этим. когда я это сделаю, я отмечу это. Спасибо! - person Jason; 10.12.2011
comment
@ Джейсон - мой другой пример забыл настроить поле для относительного положения. Это работает для правильной настройки положения следующих элементов: jsfiddle.net/xcWge/22 - person ScottS; 10.12.2011
comment
используя вашу идею, я получил его на работу. это было намного проще, чем я ожидал. спасибо! - person Jason; 10.12.2011
comment
ScottS Этот пример удивителен, если его принять за чистую монету. Но, похоже, это не работает, когда результирующая ширина и высота отличаются друг от друга. Мне нужно отобразить начальное маленькое окно/диалоговое окно, чтобы получить ввод от пользователя, а затем расширить его, чтобы охватить около 95% поверхности/окна просмотра браузера. Не могли бы вы добавить такой пример? - person azakgaim; 12.03.2018
comment
@azakgaim: если ширина и высота разные, вам просто нужно по-разному отрегулировать верхнее/нижнее (для высоты) и левое/правое (для ширины) поля, чтобы получить расширение по центру.< /b> Я немного не понимаю, как именно вы планируете взаимодействие input с расширением, и может случиться так, что то, что вы хотите сделать, невозможно сделать только с помощью css, но вот пример div, скрывающийся за по центру input, где div расширяется на :focus input до 95% размера экрана (я не проверял во всех браузерах): http://jsfiddle.net/e0atcndc/55/ - person ScottS; 13.03.2018

Вам также придется изменить его положение, чтобы сделать это, установив его относительное/абсолютное и изменив значение top по мере его анимации.

(редактировать на основе комментария)

Вместо абсолютного позиционирования вы можете попытаться сделать то же самое с отрицательным верхним полем. Это позволит сохранить его в документообороте. Однако каким-то образом вам нужно фактически переместить div, а также анимировать высоту/ширину.

person idrumgood    schedule 09.12.2011
comment
так что да, это та же проблема с использованием scale(), потому что это исключает его из потока документов. я хочу, чтобы остальная часть документа адаптировалась к изменению размера. - person Jason; 10.12.2011
comment
+1, потому что ваш добавленный комментарий о полях помог мне найти решение. - person ScottS; 10.12.2011

вам, возможно, придется сделать позицию div абсолютной, а затем отрегулировать левую и верхнюю позиции при наведении. пример jsFiddle

person ONYX    schedule 09.12.2011
comment
поэтому попробуйте добавить префикс поставщика к вашему переходу и посмотреть, что произойдет :) кроме того, это все еще дает эффект расширения слева вверху :\ - person Jason; 10.12.2011

Я делаю это, регулируя выравнивание по верхнему и левому краю при наведении. Пример: я добавлю 50 пикселей к ширине и сдвину ее влево на 25 пикселей, чтобы создать общий эффект расширения от середины.

person bennett_an    schedule 09.12.2011