我怎样才能过渡高度:0;高度:自动;使用CSS?
我正在尝试使用 CSS 过渡制作
向下滑动。
从 height: 0;
开始。悬停时,高度设置为 height:auto;
。然而,这导致它只是出现,而不是转换,如果我从 height: 40px;
到 height: auto;
,那么它会向上滑动到height: 0;
,然后突然跳到正确的高度。
如果不使用 JavaScript,我还能怎么做呢?
#child0 {
height: 0;
overflow: hidden;
background-color: #dedede;
-moz-transition: height 1s ease;
-webkit-transition: height 1s ease;
-o-transition: height 1s ease;
transition: height 1s ease;
}
#parent0:hover #child0 {
height: auto;
}
#child40 {
height: 40px;
overflow: hidden;
background-color: #dedede;
-moz-transition: height 1s ease;
-webkit-transition: height 1s ease;
-o-transition: height 1s ease;
transition: height 1s ease;
}
#parent40:hover #child40 {
height: auto;
}
h1 {
font-weight: bold;
}
The only difference between the two snippets of CSS is one has height: 0, the other height: 40.
<hr>
<div id="parent0">
<h1>Hover me (height: 0)</h1>
<div id="child0">Some content
<br>Some content
<br>Some content
<br>Some content
<br>Some content
<br>Some content
<br>
</div>
</div>
<hr>
<div id="parent40">
<h1>Hover me (height: 40)</h1>
<div id="child40">Some content
<br>Some content
<br>Some content
<br>Some content
<br>Some content
<br>Some content
<br>
</div>
</div>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(30)
在过渡中使用
max-height
而不是height
。并将max-height
的值设置为大于您的盒子所能达到的值。请参阅 Chris Jordan 在另一个 JSFiddle 演示。 com/a/20226830/18706">在这里回答。
Use
max-height
in the transition and notheight
. And set a value onmax-height
to something bigger than your box will ever get.See JSFiddle demo provided by Chris Jordan in another answer here.
您应该使用scaleY 来代替。
我在 jsfiddle 上制作了上述代码的供应商前缀版本,并更改了您的 jsfiddle 使用scaleY而不是高度。
编辑
有些人不喜欢
scaleY
转换内容的方式。如果这是一个问题,那么我建议使用clip
代替。You should use scaleY instead.
I've made a vendor prefixed version of the above code on jsfiddle, and changed your jsfiddle to use scaleY instead of height.
Edit
Some people do not like how
scaleY
transforms the content. If that is a problem then I suggest usingclip
instead.当涉及的高度之一是
auto
时,您当前无法在高度上设置动画,您必须设置两个显式高度。You can't currently animate on height when one of the heights involved is
auto
, you have to set two explicit heights.我一直使用的解决方案是首先淡出,然后缩小
font-size
、padding
和margin
值。它看起来与擦除不同,但它无需静态height
或max-height
即可工作。工作示例:
The solution that I've always used was to first fade out, then shrink the
font-size
,padding
andmargin
values. It doesn't look the same as a wipe, but it works without a staticheight
ormax-height
.Working example:
这是一个纯 CSS 解决方案,具有以下属性:
transform:scaleY(0)
不同),因此如果可折叠元素后面有内容,它会做正确的事情。height: auto
)状态下,整个内容始终具有正确的高度(与例如,如果您选择的max-height
结果太低了)。并且在折叠状态下,高度应该为零。演示
这是一个包含三个可折叠元素的演示,所有元素都有不同的高度,并且都使用相同的 CSS。您可能想在单击“运行片段”后单击“整页”。请注意,JavaScript 仅切换
collapsed
CSS 类,不涉及测量。 (您可以通过使用复选框或:target
来完成这个精确的演示,而无需任何 JavaScript)。另请注意,负责转换的 CSS 部分非常短,并且 HTML 仅需要一个额外的包装元素。它是如何运作的?
事实上,实现这一目标涉及两个转变。其中之一将
margin-bottom
从 0px(展开状态)转换为-2000px
折叠状态(类似于 这个答案)。这里的 2000 是第一个幻数,它基于您的盒子不会高于此的假设(2000 像素似乎是一个合理的选择)。单独使用
margin-bottom
过渡本身有两个问题:margin-bottom: -2000px
不会隐藏所有东西——即使在折叠的箱子里也会有可见的东西。这是我们稍后会做的一个小修复。解决第二个问题是第二个过渡出现的地方,这个过渡在概念上以包装器的最小高度为目标(“概念上”是因为我们实际上并没有使用
min-height
属性;稍后会详细介绍)。下面的动画展示了如何将具有相同持续时间的底部边距过渡与最小高度过渡相结合,为我们提供具有相同持续时间的从全高度到零高度的组合过渡。
左栏显示负底部边距如何将底部向上推,从而降低可见高度。中间的条显示最小高度如何确保在折叠情况下,过渡不会提前结束,而在展开情况下,过渡不会较晚开始。右栏显示了两者的组合如何使框在正确的时间内从全高度过渡到零高度。
在我的演示中,我选择 50px 作为最小高度值上限。这是第二个神奇数字,它应该低于盒子的高度。 50px 似乎也合理;您似乎不太可能经常想要使一个高度甚至不到 50 像素的元素可折叠。
正如你在动画中看到的,产生的过渡是连续的,但它是不可微分的——当最小高度等于底部边距调整的完整高度时,速度会突然发生变化。这在动画中非常明显,因为它对两个过渡都使用线性计时函数,并且整个过渡非常慢。在实际情况中(我的演示在顶部),转换只需要 300ms,并且底部边距转换不是线性的。对于这两种转换,我尝试过很多不同的计时函数,最终我觉得它们最适合最广泛的情况。
有两个问题需要解决:
我们通过在折叠情况下为容器元素赋予
max-height: 0
以及0s 0.3s
过渡来解决第一个问题。这意味着它并不是真正的过渡,而是应用了 max-height 并有延迟;它仅在过渡结束后适用。为了使其正常工作,我们还需要为相反的非折叠状态选择一个数字max-height
。但与 2000px 情况不同的是,选择太大的数字会影响过渡的质量,在这种情况下,这实际上并不重要。因此,我们可以选择一个非常高的数字,以至于我们知道没有任何高度可以接近这个数字。我选择了一百万像素。如果您觉得可能需要支持高度超过一百万像素的内容,那么 1) 抱歉,2) 只需添加几个零。第二个问题是我们实际上没有使用
min-height
来实现最小高度过渡的原因。相反,容器中有一个::after
伪元素,其height
从 50px 过渡到零。这与min-height
具有相同的效果:它不会让容器收缩到伪元素当前具有的任何高度以下。但因为我们使用的是height
,而不是min-height
,所以我们现在可以使用max-height
(再次应用延迟)一旦过渡结束,将伪元素的实际高度设置为零,确保至少在过渡之外,即使是小元素也具有正确的高度。因为min-height
比max-height
更强,所以如果我们使用容器的min-height
而不是伪元素的height
,则该方法将不起作用。就像上一段中的max-height
一样,这个max-height
也需要一个过渡相对端的值。但在本例中我们可以只选择 50px。在 Chrome(Win、Mac、Android、iOS)、Firefox(Win、Mac、Android)、Edge、IE11(除了我的演示中的 Flexbox 布局问题,我没有费心调试)和 Safari(Mac、iOS)中进行了测试)。说到 Flexbox,应该可以在不使用任何 Flexbox 的情况下完成这项工作;事实上,我认为您几乎可以在 IE7 中实现所有功能 - 除了您不会有 CSS 过渡这一事实,这使其成为一项毫无意义的练习。
This is a CSS-only solution with the following properties:
transform: scaleY(0)
), so it does the right thing if there's content after the collapsible element.height: auto
) state, the whole content always has the correct height (unlike e.g. if you pick amax-height
that turns out to be too low). And in the collapsed state, the height is zero as it should.Demo
Here's a demo with three collapsible elements, all of different heights, that all use the same CSS. You might want to click "full page" after clicking "run snippet". Note that the JavaScript only toggles the
collapsed
CSS class, there's no measuring involved. (You could do this exact demo without any JavaScript at all by using a checkbox or:target
). Also note that the part of the CSS that's responsible for the transition is pretty short, and the HTML only requires a single additional wrapper element.How does it work?
There are in fact two transitions involved in making this happen. One of them transitions the
margin-bottom
from 0px (in the expanded state) to-2000px
in the collapsed state (similar to this answer). The 2000 here is the first magic number, it's based on the assumption that your box won't be higher than this (2000 pixels seems like a reasonable choice).Using the
margin-bottom
transition alone by itself has two issues:margin-bottom: -2000px
won't hide everything -- there'll be visible stuff even in the collapsed case. This is a minor fix that we'll do later.Fixing this second issue is where the second transition comes in, and this transition conceptually targets the wrapper's minimum height ("conceptually" because we're not actually using the
min-height
property for this; more on that later).Here's an animation that shows how combining the bottom margin transition with the minimum height transition, both of equal duration, gives us a combined transition from full height to zero height that has the same duration.
The left bar shows how the negative bottom margin pushes the bottom upwards, reducing the visible height. The middle bar shows how the minimum height ensures that in the collapsing case, the transition doesn't end early, and in the expanding case, the transition doesn't start late. The right bar shows how the combination of the two causes the box to transition from full height to zero height in the correct amount of time.
For my demo I've settled on 50px as the upper minimum height value. This is the second magic number, and it should be lower than the box' height would ever be. 50px seems reasonable as well; it seems unlikely that you'd very often want to make an element collapsible that isn't even 50 pixels high in the first place.
As you can see in the animation, the resulting transition is continuous, but it is not differentiable -- at the moment when the minimum height is equal to the full height adjusted by the bottom margin, there is a sudden change in speed. This is very noticeable in the animation because it uses a linear timing function for both transitions, and because the whole transition is very slow. In the actual case (my demo at the top), the transition only takes 300ms, and the bottom margin transition is not linear. I've played around with a lot of different timing functions for both transitions, and the ones I ended up with felt like they worked best for the widest variety of cases.
Two problems remain to fix:
We solve the first problem by giving the container element a
max-height: 0
in the collapsed case, with a0s 0.3s
transition. This means that it's not really a transition, but themax-height
is applied with a delay; it only applies once the transition is over. For this to work correctly, we also need to pick a numericalmax-height
for the opposite, non-collapsed, state. But unlike in the 2000px case, where picking too large of a number affects the quality of the transition, in this case, it really doesn't matter. So we can just pick a number that is so high that we know that no height will ever come close to this. I picked a million pixels. If you feel you may need to support content of a height of more than a million pixels, then 1) I'm sorry, and 2) just add a couple of zeros.The second problem is the reason why we're not actually using
min-height
for the minimum height transition. Instead, there is an::after
pseudo-element in the container with aheight
that transitions from 50px to zero. This has the same effect as amin-height
: It won't let the container shrink below whatever height the pseudo-element currently has. But because we're usingheight
, notmin-height
, we can now usemax-height
(once again applied with a delay) to set the pseudo-element's actual height to zero once the transition is over, ensuring that at least outside the transition, even small elements have the correct height. Becausemin-height
is stronger thanmax-height
, this wouldn't work if we used the container'smin-height
instead of the pseudo-element'sheight
. Just like themax-height
in the previous paragraph, thismax-height
also needs a value for the opposite end of the transition. But in this case we can just pick the 50px.Tested in Chrome (Win, Mac, Android, iOS), Firefox (Win, Mac, Android), Edge, IE11 (except for a flexbox layout issue with my demo that I didn't bother debugging), and Safari (Mac, iOS). Speaking of flexbox, it should be possible to make this work without using any flexbox; in fact I think you could make almost everything work in IE7 – except for the fact that you won't have CSS transitions, making it a rather pointless exercise.
你可以,用一点非语义的技巧。我通常的方法是对具有单个子项的外部 DIV 的高度进行动画处理,该子项是一个无样式的 DIV,仅用于测量内容高度。
人们希望能够放弃
.measuringWrapper
并将 DIV 的高度设置为 auto 并使其具有动画效果,但这似乎不起作用(高度已设置,但没有动画发生)。我的解释是动画运行需要明确的高度。当高度(起始高度或结束高度)为
auto
时,您无法获得高度动画。You can, with a little bit of non-semantic jiggery-pokery. My usual approach is to animate the height of an outer DIV which has a single child which is a style-less DIV used only for measuring the content height.
One would like to just be able to dispense with the
.measuringWrapper
and just set the DIV's height to auto and have that animate, but that doesn't seem to work (the height gets set, but no animation occurs).My interpretation is that an explicit height is needed for the animation to run. You can't get an animation on height when either height (the start or end height) is
auto
.接受的答案适用于大多数情况,但当您的
div
高度变化很大时,它就不起作用了——动画速度不依赖于内容的实际高度,并且看起来不稳定。您仍然可以使用 CSS 执行实际动画,但需要使用 JavaScript 来计算项目的高度,而不是尝试使用
auto
。不需要 jQuery,尽管如果您想要兼容性,您可能需要对此进行一些修改(适用于最新版本的 Chrome :))。The accepted answer works for most cases, but it doesn't work well when your
div
can vary greatly in height — the animation speed is not dependent on the actual height of the content, and it can look choppy.You can still perform the actual animation with CSS, but you need to use JavaScript to compute the height of the items, instead of trying to use
auto
. No jQuery is required, although you may have to modify this a bit if you want compatibility (works in the latest version of Chrome :)).自从这个问题首次提出以来,浏览器已经发生了很大的变化。您现在可以转换网格轨道大小,并且它得到了很好的支持,这意味着这个问题可以通过使用 CSS 网格布局 解决
这里我正在转换第二个网格项从
0fr
(0 个小数单位)到1fr
(1 个小数单位)。Browsers have moved on a fair bit since this question was first raised. You can now transition grid track sizes and it is very well supported meaning that this problem can be solved using CSS Grid Layout
Here I am transitioning the second grid item from
0fr
(0 Fractional Units) to1fr
(1 Fractional Units).我的解决方法是将
max-height
转换为精确的内容高度,以获得流畅的动画,然后使用transitionEnd
回调来设置max-height
到9999px
以便内容可以自由调整大小。My workaround is to transition
max-height
to the exact content height for a nice smooth animation, then use atransitionEnd
callback to setmax-height
to9999px
so the content can resize freely.使用 CSS3 过渡对高度进行动画处理的视觉解决方法是对填充进行动画处理。
您还没有完全获得完整的擦除效果,但是调整过渡持续时间和填充值应该可以让您足够接近。如果您不想显式设置高度/最大高度,这应该就是您正在寻找的。
http://jsfiddle.net/catharsis/n5XfG/17/ (摘自stephband上面的jsFiddle )
A visual workaround to animating height using CSS3 transitions is to animate the padding instead.
You don't quite get the full wipe effect, but playing around with the transition-duration and padding values should get you close enough. If you don't want to explicitly set height/max-height, this should be what you're looking for.
http://jsfiddle.net/catharsis/n5XfG/17/ (riffed off stephband's above jsFiddle)
根据 MDN Web 文档,
auto
值已有意从 CSS 转换规范中排除,因此不要使用height: auto
,而是使用height: 100%
,top
>,或网格和 Flex 布局中的flex
属性。展开/折叠覆盖层
展开/折叠滑动覆盖层
According to MDN Web Docs,
auto
values have been intentionally excluded from the CSS transitions spec, so instead ofheight: auto
, useheight: 100%
,top
, or theflex
property in grid and flex layouts.Expanding/collapsing an overlay
Expanding/collapsing a sliding overlay
使用
max-height
为每个状态提供不同的过渡缓动和延迟。HTML:
CSS:
参见示例:http://jsfiddle.net/0hnjehjc/1/
Use
max-height
with different transition easing and delay for each state.HTML:
CSS:
See example: http://jsfiddle.net/0hnjehjc/1/
没有硬编码值。
没有 JavaScript。
没有近似值。
诀窍是使用隐藏的 &重复
div
以使浏览器理解 100% 的含义。只要您能够复制想要设置动画的元素的 DOM,此方法就适用。
No hard coded values.
No JavaScript.
No approximations.
The trick is to use a hidden & duplicated
div
to get the browser to understand what 100% means.This method is suitable whenever you're able to duplicate the DOM of the element you wish to animate.
更新,2024
我不推荐我原来的回复,但我会把它留给后代。自从 flexbox 得到广泛支持以来,我一直依赖在此问题上寻找解决方案,例如本问题中的问题。
我推荐这个答案,它使用弹性容器以及
height: 0
和 < code>height: 100% 以避免任何类型的“魔法值”。原始(已过时),来自 2016 年
当我发布这篇文章时,已经有超过 30 个答案,但我觉得我的答案在已经已接受的答案< /a> 作者:杰克。
我对仅仅使用 max-height 和 CSS3 过渡所产生的问题并不满意,因为正如许多评论者指出的那样,您必须将 max-height 值设置得非常接近到实际高度,否则你会得到延迟。有关该问题的示例,请参阅 JSFiddle。
为了解决这个问题(同时仍然不使用 JavaScript),我添加了另一个 HTML 元素来转换
transform:translateY
CSS 值。这意味着同时使用
max-height
和translateY
:max-height
允许元素下推其下方的元素,而translateY
给出了我们想要的“即时”效果。max-height
的问题仍然存在,但其影响有所减弱。这意味着您可以为
max-height
值设置更大的高度,而不必担心它。总体好处是,在返回(折叠)时,用户会立即看到
translateY
动画,因此max-height
的长度并不重要。需要。Fiddle 解决方案
Update, 2024
I do not recommend my original response, but I will leave it for posterity. Ever since flexbox became widely supported, I have relied on it for solutions to issues like the one in this question.
I recommend this answer, which uses a flex container and a transition between
height: 0
andheight: 100%
to avoid any sort of "magic values".Original (outdated), from 2016
As I post this there are over 30 answers already, but I feel my answer improves on the already accepted answer by jake.
I was not content with the issue that arises from simply using
max-height
and CSS3 transitions, since as many commenters noted, you have to set yourmax-height
value very close to the actual height or you'll get a delay. See this JSFiddle for an example of that problem.To get around this (while still using no JavaScript), I added another HTML element that transitions the
transform: translateY
CSS value.This means both
max-height
andtranslateY
are used:max-height
allows the element to push down elements below it, whiletranslateY
gives the "instant" effect we want. The issue withmax-height
still exists, but its effect is lessened.This means you can set a much larger height for your
max-height
value and worry about it less.The overall benefit is that on the transition back in (the collapse), the user sees the
translateY
animation immediately, so it doesn't really matter how long themax-height
takes.Solution as Fiddle
无
max-height
,使用relative
定位,适用于li
元素,&是纯 CSS:除了 Firefox 之外,我没有在任何浏览器中进行过测试,但从 CSS 来看,它应该适用于所有浏览器。
FIDDLE: http://jsfiddle.net/n5XfG/2596/
CSS
HTML
No
max-height
, usesrelative
positioning, works onli
elements, & is pure CSS:I have not tested in anything but Firefox, though judging by the CSS, it should work on all browsers.
FIDDLE: http://jsfiddle.net/n5XfG/2596/
CSS
HTML
很多答案,有些比其他更好,大多数使用 JS。我相信我通过两个易于理解的用例解决了这个问题。
切换覆盖
A lot of answers, some better than other, most using JS. I believe I figured this out in two use-cases that are easy to understand.
Toggle an overlay
Toggle in the document flow
I wrote a blog post about these techniques.
编辑:向下滚动以获取更新的答案
我正在制作一个下拉列表,看到了这篇文章...有很多不同的答案,但我决定也分享我的下拉列表,...它并不完美,但至少它只会使用 css 进行下拉!我一直在使用 transform:translateY(y) 将列表转换为视图...
您可以在测试中看到更多内容
http://jsfiddle.net/BVEpc/4/
我将 div 放在每个 li 后面,因为我的下拉列表来自上方,为了正确显示它们,这是需要的,我的 div 代码是:
悬停是:
并且因为 ul 高度设置为它可以越过你的身体的内容content 这就是为什么我对 ul:
和悬停:
转换后的第二次是延迟,并且在我的下拉列表被动画关闭后它将被隐藏......
希望以后有人能受益于此。
编辑:我简直不敢相信人们真的使用这个原型!此下拉菜单仅适用于一个子菜单,仅此而已!
我更新了一个更好的菜单,它可以有两个子菜单,用于 ltr 和 rtl 方向,并支持 IE 8。
LTR 小提琴
RTL 小提琴
希望将来有人发现这很有用。
EDIT: Scroll down for updated answer
I was making a drop down list and saw this Post ... many different answers but I decide to share my drop down list too, ... It's not perfect but at least it will using only css for drop down! I've been using transform:translateY(y) to transform the list to the view ...
You can see more in the test
http://jsfiddle.net/BVEpc/4/
I've placed div behind every li because my drop down list are coming from up and to show them properly this was needed, my div code is:
and hover is :
and because ul height is set to the content it can get over your body content that's why I did this for ul:
and hover:
the second time after transition is delay and it will get hidden after my drop down list has been closed animately ...
Hope later someone get benefit of this one.
EDIT: I just can't believe ppl actually using this prototype! this drop down menu is only for one sub menu and that's all!!
I've updated a better one that can have two sub menu for both ltr and rtl direction with IE 8 support.
Fiddle for LTR
Fiddle for RTL
hopefully someone find this useful in future.
Flexbox 解决方案
优点:
缺点:
它的工作方式是始终在包含内容的元素上使用 flex-basis: auto 并进行过渡而是使用 flex-grow 和 flex-shrink 。
编辑:受 Xbox One 界面启发改进了 JS Fiddle。
JS 小提琴
Flexbox Solution
Pros:
Cons:
The way it works is by always having flex-basis: auto on the element with content, and transitioning flex-grow and flex-shrink instead.
Edit: Improved JS Fiddle inspired by the Xbox One interface.
JS Fiddle
仅使用灵活高度 CSS 的解决方案
我偶然发现了一个使用 Flex 行为的奇怪解决方案。它至少可以在 Chrome 和 Firefox 中运行。
首先,高度过渡仅在0和100%之间起作用,两个
数值。由于“auto”不是数值,因此是小数
0 和“auto”之间不存在增量。 100%是灵活的
值,因此不需要特定的高度。
其次,隐藏内容的外容器和内容器都必须设置为 display: flex 和 flex-direction: column。
第三,外容器必须有高度属性。将其设置为0仅当所有内容都包含在外部容器中时才能保持平滑过渡,因为伸缩行为优先于高度。 编辑:Paintoshi建议使用height: fit-content,所以容器下方的任何内容也会被下推。
按“运行代码片段”按钮查看正在运行的转换。
它只是 CSS,没有具体的高度。
Flexible Height CSS Only Solution
I've stumbled upon a quirky solution using flex behavior. It works in at least Chrome and Firefox.
First, the height transition only works between 0 and 100%, two
numeric values. Since "auto" is not a numeric value, fractional
increments don't exist between 0 and "auto". 100% is a flexible
value, so no specific height is required.
Second, both the outer container and the inner container of the hidden content must be set to display: flex with flex-direction: column.
Third, the outer container must have a height property. Setting it to 0 maintains a smooth transition only when everything is contained in the outer container because the flex behavior takes precedence over the height. Edit: Paintoshi suggested using height: fit-content, so that any content below the container is also pushed down.
Press the Run Code Snippet button to see the transition in action.
It's CSS only, with no specific height.
您可以从 height:0 转换到 height:auto,前提是您还提供了 min-height 和 max-height。
You can transition from height:0 to height:auto providing that you also provide min-height and max-height.
您可以通过使用剪辑路径创建反向(折叠)动画来做到这一点。
You could do this by creating a reverse (collapse) animation with clip-path.
一句话解决方案:使用填充过渡。对于大多数情况(例如手风琴)来说这已经足够了,甚至更好,因为填充值通常不大,所以速度很快。
如果你想让动画过程更好,只需提高padding值即可。
One sentence solution: Use padding transition. It's enough for most of cases such as accordion, and even better because it's fast due to that the padding value is often not big.
If you want the animation process to be better, just raise the padding value.
扩展@jake的答案,过渡将一直达到最大高度值,从而产生极快的动画 - 如果您设置 :hover 和 off 的过渡,那么您可以稍微控制疯狂的速度。
所以li:hover是当鼠标进入状态时,然后非hovered属性上的转换将是鼠标离开。
希望这会有所帮助。
例如:
这是一个小提琴: http://jsfiddle.net/BukwJ/
Expanding on @jake's answer, the transition will go all the way to the max height value, causing an extremely fast animation - if you set the transitions for both :hover and off you can then control the crazy speed a little bit more.
So the li:hover is when the mouse enters the state and then the transition on the non-hovered property will be the mouse leave.
Hopefully this will be of some help.
e.g:
Here's a fiddle: http://jsfiddle.net/BukwJ/
我理解这个问题要求不使用 JavaScript 的解决方案。但对于那些感兴趣的人来说,这是我仅使用一点 JS 的解决方案。
好的,所以默认高度会改变的元素的css设置为
height: 0;
并且打开时height: auto;
。它还具有transition: height .25s escape;
。但问题当然是它不会转换为height: auto;
或从height: auto;
转换所以我所做的是在打开或关闭时将高度设置为
scrollHeight
元素的属性。这种新的内联样式将具有更高的特异性,并覆盖height: auto;
和height: 0;
并运行过渡。打开时,我添加一个
transitionend
事件监听器,该监听器仅运行一次,然后删除内联样式,将其设置回height: auto;
这将允许元素在必要时调整大小,正如这个带有子菜单的更复杂的示例 https://codepen.io/ninjabonsai/pen/GzYyVe关闭时,我会在下一个 事件循环之后立即删除内联样式< /a> 使用 setTimeout 循环,无延迟。这意味着
height: auto;
被暂时覆盖,从而允许转换回height 0;
I understand the question asks for a solution without JavaScript. But for those interested here's my solution using just a little bit of JS.
ok, so the element's css whose height will change by default is set to
height: 0;
and when openheight: auto;
. It also hastransition: height .25s ease-out;
. But of course the problem is that it won't transition to or fromheight: auto;
So what i've done is when opening or closing set the height to the
scrollHeight
property of the element. This new inline style will have higher specificity and override bothheight: auto;
andheight: 0;
and the transition runs.When opening i add a
transitionend
event listener which will run just once then remove the inline style setting it back toheight: auto;
which will allow the element to resize if necessary, as in this more complex example with sub menus https://codepen.io/ninjabonsai/pen/GzYyVeWhen closing i remove the inline style right after the next event loop cycle by using setTimeout with no delay. This means
height: auto;
is temporarily overridden which allows the transition back toheight 0;
该解决方案使用了一些技术:
padding-bottom:100%
“hack”,其中百分比是根据元素的当前宽度定义的。 有关此技术的更多信息。但结果是我们仅使用 CSS 获得高性能转换,并且单一的过渡函数可以平滑地实现过渡;圣杯!
当然,也有一个缺点!我不知道如何控制内容被截断的宽度(
overflow:hidden
);由于 padding-bottom hack,宽度和高度密切相关。不过可能有办法,所以会回来讨论它。https://jsfiddle.net/EoghanM/n1rp3zb4/28/
This solution uses a few techniques:
padding-bottom:100%
'hack' where percentages are defined in terms of the current width of the element. More info on this technique.The upshot though is that we get performant transitioning using CSS only, and a single transition function to smoothly achieve the transition; the holy grail!
Of course, there's a downside! I can't work out how to control the width at which content gets cut off (
overflow:hidden
); because of the padding-bottom hack, the width and height are intimately related. There may be a way though, so will come back to it.https://jsfiddle.net/EoghanM/n1rp3zb4/28/
我最近在
li
元素上转换max-height
,而不是包装ul
。原因是,与大
max-heights
相比,小max-heights
的延迟远不那么明显(如果有的话),而且我还可以设置我的max-height
值相对于li
的font-size
,而不是使用ems
或的任意巨大数字>雷姆斯
。如果我的字体大小为
1rem
,我会将max-height
设置为3rem
(以容纳换行文本)。您可以在此处查看示例:http://codepen.io/mindfullsilence/pen/DtzjE
更新:自从我写下这个答案以来,CSS 已经发展到包含更多优雅的技术。我相信今天最好的方法是使用 css grid 和 grid-template-row,如这个答案中所述:
https://stackoverflow.com/a/69802208/3594432
I've recently been transitioning the
max-height
on theli
elements rather than the wrappingul
.The reasoning is that the delay for small
max-heights
is far less noticeable (if at all) compared to largemax-heights
, and I can also set mymax-height
value relative to thefont-size
of theli
rather than some arbitrary huge number by usingems
orrems
.If my font size is
1rem
, I'll set mymax-height
to something like3rem
(to accommodate wrapped text). You can see an example here:http://codepen.io/mindfullsilence/pen/DtzjE
Update: CSS has evolved to include much more elegant techniques since I wrote this answer. I believe the best today is by using css grid and grid-template-row as described in this answer:
https://stackoverflow.com/a/69802208/3594432
每当 DOM 发生更改时,为跟踪元素设置
style=""
属性。 名为mutant-transition的插件 您可以使用CSS进行转换,而不是使用hacks。您不必编写任何 JavaScript。只需包含 JavaScript 库并指定您想要在 HTML 中查看的属性即可。您不必使用固定高度的 CSS。使用data-mutant-attributes="X"
设置您想要在相关元素上跟踪的内容。这使用 MutationObserver 来跟踪 DOM 中的更改。您无需进行任何设置或使用 JavaScript 来手动制作动画。自动跟踪更改。但是,因为它使用 MutationObserver,所以这只会在 IE11+ 中进行转换。 < IE11 将看到快速更改(无过渡)。
Fiddles
height: auto
到height: 100%
的转换>height: auto
Set the
style=""
attributes for tracked elements whenever there's a change in the DOM. plugin called mutant-transition You can use CSS for your transitions and not use hacks. You don't have to write any JavaScript. Just include the JavaScript library and specify which attributes you want to watch in the HTML. You don't have to use fixed height CSS. Set what you want to track on the element in question usingdata-mutant-attributes="X"
.This uses MutationObserver to follow changes in the DOM. You don't have to set anything up or use JavaScript to manually animate. Changes are tracked automatically. However, because it uses MutationObserver, this will only transition in IE11+. < IE11 will see snap-changes (no transition).
Fiddles
height: auto
toheight: 100%
height: auto
when adding children具有
line-height
、padding
、opacity
和margin
的替代纯 CSS 解决方案:Alternate CSS-only solution with
line-height
,padding
,opacity
andmargin
:我意识到这个帖子已经过时了,但它在某些谷歌搜索中排名很高,所以我认为它值得更新。
您还只需获取/设置元素自身的高度:
您应该在内联脚本标记中的 target_box 结束标记之后立即转储此 Javascript。
I realize this thread is getting old, but it ranks high on certain Google searches so I figure it's worth updating.
You also just get/set the element's own height:
You should dump this Javascript immediately after target_box's closing tag in an inline script tag.
杰克对最大高度动画的回答很棒,但我发现设置较大的最大高度引起的延迟很烦人。
人们可以将可折叠内容移动到内部 div 中,并通过获取内部 div 的高度来计算最大高度(通过 JQuery 它是outerHeight())。
这是一个 jsfiddle 链接: http://jsfiddle.net/pbatey/duZpT
这是一个绝对最小的 jsfiddle所需代码量:http://jsfiddle.net/8ncjjxh8/
Jake's answer to animate the max-height is great, but I found the delay caused by setting a large max-height annoying.
One could move the collapsable content into an inner div and calculate the max height by getting the height of the inner div (via JQuery it'd be the outerHeight()).
Here's a jsfiddle link: http://jsfiddle.net/pbatey/duZpT
Here's a jsfiddle with the absolute minimal amount of code required: http://jsfiddle.net/8ncjjxh8/