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

如何解决Next.js 14中Material Symbols图标闪烁问题?

Next.js 14中Material Symbols SSR加载闪烁/延迟显示的解决方法

针对你在Next.js 14.0.4里用globals.css导入Material Symbols时,SSR阶段图标看不见、加载完成后才显示的问题,给你几个实用解决方案:

1. 固定图标容器尺寸,彻底避免布局闪烁

图标加载前没有占位尺寸是导致布局跳动的核心原因,直接给图标元素设置固定宽高即可:

/* 在globals.css中添加 */
.material-symbols-outlined {
  width: 24px; /* 匹配你设置的图标font-size */
  height: 24px;
  display: inline-block;
  vertical-align: middle;
}

这样不管图标是否加载完成,容器都有固定占位,不会出现页面元素跳动的情况。

2. 配置字体预加载+强制渲染,实现SSR即时显示

修改globals.css中的字体导入规则,添加font-display: block并明确字体源,让浏览器在渲染页面时直接等待字体加载完成,避免先显示空白:

@font-face {
  font-family: 'Material Symbols Outlined';
  font-style: normal;
  font-weight: 400;
  /* 替换为你使用的Material Symbols字体源 */
  src: url(https://fonts.gstatic.com/s/materialsymbolsoutlined/v147/kJF1BvYX7BgnkSrUwT8OhrdQw4oELdPIeeII9v6oDMzByHX9rA6RzaxHMPdY43zj-jCxv3fzvRNU22ZXGJpEpjC_1n-q_4MrImHCIJIZrDCvHOej.woff2) format('woff2');
  font-display: block; /* 关键:阻止字体交换,确保SSR时直接渲染图标 */
}

如果担心字体加载慢导致长时间空白,可以结合上面的固定尺寸方案,这样至少有占位,用户感知会好很多。

3. 骨架屏方案:精准判断图标加载完成

如果要做按钮骨架屏,可以借助字体加载检测工具来切换状态:

步骤1:安装字体检测依赖

npm install fontfaceobserver

步骤2:封装字体加载检测函数

// utils/fontLoader.js
import FontFaceObserver from 'fontfaceobserver';

export default function waitForFontLoad(fontFamily) {
  return new Promise(resolve => {
    const fontObserver = new FontFaceObserver(fontFamily);
    // 加载成功或失败都resolve,避免骨架屏一直显示
    fontObserver.load().then(resolve).catch(resolve);
  });
}

步骤3:在组件中使用骨架屏

// components/IconButton.jsx
'use client';
import { useEffect, useState } from 'react';
import waitForFontLoad from '@/utils/fontLoader';

export default function IconButton() {
  const [isFontLoaded, setIsFontLoaded] = useState(false);

  useEffect(() => {
    waitForFontLoad('Material Symbols Outlined').then(() => {
      setIsFontLoaded(true);
    });
  }, []);

  return (
    <button className="px-3 py-2 flex items-center gap-2">
      {!isFontLoaded ? (
        <div className="icon-skeleton"></div>
      ) : (
        <span className="material-symbols-outlined">home</span>
      )}
      <span>首页</span>
    </button>
  );
}

步骤4:添加骨架屏样式

/* globals.css */
.icon-skeleton {
  width: 24px;
  height: 24px;
  border-radius: 4px;
  background-color: #e5e7eb;
  animation: pulse 1.5s ease-in-out infinite;
}

@keyframes pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.6; }
}

4. 备选方案:改用SVG图标组件

如果不想折腾字体加载问题,直接用SVG格式的Material Symbols图标是最彻底的解决办法——SSR时会直接渲染SVG代码,完全没有加载延迟:

// components/HomeIcon.jsx
export default function HomeIcon() {
  return (
    <svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24" fill="#333">
      <path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"/>
    </svg>
  );
}

你可以从Material Icons官网直接下载需要的SVG,或者使用@mui/icons-material这类封装好的组件库。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 06:50:17