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

如何为实时变化宽度的表单容器添加平滑过渡动画

可自扩展表单宽度动画实现方案

直接按「交互逻辑绑定+CSS过渡配置」两步实现即可,全程不需要复杂动画库,性能和流畅度都能达标:

  • 交互逻辑部分:给输入框绑定input事件做状态判断即可,不要用keydown/keypress事件——后者覆盖不到中文输入法联想输入、鼠标粘贴、右键清空内容等场景,很容易出现状态判断错位。每次内容变化时,判断输入框去除首尾空格后的值长度:长度大于0就触发表单展开,值完全为空就触发表单收缩回初始宽度。
  • 动画配置避坑:别直接给width: auto加过渡,浏览器没法计算auto的具体数值,会导致过渡完全失效;也别用JS逐帧改宽度做动画,性能差容易掉帧。直接用CSS transition配合明确的宽度数值,就能跑出60帧的丝滑效果。

基础固定宽度展开/收缩实现(最常用,性能最好)

直接给输入框设置初始宽度和展开宽度,加过渡属性即可,代码示例:

/* 输入框基础样式 */
.form-input {
  outline: none;
  border: 1px solid #e5e7eb;
  border-radius: 6px;
  padding: 8px 12px;
  font-size: 14px;
  /* 初始收缩状态宽度,可按需调整 */
  width: 180px;
  /* 过渡配置:0.25秒时长,用自然缓动函数 */
  transition: width 0.25s cubic-bezier(0.4, 0, 0.2, 1);
}
/* 展开状态类 */
.form-input.expanded {
  /* 展开后宽度,可按需调整 */
  width: 320px;
}

对应的JS逻辑:

const input = document.querySelector('.form-input');
input.addEventListener('input', () => {
  if (input.value.trim().length > 0) {
    input.classList.add('expanded');
  } else {
    input.classList.remove('expanded');
  }
});

如果用Tailwind CSS开发,不需要写自定义CSS,直接给输入框加类名即可:

<input 
  class="transition-all duration-250 ease-out w-[180px] expanded:w-[320px] px-3 py-2 border rounded"
  type="text"
>

进阶:宽度随输入内容自适应的动画实现

如果需要表单宽度完全贴合输入内容长度,不是固定展开值,可以加一个和输入框字体、内边距、字号完全一致的隐藏测量元素,每次输入时同步内容拿到实际文本宽度,再赋值给输入框,配合过渡就能实现无跳变的贴合式扩展:

<style>
/* 测量用的隐藏span,样式必须和输入框完全一致 */
.width-measure {
  position: absolute;
  visibility: hidden;
  white-space: nowrap;
  font-size: 14px;
  padding: 8px 12px;
}
.form-input {
  position: relative;
  outline: none;
  border: 1px solid #e5e7eb;
  border-radius: 6px;
  padding: 8px 12px;
  font-size: 14px;
  width: 180px;
  min-width: 180px;
  transition: width 0.25s cubic-bezier(0.4, 0, 0.2, 1);
}
</style>

<span class="width-measure"></span>
<input class="form-input" type="text">

<script>
const input = document.querySelector('.form-input');
const measure = document.querySelector('.width-measure');
input.addEventListener('input', () => {
  const val = input.value.trim();
  if (!val) {
    input.style.width = '180px';
    return;
  }
  // 同步内容到测量元素,拿到实际文本宽度
  measure.textContent = val;
  // 加2px冗余宽度避免文字挤到换行
  const targetWidth = measure.offsetWidth + 2;
  input.style.width = `${Math.max(targetWidth, 180)}px`;
});
</script>

预期效果参考:

  • 收缩状态:
    收缩状态表单
  • 展开状态:
    展开状态表单

内容的提问来源于stack exchange,提问作者Usama Abdul Razzaq

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 10:39:27