使用CSS将div从中间扩展而不仅仅是顶部和左侧。

33

我不确定这是否可行,但我认为使用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)演示),但这并不能提供给我一个非常“像素完美”的布局(因为它是基于百分比的),而且它也不会影响周围的布局(让其他在文档流中的元素调整到其大小)。这基本上就是我想要做的,只是文档流相应地受到影响。

有没有人知道一种无需JavaScript即可实现这样做的方法?


我认为你需要使用JavaScript或jQuery来实现你想要的功能。 - ONYX
4个回答

68
关键是通过公式进行边距的过渡。如果它被浮动,过渡期间会有一点令人讨厌的“摇晃”。 编辑添加选项 选项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从110px变为210px这样变化了100px,那么margin: -50px仍然可以正常工作。


那如果没有边距怎么办?在我的实际代码中,该元素没有边距:\ - Jason
@Jason--你需要转换为负边距。请参见http://jsfiddle.net/xcWge/18/。 - ScottS
所以这很棒,而且非常接近我要找的东西。最后一点不是周围的东西保持不动,而是它实际上根据元素的大小进行调整。我可以通过缩放(在大部分情况下)有效地实现你正在做的事情。但是我也希望周围的东西(在流中)也能调整它们的位置。 - Jason
我怀疑你无法完全做到这一点。对于浮点示例,您可以影响其后的元素,但不能影响其前面的元素,而是应该通过动画效果来控制“top”和“left”的值:http://jsfiddle.net/xcWge/20/。问题在于它之前的元素决定了悬停方块的位置,而不是它本身决定了那些元素的位置。 - ScottS
我其实不担心之前的东西,只是接下来和下面的部分 :) 我想我可能能够解决这个问题。当我解决了,我会标记一下的。谢谢! - Jason
显示剩余5条评论

2
你需要在动画过程中转换它的位置,将其设置为相对/绝对定位,并更改top值。
(根据评论编辑)
不使用绝对定位,你可以尝试使用负上边距来实现相同的效果。这将保持其在文档流中。但是,你需要移动div并同时动画化高度/宽度。

所以,使用 scale() 存在与此相同的问题,因为它会将其从文档流中移除。我希望文档的其余部分能够根据其调整大小而自动调整。 - Jason
+1 是因为你关于边距的评论帮助我想出了解决方案。 - ScottS

1

你可能需要将你的 div 位置设置为绝对定位,然后在悬停时调整左侧和顶部位置。jsFiddle 示例


所以尝试为您的过渡添加供应商前缀,看看会发生什么 :) 另外,这仍然会产生从左上角扩展的效果:\ - Jason

0

我通过在悬停时调整顶部和左侧对齐方式来实现这一点。例如:我会将宽度增加50像素并向左移动25像素,以使其从中间扩展。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接