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

如何在JavaScript中获取动态内容宽度并实现CSS width过渡?

问题:JavaScript动态调整元素宽度并实现CSS过渡失效问题

我在JavaScript中调整width属性时遇到问题:想要调整.btnFocus类的宽度以适配子节点(图片与文本),同时让CSS过渡正常生效,但获取.btnFocus的宽度时总是出问题——要么拿到子节点添加前的宽度值,要么直接触发代码报错。

预期实现流程:

  • 初始状态下,.hotspot元素无任何子节点;用户点击该元素时,将data-content中的内容(图片+文本)添加到.hotspot内部。
  • JavaScript获取添加内容后的.hotspot元素宽度。
  • 通过CSS过渡效果让.hotspot的宽度平滑过渡到步骤2获取的宽度值。

现有代码

treat.html

<div id="clickBox">
  <a class="hotspot" data-content="Forehead <img src='/images/common file/logo2.png' class='hotLogo'>
    <span class='fontRed'> Deep</span>"></a>
  <a class="hotspot" data-content="Chin <img src='/images/common file/logo_purple.png' class='hotLogo'>
    <span class='fontPurple'> Volume</span>"></a>
</div>

treat.css

#clickBox .hotspot {
  position: absolute;
  width: 1rem;
  height: 1rem;
  background-image: url("/images/2.treat/rect.png");
  background-size: cover;
  border-radius: 50%;
  padding: 0.3rem;
  opacity: 0.5;
  box-shadow: 0 3px 6px 0 rgba(0, 0, 0, 0.16);
  cursor: pointer;
  transition: 1s ease-in-out;
  transition-property: width, border-radius;
}

.hotspot>.hotLogo {
  width: 55px;
}
#clickBox .hotspot.btnFocus {
  /* width gonna be changed in js file*/
  width: 1rem;
  height: auto;
  opacity: 0.8;
  border-radius: 15px;
  overflow: hidden;
  text-overflow: clip;
  white-space: nowrap;
}

treat.js

let hotspot = document.querySelectorAll(".hotspot");

hotspot.forEach(function (element) {
  element.addEventListener("click", function () {
    smallBtn(element);
  });
});

function smallBtn(element) {
  if (element.classList.contains("btnFocus")) {
    element.innerHTML = "";
    element.classList.toggle("btnFocus");
  } else {
    hotspot.forEach(function (element) {
      element.innerHTML = "";
      element.classList.remove("btnFocus");
    });
    let content = element.dataset["content"];
    // cause error at below
    let contentWidth = content.getBoundingClientRect().width;
    let btnFocus = document.querySelector("btnFocus");
    console.log("contentWidth : ",contentWidth);

    btnFocus.style.width = contentWidth;
    element.classList.add("btnFocus");
    element.innerHTML = content;
  }
}

我还尝试过使用element.style.setProperty("--contentWidth", contentWidth + "px")及CSS变量,但都无效。我需要正确获取contentWidth值来修改btnFocus的宽度。


问题分析

  1. 错误获取内容宽度:直接对data-content的字符串调用getBoundingClientRect()会报错,因为字符串不是DOM元素,没有该方法。
  2. DOM操作顺序错误:在添加.btnFocus类和内容之前就尝试获取该类元素,此时元素还未添加类,且选择器写错(缺少.),导致返回null。
  3. 宽度计算时机不对:必须先将内容插入DOM,才能计算元素真实渲染后的宽度。

修正方案

修改后的treat.js

let hotspot = document.querySelectorAll(".hotspot");

hotspot.forEach(function (element) {
  element.addEventListener("click", function () {
    smallBtn(element);
  });
});

function smallBtn(element) {
  if (element.classList.contains("btnFocus")) {
    element.innerHTML = "";
    element.classList.toggle("btnFocus");
    // 重置宽度为初始值,保证下次过渡正常触发
    element.style.width = "";
  } else {
    // 先重置所有hotspot的状态
    hotspot.forEach(function (el) {
      el.innerHTML = "";
      el.classList.remove("btnFocus");
      el.style.width = "";
    });

    // 1. 先给目标元素添加类和内容
    element.classList.add("btnFocus");
    element.innerHTML = element.dataset.content;

    // 2. 等待DOM渲染完成后计算宽度
    requestAnimationFrame(() => {
      const contentWidth = element.getBoundingClientRect().width;
      // 先重置宽度为初始值,触发过渡起点
      element.style.width = "1rem";
      // 触发重绘后再设置目标宽度,确保过渡生效
      requestAnimationFrame(() => {
        element.style.width = `${contentWidth}px`;
      });
    });
  }
}

可选CSS补充调整

为避免padding影响宽度计算,给.btnFocus添加盒模型设置:

#clickBox .hotspot.btnFocus {
  width: 1rem;
  height: auto;
  opacity: 0.8;
  border-radius: 15px;
  overflow: hidden;
  text-overflow: clip;
  white-space: nowrap;
  box-sizing: border-box; /* 添加此行 */
}

关键修正说明

  • 先插入内容再计算宽度:必须将data-content的内容插入DOM后,才能通过getBoundingClientRect()获取真实渲染宽度。
  • 使用requestAnimationFrame:确保DOM完成渲染后再计算宽度,避免拿到未渲染的错误值。
  • 修复选择器错误:直接使用当前点击的element操作,无需额外查询,更高效且避免选择器错误。
  • 分步设置宽度触发过渡:先将宽度设为初始值1rem,再设置目标宽度,确保CSS过渡能捕捉到状态变化。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 20:54:53