css变量无法动态获取元素高度,因其为静态声明、不支持运行时计算;必须用js读取scrollheight后手动注入变量值,否则max-height动画会失效或截断。

不能靠 CSS 变量自动“计算”高度,必须用 JS 读取 scrollHeight 后手动设为变量值;否则所有基于 var(--menu-height) 的动画都会失效或截断。
为什么 CSS 变量本身无法动态获取元素高度
CSS 变量是静态声明的,不支持运行时计算。像 height: auto 或 scrollHeight 这类 DOM 属性,浏览器只在 JS 执行阶段暴露,CSS 引擎完全不可见。试图写 --menu-height: calc(100% + 1px) 或 --menu-height: attr(data-height px) 都不会读到真实内容高度。
- 常见错误:在 :root 里写
--menu-height: 0,然后指望媒体查询或伪类自动更新它——不行,变量值不会随 DOM 变化而重算 - 更隐蔽的坑:用
getComputedStyle读变量再 set,但没等元素渲染完成就取值,结果拿到 0 - 不要用
offsetHeight:它包含 border/padding,且未 display 时返回 0;scrollHeight才是内容撑开的真实高度
JS 获取 scrollHeight 并注入 CSS 变量的正确时机
必须等菜单元素已渲染、字体和图片加载完毕后再读取,否则高度不准。不能在 DOMContentLoaded 立即执行,得加一层保障。
- 推荐做法:用
requestAnimationFrame套一层,确保样式已应用:const menu = document.querySelector('.nav-menu');<br>requestAnimationFrame(() => {<br> document.documentElement.style.setProperty('--menu-height', menu.scrollHeight + 'px');<br>}); - 如果菜单初始是
display: none,先临时设为position: absolute; visibility: hidden; display: block,读完再恢复 - 避免在 resize 事件里频繁重设变量——高度基本不变,只在菜单项增删或字体加载后才需更新
max-height 动画中如何安全使用这个变量
设了 --menu-height 后,CSS 里不能直接写 max-height: var(--menu-height) 做过渡——部分 Safari 对变量参与 transition 支持不稳定,尤其配合 calc() 时。
- 最稳写法:
max-height: var(--menu-height, 0),并在 :root 初始设--menu-height: 0 - 展开时用 class 切换:
.menu.open { max-height: var(--menu-height, 500px); },fallback 值(如500px)要略大于最大可能高度 - 必须配
overflow: hidden,否则过渡中内容会溢出 - 别用
calc(var(--menu-height) + 20px)——Safari 16.4 之前会跳过动画,直接跳到终点
移动端点击链接后高度变量失效?检查这三个点
用户点完导航链接,菜单卡在展开态,不是变量没更新,而是状态没清空。
- JS 里监听的是
click,但触控设备上blur()不可靠,得用setTimeout(() => input.checked = false, 100) - 如果用了
input[type="checkbox"]+:checked方案,确保 checkbox 没被display: none彻底移出渲染树(旧版 Safari 会跳过状态更新) - 菜单收起后,记得重置变量:
document.documentElement.style.setProperty('--menu-height', '0'),否则下次展开可能沿用旧值
真正麻烦的不是怎么设变量,而是每次 DOM 变动后要不要重新读 scrollHeight、什么时候读、读完怎么同步到 CSS——这些边界条件,比动画本身更容易出问题。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











