在 CSS 中,auto 等关键词不是一个具体的数值,无法直接进行动画过渡,例如下面的代码并不能产生过渡效果:
.wrapper {
height: 0;
transition: height 0.5s;
}
.wrapper.expanded {
height: auto;
}
不过可以通过以下方式来实现类似的效果。最新的浏览器提案也提到了数值到关键字的过渡问题,并且提出了两种新的解决方案。
一些文章可能会使用足够大的
max-height来实现,不过这里不推荐使用,因为动画效果不好看。下面介绍一些推荐的方法。
使用 CSS Grid 布局
部分浏览器的 CSS Grid 布局中,grid-template-rows 是支持过渡的,所以可以这样实现高度从 0 到 auto 的过渡。
.wrapper {
display: grid;
grid-template-rows: 0fr;
transition: grid-template-rows 0.5s;
}
.wrapper.expanded {
grid-template-rows: 1fr;
}
缺点:兼容性不太好。
使用 JavaScript 动态计算高度
<style>
.container {
overflow: hidden;
height: 0;
transition: height 0.5s ease-out;
}
.container.expanded {
height: auto;
}
</style>
<button onclick="toggle()">Toggle</button>
<div id="content" class="container">
<p>This is some content that will expand and collapse.</p>
<p>More content...</p>
</div>
<script>
function toggle() {
const content = document.getElementById('content');
if (content.classList.contains('expanded')) {
content.style.height = content.scrollHeight + 'px';
requestAnimationFrame(() => {
content.style.height = '0';
content.classList.remove('expanded');
});
} else {
content.style.height = content.scrollHeight + 'px';
content.classList.add('expanded');
content.addEventListener('transitionend', () => {
content.style.height = 'auto';
}, { once: true });
}
}
</script>
实现复杂,但是兼容性好。
使用 calc-size()
CSS 的 calc-size() 函数将诸如 auto 之类的值转换为特定的像素值,从而可以用于过渡。
calc-size() 支持以下值:
automin-contentmax-contentfit-contentstretchcontain
.wrapper {
height: 0;
transition: height 0.5s;
}
.wrapper.expanded {
height: calc-size(auto);
}
calc-size() 预计在 Chrome 129 版本发布。
使用 interpolate-size 全局属性
CSS 的 interpolate-size 属性可以让我们在根元素上设置插值计算的规则,这样针对整个页面都会生效。
interpolate-size 有两个值,一个是 allow-keywords 所有关键字,一个是仅限数字 numeric-only。
-
numeric-only:设置了这个属性之后,如果插值的属性值不是数字的话,就不会产生过渡的效果。 -
allow-keywords:设置了这个属性,只要是合法的属性值,都会插值计算,从而都会产生过渡效果。
html {
interpolate-size: allow-keywords;
}
.wrapper {
height: 0;
transition: height 0.5s;
}
.wrapper.expanded {
height: auto;
}
interpolate-size 预计在 Chrome 129 版本发布。
参考
W3C 草案
https://drafts.csswg.org/css-values-5/#funcdef-calc-size
WebKit
https://github.com/WebKit/standards-positions/issues/348
https://developer.chrome.google.cn/docs/css-ui/animate-to-height-auto