You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

仅使用原生JS实现未知高度元素的CSS过渡:解决文本展开/收起淡入淡出功能的高度适配难题

解决方案:动态高度的展开/收起淡入淡出过渡

你的方案完全可行!问题确实出在操作时机和高度值的传递上——你已经拿到了真实高度,但没在正确的时机把它交给CSS过渡系统。下面我给你调整代码,完美实现自适应高度的淡入淡出展开效果:

核心思路

  1. 先把获取到的真实高度存储到元素的CSS变量或自定义属性中,让CSS能直接读取这个动态值
  2. 调整过渡逻辑:让.read-more从height: 0过渡到我们存储的真实高度,而不是硬编码的固定值
  3. 确保切换类名时,CSS已经能拿到正确的高度值,过渡才能平滑触发

修改后的完整代码

JavaScript 部分

document.addEventListener("DOMContentLoaded", function(event) {
  const txtElement = document.getElementById("txt");
  // 获取真实高度并存储为CSS变量
  const realHeight = txtElement.scrollHeight;
  txtElement.style.setProperty("--real-height", `${realHeight}px`);
  
  // 仅用于展示高度,可保留或删除
  const heightDisplay = document.getElementById("realHeight");
  heightDisplay.innerHTML += realHeight + "px";
});

const btn = document.querySelector(".read-more-btn");
const text = document.querySelector(".read-more");
const wrapper = document.querySelector(".wrapper");

wrapper.addEventListener("click", e => {
  const current = e.target;
  const isReadMoreBtn = current.className.includes("read-more-btn");
  if (!isReadMoreBtn) return;
  
  const currentText = e.target.parentNode.querySelector(".read-more");
  // 直接切换类名即可,CSS会自动使用我们预先存储的真实高度
  currentText.classList.toggle("read-more_open");
  
  current.textContent = current.textContent.includes("Read More") ? "Read Less" : "Read More";
});

CSS 部分

/* 切换类样式 */
.read-more {
  display: block;
  opacity: 0;
  height: 0;
  overflow: hidden; /* 必须加这个,防止内容溢出 */
  transition: all 0.5s ease;
}
.read-more_open {
  opacity: 1;
  /* 使用我们在JS中设置的CSS变量作为目标高度 */
  height: var(--real-height);
}
/* 其他样式保持不变 */
.wrapper {
  width: 20rem;
  background-color: black;
  color: white;
  margin: auto;
}
.contents {
  padding: 0.25rem;
}
.title {
  font-size: 1.7em;
  margin-bottom: 1rem;
  letter-spacing: 1px;
}
p {
  font-size: 0.8rem;
}
.read-more-btn {
  display: inline-block;
  color: white;
  background-color: grey;
  padding: 0.6rem 1.5rem;
  font-size: 1em;
  position: relative;
  z-index: 1;
  transition: all 0.5s;
  cursor: pointer;
}
.read-more-btn:hover {
  background-color: #fff;
  color: grey;
  box-shadow: 0 0 2rem rgba(0, 0, 0, 0.1);
  transform: translateY(-3px);
}

HTML 部分(无需修改,保持原结构即可)

<span id="realHeight">Real height: </span>
<div class="wrapper">
  <div class="contents">
    <h1 class="title">Some Title</h1>
    <p id="txt">
      ALWAYS VISIBLE CONTENT
      <span class="read-more">
        Fade in text with an unknown length which results in the unknown height of the paragraph. Fade in text with an unknown length which results in the unknown height of the paragraph. Fade in text with an unknown length which results in the unknown height of the paragraph. Fade in text with an unknown length which results in the unknown height of the paragraph. Fade in text with an unknown length which results in an unknown height of the paragraph.
      </span>
    </p>
    <p class="read-more-btn">Read More</p>
  </div>
</div>

关键修改点解释

  1. 存储真实高度到CSS变量:在DOMContentLoaded中,我们用style.setProperty把真实高度存在--real-height变量里,这样CSS可以直接引用这个动态值,不用硬编码。
  2. 添加overflow: hidden:这是过渡效果的关键,没有它的话,高度为0时内容还是会显示出来,过渡就失效了。
  3. 简化切换逻辑:现在只需要切换类名,CSS会自动处理从height:0到var(--real-height)的过渡,不需要在JS里手动设置高度——你之前的问题就是因为在类切换后才设置高度,此时过渡已经触发,来不及读取新的高度值。

这样修改后,不管你的文本长度如何变化,都能自动适配真实高度,实现平滑的淡入淡出展开/收起效果~

内容的提问来源于stack exchange,提问作者user16332407

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 12:32:30