在 React/Gatsby 中,当我无法访问文档 object 时,如何使用 CSS 关键帧为粘性 header 设置动画?

In React/Gatsby how can I animate a sticky header using CSS keyframes when I don't have access to the document object?

我在 React/Gatsby 中制作了一个便签 header,它只有在您向下滚动一点后才会显示。它可以工作,但是 header 突然弹出,所以我试着让它动起来。问题是我正在尝试通过 insertRule 文档 属性 使用 CSS 关键帧,而像 Netlify 这样的托管平台无法访问 document object所以无论何时构建,我都会收到此错误:

error "document" is not available during server side rendering.

我研究过,但找不到任何合适的解决方案,jsdom 似乎无法解决它,我尝试使用样式化组件,但没有用。

这是关键帧 CSS 和使用 insertRule 插入样式:

let styleSheet = document.styleSheets[0];

const keyframesFixed = `
    @keyframes headerAnimationFixed{
        0%{
            opacity: 0.7;
            transform: translateY(-100%);
        }
        100%{
            opacity: 1;
            transform: translateY(0);
        }
    }
`;

styleSheet.insertRule(keyframesFixed, styleSheet.cssRules.length);

这是我使用动画的方式:

const fixedStyles = {
    position: 'fixed',
    zIndex: '200',
    top: '0',
    left: '0',
    animation: 'headerAnimationFixed 0.3s ease',
    transition: 'all ease 0.3s'
}

使用状态,我确定用户是否已向下滚动足够远,如果是,则应用 fixedStyles

有没有其他方法可以在 Header 组件中使用 keyframes 而无需使用 document object?

感谢您的宝贵时间!

正如您在 docs 中看到的(以及您所指出的),document 和其他全局对象(例如 window)在 SSR 中不可用。有多种解决方案可以绕过这个问题,但在您的情况下,最简单的就是检查 window 是否可用于触发动画。如果是这样,这将意味着您不在 SSR 中。这样的事情应该有效:

if (typeof window != "undefined"){
let styleSheet = document.styleSheets[0];

const keyframesFixed = `
    @keyframes headerAnimationFixed{
        0%{
            opacity: 0.7;
            transform: translateY(-100%);
        }
        100%{
            opacity: 1;
            transform: translateY(0);
        }
    }
`;

styleSheet.insertRule(keyframesFixed, styleSheet.cssRules.length);
}

或者,如果您的包装器不允许 if 语句 (JSX),您可以添加一个三元条件:

let styleSheet = typeof window != "undefined" ? document.styleSheets[0] : null;

const keyframesFixed = `
    @keyframes headerAnimationFixed{
        0%{
            opacity: 0.7;
            transform: translateY(-100%);
        }
        100%{
            opacity: 1;
            transform: translateY(0);
        }
    }
`;

typeof window != "undefined" ? styleSheet.insertRule(keyframesFixed, styleSheet.cssRules.length) : null;