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

如何解决React图片组件加载时的跳动问题?Tailwind CSS方案求助

解决图片骨架屏与图片位置偏移导致的跳动问题

我开发了一个图片加载组件,逻辑很简单:图片加载过程中显示骨架屏,加载完成后显示图片。目前功能正常,但存在一个问题:骨架屏渲染时位置偏下,图片加载完成后骨架屏消失,图片会向上跳动。想请教如何用Tailwind让图片精确渲染在骨架屏的位置(相同宽高与位置),消除跳动现象。

原组件代码

import { useEffect, useState } from "react";
import Footer from "~/components/footer/footer";
import Header from "~/components/header/header";

export default function ErrorBoundary() {
  const [loading, setLoading] = useState(true);
  const [randomNumber, setRandomNumber] = useState<number>();

  useEffect(() => {
    if (!randomNumber) {
      setRandomNumber(Math.floor((Math.random() * 100) + 1))
    }
  }, [randomNumber])

  return (
    <>
      <Header />
      <div className="flex flex-col items-center justify-between text-center h-80 w-80">
        <div className="">
          {
            randomNumber && <img className="h-40 w-40" src={`https://robohash.org/${randomNumber}?set=set4`} alt='catLoader' onLoad={() => {
              setLoading(false)
            }} />
          }
          {loading &&
            <div role="status" className="animate-pulse md:space-y-0 md:space-x-8 md:flex md:items-center">
              <div className="flex items-center justify-center w-40 h-40 bg-gray-300 rounded sm:w-96 dark:bg-gray-700">
                <svg className="w-40 h-40 text-gray-200 dark:text-gray-600" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 20 18">
                  <path d="M18 0H2a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2Zm-5.5 4a1.5 1.5 0 1 1 0 3 1.5 1.5 0 0 1 0-3Zm4.376 10.481A1 1 0 0 1 16 15H4a1 1 0 0 1-.895-1.447l3.5-7A1 1 0 0 1 7.468 6a.965.965 0 0 1 .9.5l2.775 4.757 1.546-1.887a1 1 0 0 1 1.618.1l2.541 4a1 1 0 0 1 .028 1.011Z" />
                </svg>
              </div>
              <span className="sr-only">Fetching a cat picture...</span>
            </div>
          }
        </div>
        <h1 className='text-7xl text-secondary-300 align-bottom'>Coming Soon!</h1>
      </div>
      <Footer />
    </>
  )
}

核心问题分析

跳动的本质是骨架屏与图片的布局上下文不一致:两者属于互斥的条件渲染DOM元素,且骨架屏外层带有md:flex、md:items-center等额外样式,导致容器的垂直位置、尺寸在切换时发生变化,触发浏览器重排重绘。

修复方案与修改后代码

import { useEffect, useState } from "react";
import Footer from "~/components/footer/footer";
import Header from "~/components/header/header";

export default function ErrorBoundary() {
  const [loading, setLoading] = useState(true);
  const [randomNumber, setRandomNumber] = useState<number>();

  useEffect(() => {
    if (!randomNumber) {
      setRandomNumber(Math.floor((Math.random() * 100) + 1))
    }
  }, [randomNumber])

  return (
    <>
      <Header />
      <div className="flex flex-col items-center justify-between text-center h-80 w-80">
        {/* 统一的父容器:固定宽高+相对定位,作为图片和骨架屏的基准 */}
        <div className="relative w-40 h-40">
          {/* 图片始终存在,通过hidden/block控制显示,避免DOM移除导致布局变化 */}
          {randomNumber && (
            <img 
              className={`w-full h-full object-contain ${loading ? 'hidden' : 'block'}`} 
              src={`https://robohash.org/${randomNumber}?set=set4`} 
              alt='catLoader' 
              onLoad={() => setLoading(false)} 
            />
          )}
          {/* 骨架屏绝对定位,完全覆盖父容器,和图片位置完全重合 */}
          {loading && (
            <div 
              role="status" 
              className="absolute inset-0 animate-pulse flex items-center justify-center bg-gray-300 rounded dark:bg-gray-700"
            >
              <svg className="w-40 h-40 text-gray-200 dark:text-gray-600" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 20 18">
                <path d="M18 0H2a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2Zm-5.5 4a1.5 1.5 0 1 1 0 3 1.5 1.5 0 0 1 0-3Zm4.376 10.481A1 1 0 0 1 16 15H4a1 1 0 0 1-.895-1.447l3.5-7A1 1 0 0 1 7.468 6a.965.965 0 0 1 .9.5l2.775 4.757 1.546-1.887a1 1 0 0 1 1.618.1l2.541 4a1 1 0 0 1 .028 1.011Z" />
              </svg>
              <span className="sr-only">Fetching a cat picture...</span>
            </div>
          )}
        </div>
        <h1 className='text-7xl text-secondary-300 align-bottom'>Coming Soon!</h1>
      </div>
      <Footer />
    </>
  )
}

关键修改点说明

  • 统一布局容器:给图片和骨架屏添加共同的父容器,设置relative w-40 h-40,确保两者使用完全相同的尺寸基准。
  • 绝对定位重叠:骨架屏用absolute inset-0实现完全覆盖父容器,与图片位置100%重合。
  • 避免DOM切换:图片通过hidden/block控制显示而非移除DOM,消除容器结构变化带来的布局波动。
  • 清理冗余样式:移除骨架屏原有的md:flex、md:space-x-8等干扰布局的样式,保持样式一致性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 08:17:55