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

React+TS+Tailwind动态网格列失效(Math.min相关问题)

解决React+Tailwind动态Grid列数偶尔失效的问题

问题背景

使用React+TypeScript+Tailwind CSS开发食谱网站,「我的食谱」页面通过Grid布局展示用户食谱,原本通过Math.min(列数上限, recipes.length)动态生成不同屏幕断点的列数,正常情况下功能正常,但重启应用后,无论屏幕宽度如何都只显示1列,移除Math.min后恢复正常,希望修复该问题而非绕过。

用户核心代码片段:

return (
  <div className="flex flex-col items-center">
    {!loading && (
      <>
        {recipes.length === 0 ? (
          <div>
            <h1 className="text-4xl">You have no recipes yet</h1>
            <Link to="/add-recipes" className="mt-6">
              Add a recipe
            </Link>
          </div>
        ) : (
          <>
            <h1 className="title">Your recipes</h1>
            <div
              className={`grid grid-cols-1 sm:grid-cols-${Math.min(2, recipes.length)} md:grid-cols-${Math.min(3, recipes.length)} gap-4 mt-6 p-4`}
            >
              {recipes.map((recipe, index) => (
                <RecipeCard recipe={recipe} key={index}/>
              ))}
            </div>
          </>
        )}
      </>
    )}
  </div>
);

问题根源

核心原因是Tailwind的JIT编译机制特性:Tailwind只会编译构建时能静态检测到的类名。当应用重启时,若初始recipes数组为空或长度为1,Math.min(2, recipes.length)会生成sm:grid-cols-1,此时Tailwind仅会编译该类名;后续数据加载完成后,即使recipes.length >=2,动态生成的sm:grid-cols-2类名并未被Tailwind提前编译,因此CSS中不存在该类,最终仍显示1列。

修复方案

方案1:添加安全列表强制编译所有可能的列数类(推荐)

在tailwind.config.js的safelist中声明所有可能用到的Grid列数类,确保Tailwind无论静态检测结果如何,都会编译这些类:

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: ["./src/**/*.{js,jsx,ts,tsx}"],
  safelist: [
    'grid-cols-1', 'grid-cols-2', 'grid-cols-3',
    'sm:grid-cols-1', 'sm:grid-cols-2', 'sm:grid-cols-3',
    'md:grid-cols-1', 'md:grid-cols-2', 'md:grid-cols-3'
  ],
  theme: { extend: {} },
  plugins: []
};

方案2:用条件渲染替代动态类名

将动态拼接类名改为基于recipes.length的静态条件判断,让Tailwind能扫描到所有可能的类名:

// 替换原Grid容器的className部分
<div className={`grid gap-4 mt-6 p-4 ${
  recipes.length === 1 
    ? 'grid-cols-1 sm:grid-cols-1 md:grid-cols-1'
    : recipes.length === 2
      ? 'grid-cols-1 sm:grid-cols-2 md:grid-cols-2'
      : 'grid-cols-1 sm:grid-cols-2 md:grid-cols-3'
}`}>
  {recipes.map((recipe, index) => (
    <RecipeCard recipe={recipe} key={index}/>
  ))}
</div>

方案3:使用Tailwind动态值语法(Tailwind v3+)

利用Tailwind支持的方括号动态值语法,强制JIT编译动态生成的列数类:

<div className={`grid grid-cols-[1] sm:grid-cols-[${Math.min(2, recipes.length)}] md:grid-cols-[${Math.min(3, recipes.length)}] gap-4 mt-6 p-4`}>
  {recipes.map((recipe, index) => (
    <RecipeCard recipe={recipe} key={index}/>
  ))}
</div>

注:该方案需确保动态值为有效整数,否则可能出现样式异常。

验证步骤

  1. 重启应用,确保初始recipes为空数组
  2. 加载数据后检查不同屏幕宽度下的列数:
    • sm及以上宽度,recipes.length >=2时显示2列
    • md及以上宽度,recipes.length >=3时显示3列
  3. 多次重启应用验证列数逻辑稳定生效

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 00:11:23