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

如何用原生JavaScript实现带动画的元素显示隐藏效果

原生JS实现无CSS依赖的show('slow')/hide('slow')等价效果

直接修改display属性会触发瞬时切换,核心原因是display属于离散CSS属性,不存在可插值的中间状态,浏览器会直接渲染最终样式。jQuery的show('slow')/hide('slow')本身也不是靠CSS过渡实现,而是通过JS逐帧修改元素尺寸、边距类属性完成动画,你完全可以用原生API复刻完全一致的效果,不需要引入任何额外CSS规则。

jQuery中slow参数对应动画时长为400ms,默认使用swing缓动曲线,以下是完全等价的原生实现,默认仅做尺寸类属性动画,不包含透明度、位移变化,就是你需要的组装式展开/收起效果:

/**
 * 等价jQuery show/hide动画 无CSS依赖
 * @param {HTMLElement} el 目标元素
 * @param {number} duration 动画时长 slow对应400ms
 * @param {'show'|'hide'} type 动画类型
 */
function toggleFormAnimate(el, duration = 400, type) {
  if (el.dataset.animating === 'true') return;
  el.dataset.animating = 'true';

  const sizeProps = [
    'height', 'paddingTop', 'paddingBottom',
    'marginTop', 'marginBottom',
    'borderTopWidth', 'borderBottomWidth'
  ];
  const getStyleVal = (target, prop) => parseFloat(window.getComputedStyle(target)[prop]) || 0;
  let startVals = {}, endVals = {};

  if (type === 'hide') {
    const curDisplay = window.getComputedStyle(el).display;
    el.style.display = curDisplay === 'none' ? 'block' : curDisplay;
    sizeProps.forEach(prop => {
      startVals[prop] = getStyleVal(el, prop);
      endVals[prop] = 0;
    });
  } else {
    // 临时显示元素获取原始目标尺寸
    el.style.visibility = 'hidden';
    const originDisplay = window.getComputedStyle(el).display;
    el.style.display = originDisplay === 'none' ? 'block' : originDisplay;
    sizeProps.forEach(prop => {
      endVals[prop] = getStyleVal(el, prop);
      startVals[prop] = 0;
    });
    el.style.visibility = '';
    sizeProps.forEach(prop => el.style[prop] = '0px');
  }
  el.style.overflow = 'hidden';

  // jQuery默认swing缓动
  const swingEase = (t) => 0.5 - Math.cos(t * Math.PI) / 2;
  const startTs = performance.now();

  function runFrame(now) {
    const progress = Math.min((now - startTs) / duration, 1);
    const easedProgress = swingEase(progress);

    sizeProps.forEach(prop => {
      const val = startVals[prop] + (endVals[prop] - startVals[prop]) * easedProgress;
      el.style[prop] = `${val}px`;
    });

    if (progress < 1) {
      requestAnimationFrame(runFrame);
    } else {
      // 动画结束 清理临时行内样式 不破坏原有布局
      el.dataset.animating = 'false';
      el.style.overflow = '';
      sizeProps.forEach(prop => el.style[prop] = '');
      el.style.display = type === 'hide' ? 'none' : '';
    }
  }
  requestAnimationFrame(runFrame);
}

// 替换原有jQuery代码即可
toggleFormAnimate(document.querySelector('#form-1'), 400, 'hide');
toggleFormAnimate(document.querySelector('#form-2'), 400, 'show');

实现说明

  • 全程通过JS动态写入行内样式完成动画,不需要提前写任何CSS类、transition或animation规则,动画结束后会自动清理所有临时添加的行内样式,不会影响元素原有响应式布局逻辑
  • 内置动画锁,避免短时间重复触发动画导致的样式错乱
  • 动画过程中自动添加overflow: hidden避免内容溢出,动画结束自动移除
  • 缓动曲线、动画时长和jQuery默认的slow参数完全对齐,视觉效果和原有实现无差异
  • 如果后续需要调整动画属性,只需要修改sizeProps数组即可,比如不需要边框动画就删掉数组里的border相关属性

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 00:09:38