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

CSS Transition无法识别内联自定义变量问题排查

问题原因分析
  1. 动画叠加掩盖效果:你给section和p元素都套用了.hidden类,section的translateX(-100%)位移动画会带动内部所有p元素整体移动,完全覆盖了p自身的位移动画,导致p的transition-delay延迟效果被彻底掩盖,视觉上看起来像是自定义变量未生效。
  2. 监听范围逻辑错误:你的IntersectionObserver同时监听了所有.hidden元素(包括section和内部p),当section进入视口时,内部所有p会被同时触发添加.show类——即便p的延迟参数生效,也会因为和section动画同步启动,无法体现出段落依次延迟的需求效果。
解决方案

下面提供两种可行的修复方案,你可以根据需求选择:

方案一:分离section与p的动画逻辑(推荐)

通过给section单独定义动画类,调整Observer监听范围,让section先完成显示动画,再按顺序触发内部段落的延迟显示:

修改后的完整代码

<html>
<head>
    <style>
        @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@200;400;700&display=swap');
        body {
            background-color: #131316;
            color: #ffffff;
            padding: 0;
            margin: 0;
            font-family: 'Poppins', sans-serif;
        }
        section {
            display: grid;
            place-items: center;
            align-content: center;
            min-height: 100vh;
            padding: 0px 20%;
        }
        /* 给section单独定义隐藏/显示类,避免和p的动画冲突 */
        .section-hidden {
            opacity: 0;
            filter: blur(5px);
            transform: translateY(20%);
            transition: all 1s ease-out;
        }
        .section-show {
            opacity: 1;
            filter: blur(0);
            transform: translateY(0);
        }
        /* p元素的动画类保留 */
        .hidden {
            opacity: 0;
            filter: blur(5px);
            transform: translateX(-100%);
            transition: all 1s ease-out;
        }
        .show {
            opacity: 1;
            filter: blur(0);
            transform: translateX(0);
        }
        /* 保留p的延迟设置,增强动画层次感 */
        section p {
            transition-delay: calc(200ms * var(--order));
        }
    </style>
</head>
<body>
    <section class="section-hidden">
        <p class="hidden" style="--order: 1;" >Far far away, behind the word mountains, far from the countries Vokalia and Consonantia, there live the blind texts.</p>
        <p class="hidden" style="--order: 2;" >Separated they live in Bookmarksgrove right at the coast of the Semantics, a large language ocean. A small river named Duden flows by their place and supplies it with the necessary regelialia.</p>
        <p class="hidden" style="--order: 3;" >It is a paradisematic country, in which roasted parts of sentences fly into your mouth.</p>
        <p class="hidden" style="--order: 4;" >Even the all-powerful Pointing has no control about the blind texts it is an almost unorthographic life One day however a small line of blind text by the name of Lorem Ipsum decided to leave for the far World of Grammar.</p>
        <p class="hidden" style="--order: 5;" >The Big Oxmox advised her not to do so, because there were thousands of bad Commas, wild Question Marks and devious Semikoli, but the Little Blind Text didn’t listen. She packed her seven versalia, put her initial into the belt and made herself on the way.</p>
    </section>
    <section class="section-hidden">
        <p class="hidden" style="--order: 1;" >Far far away, behind the word mountains, far from the countries Vokalia and Consonantia, there live the blind texts.</p>
        <p class="hidden" style="--order: 2;" >The Big Oxmox advised her not to do so, because there were thousands of bad Commas, wild Question Marks and devious Semikoli, but the Little Blind Text didn’t listen. She packed her seven versalia, put her initial into the belt and made herself on the way.</p>
    </section>

    <script>
        const observer = new IntersectionObserver((entries, observer) => {
            entries.forEach(entry => {
                if (!entry.isIntersecting) return;
                // 触发section的显示动画
                entry.target.classList.add('section-show');
                // 获取section内的所有段落
                const paragraphs = entry.target.querySelectorAll('p.hidden');
                paragraphs.forEach(p => {
                    // 读取内联定义的--order变量,计算延迟时间
                    const order = parseInt(getComputedStyle(p).getPropertyValue('--order'));
                    // 延迟添加show类,实现依次显示
                    setTimeout(() => {
                        p.classList.add('show');
                    }, 200 * order);
                });
                // 移除监听,避免重复触发
                observer.unobserve(entry.target);
            });
        }, { threshold: 0.1 });

        const hiddenSections = document.querySelectorAll('.section-hidden');
        hiddenSections.forEach(section => observer.observe(section));
    </script>
</body>
</html>

方案二:仅调整CSS避免动画叠加

如果不想修改JS逻辑,只需修改CSS让section和p的动画方向不同,避免叠加掩盖:

/* 修改section的.hidden类动画为Y轴位移,和p的X轴位移区分开 */
section.hidden {
    opacity: 0;
    filter: blur(5px);
    transform: translateY(20%);
    transition: all 1s;
}
section.show {
    opacity: 1;
    filter: blur(0);
    transform: translateY(0);
}
/* p的动画类保留不变 */
.hidden {
    opacity: 0;
    filter: blur(5px);
    transform: translateX(-100%);
    transition: all 1s;
}
.show {
    opacity: 1;
    filter: blur(0);
    transform: translateX(0);
}
section p {
    transition-delay: calc(200ms * var(--order));
}

这种方案下,section会从下方滑入,p从左侧滑入,两者动画互不干扰,p的延迟效果会正常显示。


内容的提问来源于stack exchange,提问作者auto-cast

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 00:40:59