如何使用TailwindCSS创建一个具有动态网格列数量的网格?

9
我正在使用Vue3和TailwindCSS,想创建一个带有动态grid-cols-{n}类的网格。我知道TailwindCSS默认支持最多12列,但我无法自定义主题,因为列数完全是动态的。
给出以下纯HTML/JS示例。

const amountOfItemsPerRow = 16;

const container = document.getElementById("container");

for (let i = 0; i < amountOfItemsPerRow; i++) {
  const item = document.createElement("div");
  item.innerText = i;
  container.appendChild(item);
}

container.classList.add(`grid-cols-${amountOfItemsPerRow}`); // this doesn't work if the value is greater than 12
<script src="https://cdn.tailwindcss.com"></script>

<div id="container" class="grid"></div>

如果amountOfItemsPerRow小于或等于12,这段代码可以正常工作,否则CSS将出现问题。

我需要编写代码来设置纯CSS以解决此问题,还是有动态的Tailwind解决方案?


另一种方法:

根据文档,我尝试替换以下行:

container.classList.add(`grid-cols-${amountOfItemsPerRow}`);

使用

container.classList.add(`grid-template-columns:repeat(${amountOfItemsPerRow},minmax(0,1fr))`);

我们曾尝试采用“本地化”方法,但并没有帮助到我们。


另一个解决方案是创建一个网格组件,并根据从API返回的数据列数量使用它。这样你就会得到多个12列的网格。 - undefined
3个回答

12

仅使用纯TailwindCSS无法做到这一点。

@Ajay Raja提出的建议行不通,因为它只能在即时编译(JIT)时运行。在编译应用程序之前,您可以使用任意值,但一旦编译并部署了您的捆绑包,就不能再动态设置。它只能在构建时起作用;因此,如果您正在使用CDN,则无法实现。

您可以查看类的实现,并设置一些JavaScript监听器来动态设置样式属性:

此处可以看到.grid-columns-12的实现。

.grid-columns-12 {
  grid-template-columns: repeat(12, minmax(0, 1fr));
}

因此,您可以通过JS执行以下操作:

function setDynamicColumns(cols) {
  document
    .querySelector('#elementWithDynamicGrid')
    .style['grid-template-columns'] = `repeat(${cols}, minmax(0, 1fr))`
}

我不是Vue专家,但您可以像在Angular或React上设置双向数据绑定一样进行设置。

您在这里所做的是什么

container.classList.add(`grid-template-columns:repeat(${amountOfItemsPerRow},minmax(0,1fr))`)

之前无法工作是因为您将 style 指令应用到了 class 属性中。


另一种解决这个问题的方法是在构建时生成所需数量的类,以便您可以在运行时安全地使用它们:

如果您查看此处的文档

您可以通过修改 tailwind.config.js 文件来添加自己的自定义网格修饰符。

module.exports = {  
  theme: {    
    extend: {      
      gridTemplateColumns: {        
      // Simple 16 column grid        
      '16': 'repeat(16, minmax(0, 1fr))',     
      }    
    }  
  }
}

因此,您可以添加一个生成合理数量列的函数,如下所示:

//tailwind.config.js
function generateGridColumns(lastValue) {
   let obj = {}
   for(let i = 13; i < lastValue; i++) {
     obj[`${i}`] = `repeat(${i}, minmax(0, 1fr))`
   }
   return obj
}


module.exports = {  
  theme: {    
    extend: {      
      gridTemplateColumns: {
         ...generateGridColumns(100) // This generates the columns from 12 until 100
      }    
    }  
  }
}

请记住,在清理你的 tailwindCSS 构建时,你需要指示保留所有 grid-columns-* 类,因为清理器无法猜测你将要使用它们。

有趣。我的方法 container.classList.add(grid-template-columns:repeat(${amountOfItemsPerRow},minmax(0,1fr))) 没有生效。但你的方法 container.style['grid-template-columns'] = repeat(${amountOfItemsPerRow},minmax(0,1fr))`` 生效了... 我用 https://jsfiddle.net/t94gfops/3/ 复现了它。 - user17298649
因为我们正在从HTML动态设置“style”属性。你走在了正确的道路上,但是设置了一个不存在的类。 - Some random IT boy
很遗憾,它与TailwindCSS不兼容,因为显然是通过postCSS集成的。由于我正在开发一个定制的日历(现有的日历不能满足我的需求),我有一定数量的网格列模板(2到8列),我可以将其添加为自定义模板,并确保在safelist中包括这些内容。谢谢! - Igor

0

React.js和Next.js的使用指南:

import { AllHTMLAttributes } from "react";
import classNames from "classnames";

// @interface IGrid extends all <div /> properties
interface IGrid extends AllHTMLAttributes<HTMLDivElement> {}

export default function Grid({
  className = "",
  cols = 8,
  rows = 4,
  ...rest
}: IGrid) {
  const props = { className: classNames(className, "grid"), ...rest };
  const gridTemplateColumns = `repeat(${cols}, 1fr)`;

  const gridItems = new Array(cols * rows)
    .fill("")
    .map((_, i) => <div key={`gridItem-${i}`}>{i}</div>);

  return (
    <div {...props} style={{ gridTemplateColumns }}>
      {gridItems}
    </div>
  );
}

✅ 在 tailwindcss@3.3.3 版本中进行了测试,无需额外配置。
⚠️ 虽然这不是最佳实践:

Microsoft Edge 工具:(无内联样式)


-1
使用Tailwindcss创建动态类名非常容易。 在[]之间,您可以添加带有TailwindCSS的动态类。
const amountOfRows = 16;
const amountOfCellsPerRow = 16;

const container = document.getElementById("container");

for (let rowIndex = 0; rowIndex < amountOfRows; rowIndex++) {
  for (let columnIndex = 0; columnIndex < amountOfCellsPerRow; columnIndex++) {
    const cell = document.createElement("div");
    cell.innerText = rowIndex + "|" + columnIndex;
    container.appendChild(cell);
  }
}

container.classList.add(`grid-cols-[${amountOfCellsPerRow}]`)

更多细节请点击这里


但是在将其包装在“[]”中之后,需要做什么?我认为所需的CSS应该是grid-template-columns: repeat(amountOfCellsPerRow, minmax(0, 1fr)); - user17298649
@medsmh我的工作正常吗? - Ajay Raja
抱歉,不行。我已经使用上面的CDN示例进行了测试。 - user17298649

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接