Tailwind CSS Grid Template Columns
Grid Template Columns define the column structure within grid containers. Tailwind CSS simplifies this further with an array of utilities to control grid layout properties. These utilities integrate directly into your markup, enabling rapid prototyping and customization.
In this guide, we will explore how to use Grid Template Columns utilities in Tailwind CSS, covering everything from fundamental concepts to advanced customization techniques.
Class | Properties | Example |
---|---|---|
grid-cols-1 | grid-template-columns: repeat(1, minmax(0, 1fr)); | <div className="grid-cols-1"></div> |
grid-cols-2 | grid-template-columns: repeat(2, minmax(0, 1fr)); | <div className="grid-cols-2"></div> |
grid-cols-3 | grid-template-columns: repeat(3, minmax(0, 1fr)); | <div className="grid-cols-3"></div> |
grid-cols-4 | grid-template-columns: repeat(4, minmax(0, 1fr)); | <div className="grid-cols-4"></div> |
grid-cols-5 | grid-template-columns: repeat(5, minmax(0, 1fr)); | <div className="grid-cols-5"></div> |
grid-cols-6 | grid-template-columns: repeat(6, minmax(0, 1fr)); | <div className="grid-cols-6"></div> |
grid-cols-7 | grid-template-columns: repeat(7, minmax(0, 1fr)); | <div className="grid-cols-7"></div> |
grid-cols-8 | grid-template-columns: repeat(8, minmax(0, 1fr)); | <div className="grid-cols-8"></div> |
grid-cols-9 | grid-template-columns: repeat(9, minmax(0, 1fr)); | <div className="grid-cols-9"></div> |
grid-cols-10 | grid-template-columns: repeat(10, minmax(0, 1fr)); | <div className="grid-cols-10"></div> |
grid-cols-11 | grid-template-columns: repeat(11, minmax(0, 1fr)); | <div className="grid-cols-11"></div> |
grid-cols-12 | grid-template-columns: repeat(12, minmax(0, 1fr)); | <div className="grid-cols-12"></div> |
grid-cols-none | grid-template-columns: none; | <div className="grid-cols-none"></div> |
grid-cols-subgrid | grid-template-columns: subgrid; | <div className="grid-cols-subgrid"></div> |
Overview of Grid Template Columns
Adding the Grid Template Columns
To define the number of columns in grid, use Tailwind's grid-cols-*
utilities like- grid-cols-2
, grid-cols-3
, grid-cols-4
, etc.
export default function App() { return ( <div className="grid grid-cols-3 gap-4 h-screen w-screen bg-gray-100 p-8"> <div className="bg-blue-500 text-white p-4">Column 1</div> <div className="bg-green-500 text-white p-4">Column 2</div> <div className="bg-yellow-500 text-white p-4">Column 3</div> </div> ); }
Subgrid Support
To define sub-grids within parent grid items, use grid-cols-subgrid
.
export default function SubgridDemo() { return ( <div className="grid grid-cols-3 gap-6 h-screen w-screen p-8 bg-gray-50"> <div className="bg-orange-400" /> <div className="bg-red-400" /> <div class="grid grid-cols-subgrid gap-4 col-span-3 bg-zinc-300 border-2 border-black border-dashed"> <div className="bg-indigo-400" /> <div className="bg-indigo-400" /> <div className="bg-indigo-400" /> </div> <div className="bg-yellow-400" /> <div className="bg-pink-400" /> <div className="bg-blue-400" /> </div> ); }
States and Responsiveness
Tailwind provides modifiers to let you define grid columns based on states and resolutions. This ensures you can adapt your design based on user interactions (hover
, focus
) or various screen sizes.
Hover and Focus States
To define grid columns on states like hover and focus, use hover
and focus
modifiers, e.g., hover:grid-cols-3
, focus:grid-cols-4
, etc.
export default function HoverGrid() { return ( <div className="h-screen w-screen flex justify-center items-center flex-col text-center px-12 gap-6"> <p className="underline">Hover on the below container to change the grid columns</p> <div className="grid grid-cols-3 hover:grid-cols-6 bg-gray-100 h-72 w-72"> <div className="bg-purple-400" /> <div className="bg-fuchsia-400" /> <div className="bg-indigo-400" /> </div> </div> ); }
Breakpoint Modifiers
To define grid columns based on the device breakpoint, use the breakpoint modifiers(sm
, md
, etc.), e.g., md:grid-cols-6
.
export default function ResponsiveGrid() { return ( <div className="h-screen w-screen flex justify-center items-center flex-col text-center px-6 pt-6 gap-4"> <p className="underline">The below container will have different number of columns based on the breakpoint</p> <div className="grid grid-cols-1 md:grid-cols-3 lg:grid-cols-6 gap-4 h-screen w-screen p-8"> <div className="bg-indigo-500" /> <div className="bg-indigo-500" /> <div className="bg-indigo-500" /> </div> </div> ); }
Custom Grid Template Columns
Tailwind lets you extend its default utilities through its config file and arbitrary values.
Extending the Theme
You can extend Tailwind's grid column utilities in your tailwind.config.js
file. Define custom increments or specific fractions to match your design requirements:
With extended configurations, you can use these utilities directly in your markup:
import tailwindConfig from "./tailwind.config.js"; tailwind.config = tailwindConfig; export default function ExtendedGrid() { return ( <div className="grid grid-cols-custom gap-6 h-screen w-screen bg-gray-200 p-8"> <div className="bg-orange-400 text-white p-4">Custom Column</div> <div className="bg-red-400 text-white p-4">Custom Width</div> </div> ); }
Using Arbitrary Values
For one-off values, where it doesn't make much sense to modify the theme, Tailwind supports arbitrary values directly in your markup.
export default function ArbitraryGrid() { return ( <div className="grid grid-cols-[80px_minmax(120px,_2fr)_20px] gap-4 h-screen w-screen bg-teal-100 p-8"> <div className="bg-red-400" /> <div className="bg-orange-400" /> <div className="bg-indigo-400" /> <div className="bg-yellow-400" /> <div className="bg-blue-400" /> <div className="bg-green-400" /> </div> ); }
Real World Examples
Product Showcase Grid
This example demonstrates a responsive product grid layout for an e-commerce website that adjusts columns based on screen size.
export default function ProductShowcase() { const products = [ { id: 1, name: "Premium Leather Watch", price: "$299.99", src: "https://images.unsplash.com/photo-1524592094714-0f0654e20314", alt: "Premium leather watch with gold accents" }, { id: 2, name: "Wireless Earbuds", price: "$159.99", src: "https://images.unsplash.com/photo-1572569511254-d8f925fe2cbb", alt: "White wireless earbuds in charging case" }, { id: 3, name: "Laptop Stand", price: "$49.99", src: "https://images.unsplash.com/photo-1527864550417-7fd91fc51a46", alt: "Aluminum laptop stand" }, { id: 4, name: "Mechanical Keyboard", price: "$129.99", src: "https://images.unsplash.com/photo-1595225476474-87563907a212", alt: "RGB mechanical keyboard" } ]; return ( <div className="container mx-auto px-4 py-4"> <div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6"> {products.map((product) => ( <div key={product.id} className="bg-white rounded-lg shadow-md overflow-hidden"> <img src={product.src} alt={product.alt} className="w-full h-48 object-cover" /> <div className="p-4"> <h3 className="text-lg font-semibold">{product.name}</h3> <p className="text-gray-600">{product.price}</p> </div> </div> ))} </div> </div> ); }
Team Member Directory
A responsive grid layout for displaying team members with their information.
export default function TeamDirectory() { const teamMembers = [ { id: 1, name: "Sarah Johnson", role: "CEO", src: "https://images.unsplash.com/photo-1494790108377-be9c29b29330", alt: "Sarah Johnson headshot", email: "sarah@company.com" }, { id: 2, name: "Michael Chen", role: "CTO", src: "https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d", alt: "Michael Chen headshot", email: "michael@company.com" }, { id: 3, name: "Emily Rodriguez", role: "Design Director", src: "https://images.unsplash.com/photo-1438761681033-6461ffad8d80", alt: "Emily Rodriguez headshot", email: "emily@company.com" }, { id: 4, name: "David Kim", role: "Lead Developer", src: "https://images.unsplash.com/photo-1500648767791-00dcc994a43e", alt: "David Kim headshot", email: "david@company.com" }, { id: 5, name: "Lisa Patel", role: "Product Manager", src: "https://images.unsplash.com/photo-1534528741775-53994a69daeb", alt: "Lisa Patel headshot", email: "lisa@company.com" }, { id: 6, name: "James Wilson", role: "Marketing Director", src: "https://images.unsplash.com/photo-1506794778202-cad84cf45f1d", alt: "James Wilson headshot", email: "james@company.com" } ]; return ( <div className="bg-gray-100 min-h-screen py-12"> <div className="container mx-auto px-4"> <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8"> {teamMembers.map((member) => ( <div key={member.id} className="bg-white rounded-xl p-6 shadow-lg"> <div className="flex items-center space-x-4"> <img src={member.src} alt={member.alt} className="w-20 h-20 rounded-full object-cover" /> <div> <h3 className="text-xl font-bold">{member.name}</h3> <p className="text-blue-600">{member.role}</p> <p className="text-gray-500 text-sm">{member.email}</p> </div> </div> </div> ))} </div> </div> </div> ); }
Dashboard Statistics Grid
A dashboard statistics grid that displays key metrics in cards.
const DashboardStats = () => { const stats = [ { id: 1, title: "Total Revenue", value: "$124,592", change: "+12.5%", icon: "https://images.unsplash.com/photo-1687914141292-906c2b2f5911", alt: "Revenue icon" }, { id: 2, title: "Active Users", value: "8,492", change: "+5.2%", icon: "https://images.unsplash.com/photo-1633332755192-727a05c4013d", alt: "Users icon" }, { id: 3, title: "Conversion Rate", value: "2.4%", change: "+0.8%", icon: "https://images.unsplash.com/photo-1551288049-bebda4e38f71", alt: "Conversion icon" }, { id: 4, title: "Avg. Order Value", value: "$245", change: "+3.1%", icon: "https://images.unsplash.com/photo-1553729459-efe14ef6055d", alt: "Order icon" }, { id: 5, title: "Products Sold", value: "12,389", change: "+15.3%", icon: "https://images.unsplash.com/photo-1624137527136-66e631bdaa0e", alt: "Products icon" }, { id: 6, title: "Customer Satisfaction", value: "4.8/5", change: "+0.2", icon: "https://images.unsplash.com/photo-1549465220-1a8b9238cd48", alt: "Satisfaction icon" } ]; return ( <div className="p-4"> <div className="grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 gap-4"> {stats.map((stat) => ( <div key={stat.id} className="bg-white rounded-lg p-6 shadow-sm"> <div className="flex items-center space-x-4"> <img src={stat.icon} alt={stat.alt} className="w-12 h-12 rounded-full" /> <div> <p className="text-sm text-gray-500">{stat.title}</p> <p className="text-2xl font-bold">{stat.value}</p> <span className="text-green-500 text-sm">{stat.change}</span> </div> </div> </div> ))} </div> </div> ); }; export default DashboardStats;
Blog Post Grid
A modern blog post grid with featured images and post metadata. Uses different column spans for featured posts.
const BlogGrid = () => { const posts = [ { id: 1, title: "The Future of Web Development", excerpt: "Exploring upcoming trends in web development and what they mean for developers.", author: "Sarah Johnson", date: "Mar 15, 2024", category: "Technology", featured: false, src: "https://images.unsplash.com/photo-1498050108023-c5249f4df085", alt: "Coding on laptop" }, { id: 2, title: "Design Systems in 2024", excerpt: "How design systems are evolving and shaping modern UI development.", author: "Mike Chen", date: "Mar 12, 2024", category: "Design", featured: false, src: "https://images.unsplash.com/photo-1561070791-2526d30994b5", alt: "Design system sketch" }, { id: 3, title: "Mastering CSS Grid", excerpt: "A comprehensive guide to building layouts with CSS Grid.", author: "Emma Wilson", date: "Mar 10, 2024", category: "CSS", featured: true, src: "https://images.unsplash.com/photo-1507721999472-8ed4421c4af2", alt: "CSS code screenshot" }, { id: 4, title: "JavaScript Performance Tips", excerpt: "Optimize your JavaScript code for better performance.", author: "Alex Brown", date: "Mar 8, 2024", category: "JavaScript", featured: false, src: "https://images.unsplash.com/photo-1579468118864-1b9ea3c0db4a", alt: "JavaScript code" }, { id: 5, title: "Responsive Design Best Practices", excerpt: "Creating websites that work seamlessly across all devices.", author: "Lisa Park", date: "Mar 5, 2024", category: "Design", featured: false, src: "https://images.unsplash.com/photo-1554200876-56c2f25224fa", alt: "Responsive design" }, { id: 6, title: "The Rise of AI in Web Development", excerpt: "How artificial intelligence is changing the way we build websites.", author: "David Kim", date: "Mar 3, 2024", category: "AI", featured: true, src: "https://images.unsplash.com/photo-1677442136019-21780ecad995", alt: "AI concept" } ]; return ( <div className="p-4"> <div className="grid grid-cols-2 lg:grid-cols-3 gap-6"> {posts.map((post) => ( <div key={post.id} className={`bg-white rounded-lg overflow-hidden shadow-md ${ post.featured ? 'col-span-2' : '' }`} > <img src={post.src} alt={post.alt} className="w-full h-48 object-cover" /> <div className="p-6"> <span className="text-sm text-blue-600">{post.category}</span> <h3 className="text-xl font-semibold mt-2">{post.title}</h3> <p className="text-gray-600 mt-2">{post.excerpt}</p> <div className="mt-4 flex items-center justify-between"> <span className="text-sm text-gray-500">{post.author}</span> <span className="text-sm text-gray-500">{post.date}</span> </div> </div> </div> ))} </div> </div> ); }; export default BlogGrid;
Gallery Grid
A masonry-style image gallery grid with hover effects. Uses auto-fill and spans different columns based on image orientation.
const GalleryGrid = () => { const images = [ { id: 1, title: "Mountain Landscape", category: "Nature", span: "col-span-2", src: "https://images.unsplash.com/photo-1506905925346-21bda4d32df4", alt: "Mountain peaks at sunset" }, { id: 2, title: "Urban Architecture", category: "City", span: "col-span-1", src: "https://images.unsplash.com/photo-1486406146926-c627a92ad1ab", alt: "Modern building facade" }, { id: 3, title: "Ocean Waves", category: "Nature", span: "col-span-1", src: "https://images.unsplash.com/photo-1505118380757-91f5f5632de0", alt: "Crashing ocean waves" }, { id: 4, title: "Street Photography", category: "Urban", span: "col-span-2", src: "https://images.unsplash.com/photo-1523990853274-86278eb4e38c", alt: "Busy city street" }, { id: 5, title: "Forest Path", category: "Nature", span: "col-span-1", src: "https://images.unsplash.com/photo-1441974231531-c6227db76b6e", alt: "Path through dense forest" }, { id: 6, title: "Desert Sunset", category: "Nature", span: "col-span-1", src: "https://images.unsplash.com/photo-1682685796965-9814afcbff55", alt: "Sunset over sand dunes" } ]; return ( <div className="p-4"> <div className="grid grid-cols-2 sm:grid-cols-2 lg:grid-cols-4 gap-4"> {images.map((image) => ( <div key={image.id} className={`relative overflow-hidden rounded-lg ${image.span} group`} > <img src={image.src} alt={image.alt} className="w-full h-64 object-cover transition-transform duration-300 group-hover:scale-110" /> <div className="absolute inset-0 bg-black bg-opacity-40 opacity-0 group-hover:opacity-100 transition-opacity duration-300"> <div className="absolute bottom-0 left-0 right-0 p-4 text-white"> <h3 className="text-lg font-semibold">{image.title}</h3> <p className="text-sm">{image.category}</p> </div> </div> </div> ))} </div> </div> ); }; export default GalleryGrid;
Customization Examples
Product Showcase Layout
This example demonstrates a responsive product grid with custom column sizes optimized for an e-commerce product listing page.
import tailwindConfig from "./tailwind.config.js"; tailwind.config = tailwindConfig; // App.js export default function ProductGrid() { const products = [ { id: 1, name: "Premium Headphones", price: "$299", image: "https://images.unsplash.com/photo-1505740420928-5e560c06d30e" }, { id: 2, name: "Wireless Speaker", price: "$199", image: "https://images.unsplash.com/photo-1608043152269-423dbba4e7e1" }, { id: 3, name: "Smart Watch", price: "$399", image: "https://images.unsplash.com/photo-1546868871-7041f2a55e12" } ]; return ( <div className="container mx-auto p-8"> <div className="grid grid-cols-product gap-8"> {products.map(product => ( <div key={product.id} className="bg-white rounded-lg shadow-lg overflow-hidden"> <img src={product.image} alt={product.name} className="w-full h-64 object-cover" /> <div className="p-6"> <h3 className="text-xl font-semibold">{product.name}</h3> <p className="text-gray-600 mt-2">{product.price}</p> </div> </div> ))} </div> </div> ); }
Dashboard Analytics Layout
This example shows a custom dashboard layout with varying column widths for different widgets.
import tailwindConfig from "./tailwind.config.js"; tailwind.config = tailwindConfig; // App.js export default function DashboardLayout() { return ( <div className="min-h-screen p-8"> <div className="grid grid-cols-dashboard gap-6"> <div className="bg-white rounded-xl p-6 shadow-md"> <h2 className="text-2xl font-bold mb-4">Analytics Overview</h2> <div className="grid grid-cols-widgets gap-4"> <div className="bg-blue-50 p-4 rounded-lg"> <h3 className="text-lg font-semibold">Total Sales</h3> <p className="text-3xl font-bold text-blue-600">$45,678</p> </div> <div className="bg-green-50 p-4 rounded-lg"> <h3 className="text-lg font-semibold">Visitors</h3> <p className="text-3xl font-bold text-green-600">12,345</p> </div> <div className="bg-purple-50 p-4 rounded-lg"> <h3 className="text-lg font-semibold">Conversions</h3> <p className="text-3xl font-bold text-purple-600">8.5%</p> </div> </div> </div> <div className="bg-white rounded-xl p-6 shadow-md"> <h2 className="text-2xl font-bold mb-4">Recent Activity</h2> <div className="space-y-4"> {/* Activity items */} </div> </div> </div> </div> ); }
Photo Gallery Layout
This example creates a masonry-style photo gallery with custom column configurations.
import tailwindConfig from "./tailwind.config.js"; tailwind.config = tailwindConfig; // NewsGrid.js import React from 'react'; const NewsGrid = () => { const articles = [ { id: 1, title: 'Featured Story', excerpt: 'Breaking news...', image: 'https://images.unsplash.com/photo-1557992260-ec58e38d363c', span: 8 }, { id: 2, title: 'Tech Updates', excerpt: 'Latest in tech...', image: 'https://images.unsplash.com/photo-1519389950473-47ba0277781c', span: 4 }, { id: 3, title: 'Science News', excerpt: 'New discoveries...', image: 'https://images.unsplash.com/photo-1507413245164-6160d8298b31', span: 6 }, { id: 4, title: 'Sports', excerpt: 'Match results...', image: 'https://images.unsplash.com/photo-1461896836934-ffe607ba8211', span: 6 }, ]; return ( <div className="grid grid-cols-news gap-4 p-4"> {articles.map(article => ( <div key={article.id} className={`col-span-${article.span} relative overflow-hidden rounded-lg`} > <img src={`${article.image}?auto=format&fit=crop&w=350`} alt={article.title} className="w-full h-48 object-cover" /> <div className="absolute bottom-0 left-0 right-0 bg-gradient-to-t from-black to-transparent p-4"> <h3 className="text-white font-bold">{article.title}</h3> <p className="text-gray-200 text-sm">{article.excerpt}</p> </div> </div> ))} </div> ); }; export default NewsGrid;
Best Practices
Optimize for Reusability
To promote reusability, consider using component-based frameworks such as React or Vue in conjunction with Tailwind. Structuring components with props that determine column counts, spacing, and alignment enhances flexibility. A reusable component can be designed to accept className props
, allowing variations in the grid structure without modifying the core component logic.
Additionally, to standardize grid layouts across projects, create custom utility classes in Tailwind's config file. This practice ensures that teams follow a common structure while allowing for easy updates to the grid system when necessary. Maintaining reusable components reduces redundancy and promotes efficient design iterations.
Build Responsive Design
Ensuring that grid layouts are flexible across different screen sizes is key for responsive design. Tailwind CSS makes this simple with its responsive variants like sm:grid-cols-*
, lg:grid-cols-*
, etc., which let you set different column counts based on the viewport width.
A mobile-first strategy is recommended, where you start with a single-column layout and gradually add more columns as the screen expands. For example, using sm:grid-cols-2 lg:grid-cols-4
allows your design to smoothly transition from small screens to larger ones without compromising usability.
For more advanced layouts, you can incorporate CSS functions like minmax()
with Tailwind’s grid utilities in custom styles. This approach keeps columns flexible and prevents the layout from breaking, especially when combined with auto-fit
or auto-fill
, ensuring that grid items adjust evenly to the available space.
Accessibility Considerations
Enhance Readability and Navigability
Using grid-cols-*
correctly contributes to improved readability and navigation. When defining a grid layout, ensure that content flows in a logical order, particularly for users who rely on assistive technologies. Structuring content using semantic HTML elements like <section>
and <article>
while applying grid-cols-*
maintains a consistent reading experience for screen readers.
Moreover, grid-cols-*
should be applied in a way that prevents excessive text wrapping or narrow columns, which can reduce readability. Ensuring sufficient column width, particularly for text-heavy content, improves user comprehension.
Focus on High Contrast
A well-structured grid layout should also prioritize sufficient contrast to accommodate users with visual impairments. While grid-cols-*
primarily affects layout, it indirectly influences contrast by determining the positioning and spacing of elements. Placing text over busy backgrounds, especially in multi-column grids, can reduce readability.
To mitigate this, use high-contrast foreground and background colors, ensuring that text elements maintain a minimum contrast ratio of 4.5:1
for normal text and 3:1
for large text, as recommended by WCAG. Additionally, when using background images, applying backdrop-brightness-*
or backdrop-contrast-*
can enhance text visibility without requiring significant layout changes.
Interactive components such as buttons or links within grid-based layouts must remain highly distinguishable. Use distinct color combinations and border-*
utilities to enhance contrast. Additionally, incorporating focus:ring-*
classes provides a visual cue when elements receive focus, ensuring that users navigating via keyboard can clearly perceive interactive elements.