Creating a versatile TailwindCSS grid that can adjust to varying numbers of grid columns

I am currently working with Vue3 and TailwindCSS, attempting to create a grid using a dynamic grid-cols-{n} class. While I am aware that TailwindCSS typically supports up to 12 columns by default, the challenge arises when the number of columns needed is entirely dynamic and cannot be customized within the theme.

For example, consider the following simple HTML / JS snippet:

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>

In this scenario, the code functions correctly if the value of amountOfItemsPerRow is less than or equal to 12, but breaks the CSS style when exceeding 12 columns.

Is there a way to address this issue without resorting to writing custom CSS styles, perhaps through a dynamic solution within Tailwind?


An Alternative Approach:

Following guidance from the TailwindCSS documentation, I attempted to modify the line

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

to

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

In an effort to develop a more "native" solution, however, this adjustment did not yield the desired outcome.

Answer №1

Unfortunately, plain TailwindCSS does not support dynamic grid template columns.

Even though @Ajay Raja's suggestion is for JIT (just-in-time) compilation, it won't work for dynamic changes after deployment. The only option is to set up Javascript listeners to dynamically modify the style attribute based on the implementation of the desired class.

To achieve this, you can refer to the implementation of the .grid-columns-12 class from the documentation.

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

For a Vue application, consider implementing two-way data binding like in Angular or React instead of directly applying style directives to class attributes as previously attempted.


An alternative solution is to pre-generate a range of custom grid classes in the tailwind.config.js file during build time, allowing safe usage at runtime:

You can create your own custom grid modifiers following the guidelines in the documentation.

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

Add a function in the config file that generates a series of grid columns and remember to specify to preserve all grid-columns-* classes during purging to avoid unintentional removal.

Answer №2

In my expertise with React.js & Next.js:

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

// Defining interface IGrid to include all properties of <div />
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:

<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="2753464e4b504e4943445454671409140914">[email protected]</a>
without any further setup needed.

⚠️ Although not considered the best practice:

Microsoft Edge Tools: (no-inline-styles)

Answer №3

Generating Dynamic Class Names with Tailwindcss is a breeze. You have the flexibility to include dynamic classes within square brackets using 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 a more in-depth explanation, visit this link.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the best way to create underlined text that is either left-aligned or centered?

I am looking to replicate this specific style of decoration in a full width container. My goal is to have it aligned to the left of the text and restricted to a maximum width. https://i.stack.imgur.com/H8DXT.png ...

Comparing parameters between two functions in Javascript: a step-by-step guide

I am currently working on solving this problem: var name; var totalScore; var gamesPlayed; var player; var score; // Creating the game player object function makeGamePlayer(name, totalScore, ga ...

When using Material UI, it is not possible to apply the text-overflow: ellipsis and overflow: hidden properties to multiple

I am new to material UI and here is the current state of my website: view reality of current website This is what I am expecting it to be: what I envision it becoming From the images above, you can see that I want the text inside the circle to be shorten ...

Experiencing an excessive number of re-renders can be a common issue in React as it has limitations set in place to prevent infinite loops. This

I have integrated React context to access the login function and error from the context provider file for logging into the firebase database. I am trying to display any thrown errors in the app during the login process. However, I encountered an issue whe ...

Ways to discreetly conceal forward and backward buttons in the v-pagination component of Vuetify

Is there a way to remove the previous and next buttons from v-pagination in Vuetify? Here's my code snippet- <v-pagination v-model="page" :length="pageCount" :total-visible="8" color="primary" /> ...

What is the best way to extract all of the JSON data from Firebase using a web platform?

As a newcomer to Firebase and noSQL databases, I'm encountering difficulties in extracting all the JSON data from the database. Although I've gone through the firecast tutorials and understand how to retrieve specific values by referencing the da ...

React state not being updated by setState method

Here's the situation: let total = newDealersDeckTotal.reduce(function(a, b) { return a + b; }, 0); console.log(total, 'tittal'); //displays correct total setTimeout(() => { this.setState({ dealersOverallTotal: total }); }, 10); cons ...

The dropdown menu in AngularJS is unable to retrieve the selected index

Presently, I have a dropdown menu: <select class="form-control" name="timeSlot" ng-model="user.dateTimeSlot" ng-change="dateTimeChanged(user.dateTimeSlot)" ng-blur="blur29=true" required style="float: none; margin: 0 auto;"> ...

Error encountered: jQuery AJAX JSON request failed to be caught

While my WordPress AJAX process is successful, a peculiar error keeps popping up in Chrome Devtools: Uncaught TypeError: Cannot read property 'vehicle' of undefined. It's puzzling, as the parsed JSON data seems to be in the correct object fo ...

Navigating back to the beginning of the webpage following the completion of a form submission utilizing Master Pages and Ajax

I am having an issue with my ASP.NET 4.0 page where I want to reset it to the top after a form submission so that the validation summary can be displayed properly. The setup involves using Ajax and a master page with the following simplified code: <f ...

unable to see the new component in the display

Within my app component class, I am attempting to integrate a new component. I have added the selector of this new component to the main class template. `import {CountryCapitalComponent} from "./app.country"; @Component({ selector: 'app-roo ...

Radio buttons have been concealed and are not visible

Tried the solutions recommended in a previous question about radio buttons not showing in Safari and Chrome, but unfortunately, it did not solve my problem. It seems like this issue is different from the one discussed in that question. The WordPress them ...

How can I retrieve the value of a div nested within another div?

Alright, let's talk about a situation where we have a draggable HTML div element: <div id="server" draggable="true" ondragstart="return dragStart(event)">Server</div> and also a target div: <div id="target1" ondragenter="return dragE ...

Encountered a parsing error when attempting to integrate SCSS with webpack and babel setup

I am facing an issue while trying to integrate SCSS into my webpack and babel setup. When running npm run build, I encounter an error that I'm unfamiliar with. As a beginner in using webpack and babel, I'm unsure about the necessary changes requ ...

How can I pass the dynamically generated ID from PHP to AJAX/jQuery using an anchor tag?

I'm seeking help with jQuery and Ajax as I am new to it. My issue is that I have multiple 'edit' buttons in a table, one for each row's data. When I click on an edit button to modify the data, they all open at once instead of just the s ...

What is the best way to define the width of text inside a div block?

I'm having trouble adjusting the width of the text in my code to only fill 80% of the body element. I've tried using both the width property and padding, but neither seems to be working for me at the moment. Here's the HTML: <body&g ...

Preserve the content in the text box corresponding to the selected radio button

In my form, there are multiple radio buttons, each with an associated text box value. Users can only select one radio button at a time and submit the form. However, sometimes users will enter data in a textbox for one radio button, then switch to another o ...

WordPress CSS Styling Issue: HTML Element Display Problem

I recently converted my static HTML site to WordPress, but I'm facing an issue where the site is always aligned to the left. Despite trying different solutions like the one below: body{ margin: auto; } The original HTML page was centered perfectly ...

What is the method for utilizing HSL instead of RGB in the global declaration of SCSS using the JavaScript API

This is how my next.config.js file is structured: // next.config.js const env = require('./site.config').env; const Colour = require('sass').types.Color; const {r, g, b} = require('./site.config').customProperties; const wit ...

Dynamically include new events

Here is the code snippet I have in a JS file: $(".dropmenu").on("click", function(event){ event.preventDefault(); $(this).parent().find("ul").slideToggle(); }); On my webpage, I'm using the following code: var append="<ul> ...