最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to create a TailwindCSS grid with a dynamic amount of grid columns? - Stack Overflow

programmeradmin1浏览0评论

I'm using Vue3 with TailwindCSS and want to create a grid with a dynamic grid-cols-{n} class. I know that TailwindCSS supports up to 12 columns by default but I can't customize the theme because the amount of columns is completely dynamic.

Given the following plain HTML / Js example

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=""></script>

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

I'm using Vue3 with TailwindCSS and want to create a grid with a dynamic grid-cols-{n} class. I know that TailwindCSS supports up to 12 columns by default but I can't customize the theme because the amount of columns is completely dynamic.

Given the following plain HTML / Js example

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>

This code works fine if amountOfItemsPerRow is smaller or equal than 12, otherwise the CSS is broken.

Do I have to write code to setup plain CSS solving this or is there a dynamic Tailwind solution?


Another approach:

Based on the docs I tried to replace the line

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

with

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

to come up with a "native" approach but that didn't help.

Share Improve this question edited Feb 10, 2022 at 14:10 asked Feb 8, 2022 at 13:48 user17298649user17298649 1
  • Another solution would be to create a grid component and use that based on the amount of data columns returned from API, etc. You would end up with multiple 12 column grids. – CloudBranch Commented Oct 5, 2023 at 0:09
Add a comment  | 

3 Answers 3

Reset to default 13 +100

You cannot do that with plain TailwindCSS.

What @Ajay Raja suggests won't work because it only works with JIT (just-in-time); so previously to compiling the application you can use arbitrary values but once you've compiled and deployed your bundle that cannot be dynamic. It only works during build-time; so if you're using a CDN you'll not make it

What you can do is taking a look at the implementation of the class and set up some javascript listeners to dynamically set the style attribute:

From here you can see the implementation of .grid-columns-12.

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

So from JS you can do something as follows:

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

I am not a Vue expert, but you could set two-way databinding like you would on Angular or React.

What you were doing here

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

Was not working because you were applying a style directive into the class attribute


Another approach to tackle this problem would be to generate the necessary amount of classes at build time so then you can use them safely at runtime:

If you take a look at the docs here

You can add your own custom grid modifiers by modifying the tailwind.config.js file.

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

So you can add a function that generates a reasonable number of columns there as follows:

//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
      }    
    }  
  }
}

Please bear in mind that when purging your tailwindCSS builds you need to indicate to keep all grid-columns-* classes since the purger cannot guess that you're going to use them

Here for 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>
  );
}

✅ Tested in: [email protected] without additional configuration.

⚠️ It isn't a best practice though:

Microsoft Edge Tools: (no-inline-styles)

Create Dynamic Class Name with Tailwindcss is easy. Inside [ and ], You can add Dynamic Class with 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}]`)

For more details here

发布评论

评论列表(0)

  1. 暂无评论