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

切换display属性时CSS transition失效问题咨询

问题原因与解决方案

为什么切换display属性会导致transition失效?

CSS过渡(transition)仅对有连续数值变化的可动画属性生效,而display: none是一个「二元切换」属性——元素要么完全脱离页面渲染树(不可见),要么完全参与渲染(可见),没有任何中间状态。

当你在JS中同时执行两个操作:

  1. 移除tr的d-none类(将display从none改为table-row)
  2. 给div添加expanded类(将height从0改为200px)

浏览器会将这两个操作合并为一次重绘,直接让元素从「不可见」状态跳到「height:200px可见」状态,完全跳过了transition需要的从0到200px的渐变过程,因此过渡动画失效。

而移除d-none逻辑后,tr始终处于渲染状态,div的height变化是连续的数值过渡,符合transition的触发条件,所以动画能正常运行。

解决方案

方案1:用height+overflow替代display:none隐藏元素

通过设置tr的height:0和overflow:hidden实现默认隐藏,避免使用display:none,同时保留过渡效果:

修改后的CSS

/* 控制tr的显示/隐藏过渡 */
.inventory-row {
  height: 0;
  overflow: hidden;
  transition: height 0.3s linear;
}
.inventory-row.expanded {
  height: 200px; /* 与内部div的高度匹配 */
}

/* 内部div的过渡保持不变 */
.inventory {
  height: 0px;
  max-height: 200px;
  overflow-y: auto;
  transition: height .3s linear;
}
.inventory.expanded{
  height: 200px;
}

修改后的HTML

<tr class="data-row">
    ...
    <td class="mb-0 p-1 text-end" style="height: 36px"><h6 class="text-sm mb-0"><em class="table-icon fas fa-chevron-down text-primary cursor-pointer" onclick="expand_card(this)" id="" aria-hidden="true"></em></h6></td>
</tr>
<!-- 移除d-none,添加inventory-row类 -->
<tr class="mb-0 p-1 inventory-row" id="inventory-table-">
    <td class="bg-gray-100 py-0 px-2" id="" colspan="8" style="vertical-align: top;"><div class="inventory" style="" id="inventory-div-"></div></td>
</tr>

修改后的JS

function expand_card(e) {
    let open = e.classList.contains("open");
    const inventoryRow = document.getElementById('inventory-table-' + e.id);
    const inventoryDiv = document.getElementById('inventory-div-' + e.id);
    
    if (open) {
        inventoryRow.classList.remove('expanded');
        inventoryDiv.classList.remove('expanded');
        cards_inventory_table_delete(e.id);
        e.classList.remove("open");
    } else {
        inventoryRow.classList.add('expanded');
        inventoryDiv.classList.add('expanded');
        cards_read(e.id);
        e.classList.add("open");
    }
}

方案2:延迟触发div的过渡动画

如果必须保留display:none,可以通过requestAnimationFrame让浏览器先完成tr的显示渲染,再触发div的过渡:

修改后的JS

function expand_card(e) {
    let open = e.classList.contains("open");
    const inventoryTable = document.getElementById('inventory-table-' + e.id);
    const inventoryDiv = document.getElementById('inventory-div-' + e.id);
    
    if (open) {
        // 先收起div,等过渡结束后再隐藏tr
        inventoryDiv.classList.remove('expanded');
        setTimeout(() => {
            inventoryTable.classList.add('d-none');
        }, 300); // 时间与transition的duration一致
        cards_inventory_table_delete(e.id);
        e.classList.remove("open");
    } else {
        // 先显示tr,再延迟触发div的过渡
        inventoryTable.classList.remove('d-none');
        requestAnimationFrame(() => {
            inventoryDiv.classList.add('expanded');
        });
        cards_read(e.id);
        e.classList.add("open");
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 14:15:38