Menu

Tailwind CSS Grid Auto Columns

Grid Auto Columns defines the size of implicit grid columns—columns that are automatically created instead of explicitly defined with grid-template-columns.

Tailwind CSS provides grid utilities to help you implement grid properties quickly. Among these utilities is a set of classes specifically dedicated to grid-auto-columns, allowing both beginner and advanced developers to define implicit column sizing with minimal effort.

ClassPropertiesExample
auto-cols-autogrid-auto-columns: auto;<div className="auto-cols-auto"></div>
auto-cols-mingrid-auto-columns: min-content;<div className="auto-cols-min"></div>
auto-cols-maxgrid-auto-columns: max-content;<div className="auto-cols-max"></div>
auto-cols-frgrid-auto-columns: minmax(0, 1fr);<div className="auto-cols-fr"></div>

Overview of Grid Auto Columns

Adding the Grid Auto Columns

To define the size of implicit columns in a grid container, use the auto-cols-* utilities, e.g., auto-cols-max, auto-cols-fr, etc.

This is a live editor. Play around with it!
export default function AutoColumnsDemo() {
  return (
    <div className="grid grid-cols-2 grid-rows-2 grid-flow-col auto-cols-fr gap-4 bg-gray-100 p-8 gap-4 h-screen">
      <div className="bg-blue-300" />
      <div className="bg-red-300" />
      <div className="bg-green-300" />
      <div className="bg-pink-300" />
      <div className="bg-amber-300" />
      <div className="bg-indigo-300" />
    </div>
  );
}

States and Responsiveness

Hover and Focus States

Tailwind allows you to conditionally apply the grid-auto-columns on certain states like hover and focus. Use Tailwind's state modifiers like- hover, focus, etc. to apply the utility only when these states are active, e.g., hover:auto-cols-fr.

This is a live editor. Play around with it!
export default function HoverFlowGrid() {
  return (
    <div className="h-screen w-screen">
      <p className="underline px-10 text-center pt-6">Hover on the below container to add the <code>grid-auto-columns</code></p>
      <div className="grid grid-cols-2 grid-rows-2 grid-flow-col hover:auto-cols-fr gap-4 bg-lime-100 p-8 gap-4 h-72 mt-10">
        <div className="bg-blue-300" />
        <div className="bg-red-300" />
        <div className="bg-green-300" />
        <div className="bg-pink-300" />
        <div className="bg-amber-300" />
        <div className="bg-indigo-300" />
      </div>
    </div>
  );
}

Breakpoint Modifiers

Tailwind CSS provides breakpoint modifiers to conditionally apply the grid-auto-columns only when the screen hits the defined breakpoint. Use Tailwind's breakpoint modifiers like- sm, md, etc., to apply the utility only on these breakpoints and above.

This is a live editor. Play around with it!
export default function ResponsiveAutoFlow() {
  return (
    <div className="h-screen w-screen">
      <p className="underline px-6 text-center pt-6">The below container will change the <code>grid-auto-columns</code> on the <code>md</code> breakpoint</p>
      <div className="grid grid-cols-2 grid-rows-2 grid-flow-col md:auto-cols-fr gap-4 bg-lime-100 p-8 gap-4 h-72 mt-10">
        <div className="bg-blue-300" />
        <div className="bg-red-300" />
        <div className="bg-green-300" />
        <div className="bg-pink-300" />
        <div className="bg-amber-300" />
        <div className="bg-indigo-300" />
      </div>
    </div>
  );
}

Custom Grid Auto Columns

Extending the Theme

One way to incorporate your own grid-auto-columns values is by extending the Tailwind theme configuration. In your tailwind.config.js, you can define gridAutoColumns properties that map to custom sizes.

This is especially useful if you have repeated patterns in your design system—like columns that always need to be at least 200px wide or 50% of the available space.

This is a live editor. Play around with it!
import tailwindConfig from "./tailwind.config.js";
tailwind.config = tailwindConfig;

export default function CustomThemeColumns() {
  return (
    <div className="grid grid-cols-2 grid-rows-2 grid-flow-col auto-cols-custom gap-4 bg-gray-100 p-8 gap-4 h-screen">
      <div className="bg-blue-300" />
      <div className="bg-red-300" />
      <div className="bg-green-300" />
      <div className="bg-pink-300" />
      <div className="bg-amber-300" />
      <div className="bg-indigo-300" />
    </div>
  );
}

Using Arbitrary Values

Tailwind CSS also lets you specify arbitrary values by enclosing them in square brackets. This is a quick way to handle one-off sizing needs without updating your configuration file. It’s ideal if you’re experimenting with new designs or need a unique size for a specific situation.

This is a live editor. Play around with it!
export default function ArbitraryColumns() {
  return (
    <div className="grid grid-cols-2 grid-rows-2 grid-flow-col auto-cols-[200px] gap-4 bg-gray-100 p-8 gap-4 h-screen">
      <div className="bg-blue-300" />
      <div className="bg-red-300" />
      <div className="bg-green-300" />
      <div className="bg-pink-300" />
      <div className="bg-amber-300" />
      <div className="bg-indigo-300" />
    </div>
  );
}

Real World Examples

Blog Post Grid

A blog post preview grid that automatically arranges posts based on their importance.

This is a live editor. Play around with it!
const BlogGrid = () => {
  const posts = [
    {
      id: 1,
      title: "The Future of AI",
      category: "Technology",
      readTime: "5 min",
      src: "https://images.unsplash.com/photo-1677442136019-21780ecad995",
      alt: "AI visualization"
    },
    {
      id: 2,
      title: "Sustainable Living",
      category: "Lifestyle",
      readTime: "3 min",
      src: "https://images.unsplash.com/photo-1472141521881-95d0e87e2e39",
      alt: "Eco-friendly home"
    },
    {
      id: 3,
      title: "Remote Work Tips",
      category: "Work",
      readTime: "4 min",
      src: "https://images.unsplash.com/photo-1587614382346-4ec70e388b28",
      alt: "Home office setup"
    },
    {
      id: 4,
      title: "Healthy Recipes",
      category: "Food",
      readTime: "6 min",
      src: "https://images.unsplash.com/photo-1490645935967-10de6ba17061",
      alt: "Healthy meal"
    },
    {
      id: 5,
      title: "Fitness at Home",
      category: "Health",
      readTime: "4 min",
      src: "https://images.unsplash.com/photo-1518611012118-696072aa579a",
      alt: "Home workout"
    },
    {
      id: 6,
      title: "Travel Guide",
      category: "Travel",
      readTime: "5 min",
      src: "https://images.unsplash.com/photo-1488646953014-85cb44e25828",
      alt: "Travel destination"
    }
  ];

  return (
    <div className="p-3 bg-white">
      <div className="grid grid-rows-2 grid-flow-col auto-cols-[180px] gap-3 overflow-x-auto">
        {posts.map(post => (
          <div key={post.id} className="rounded-lg bg-gray-50 shadow-sm">
            <img 
              src={post.src} 
              alt={post.alt}
              className="w-full h-24 object-cover rounded-t-lg"
            />
            <div className="p-2">
              <span className="text-xs text-blue-600">{post.category}</span>
              <h4 className="text-sm font-medium mt-1">{post.title}</h4>
              <p className="text-xs text-gray-500 mt-1">{post.readTime} read</p>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
};

export default BlogGrid;

Task Board Column Flow

A task board with a horizontal scrolling list of task columns.

This is a live editor. Play around with it!
const TaskBoard = () => {
  const tasks = [
    {
      id: 1,
      title: "Design System",
      priority: "High",
      assignee: "Alice",
      status: "In Progress"
    },
    {
      id: 2,
      title: "API Integration",
      priority: "Medium",
      assignee: "Bob",
      status: "Todo"
    },
    {
      id: 3,
      title: "User Testing",
      priority: "Low",
      assignee: "Charlie",
      status: "Done"
    },
    {
      id: 4,
      title: "Documentation",
      priority: "Medium",
      assignee: "David",
      status: "Review"
    },
    {
      id: 5,
      title: "Bug Fixes",
      priority: "High",
      assignee: "Eve",
      status: "In Progress"
    },
    {
      id: 6,
      title: "Feature Release",
      priority: "High",
      assignee: "Frank",
      status: "Todo"
    }
  ];

  return (
    <div className="p-3 bg-gray-100 h-screen">
      <div className="grid grid-rows-2 grid-flow-col auto-cols-[200px] gap-3 overflow-x-auto">
        {['Todo', 'In Progress', 'Review', 'Done'].map(status => (
          <div key={status} className="bg-white rounded-lg p-2 shadow-sm">
            <h4 className="text-sm font-semibold mb-2">{status}</h4>
            <div className="space-y-2">
              {tasks
                .filter(task => task.status === status)
                .map(task => (
                  <div key={task.id} className="bg-gray-50 p-2 rounded">
                    <h5 className="text-xs font-medium">{task.title}</h5>
                    <div className="flex items-center mt-1">
                      <span className={`text-xs px-1.5 rounded ${
                        task.priority === 'High' ? 'bg-red-100 text-red-600' :
                        task.priority === 'Medium' ? 'bg-yellow-100 text-yellow-600' :
                        'bg-green-100 text-green-600'
                      }`}>
                        {task.priority}
                      </span>
                      <span className="text-xs text-gray-500 ml-2">{task.assignee}</span>
                    </div>
                  </div>
                ))}
            </div>
          </div>
        ))}
      </div>
    </div>
  );
};

export default TaskBoard;

A horizontally scrollable team members showcase with automatic column sizing based on content.

This is a live editor. Play around with it!
const TeamCarousel = () => {
  const teamMembers = [
    {
      id: 1,
      name: "Sarah Johnson",
      role: "CEO",
      src: "https://images.unsplash.com/photo-1438761681033-6461ffad8d80",
      alt: "Sarah Johnson",
      department: "Executive"
    },
    {
      id: 2,
      name: "Michael Chen",
      role: "Lead Developer",
      src: "https://images.unsplash.com/photo-1472099645785-5658abf4ff4e",
      alt: "Michael Chen",
      department: "Engineering"
    },
    {
      id: 3,
      name: "Emma Wilson",
      role: "Design Director",
      src: "https://images.unsplash.com/photo-1494790108377-be9c29b29330",
      alt: "Emma Wilson",
      department: "Design"
    },
    {
      id: 4,
      name: "James Rodriguez",
      role: "Marketing Manager",
      src: "https://images.unsplash.com/photo-1500648767791-00dcc994a43e",
      alt: "James Rodriguez",
      department: "Marketing"
    },
    {
      id: 5,
      name: "Lisa Thompson",
      role: "Product Owner",
      src: "https://images.unsplash.com/photo-1534528741775-53994a69daeb",
      alt: "Lisa Thompson",
      department: "Product"
    },
    {
      id: 6,
      name: "David Kim",
      role: "Sales Director",
      src: "https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d",
      alt: "David Kim",
      department: "Sales"
    }
  ];

  return (
    <div className="p-4 bg-gray-100">
      <div className="grid grid-rows-2 grid-flow-col auto-cols-auto gap-3 overflow-x-auto pb-4">
        {teamMembers.map((member) => (
          <div key={member.id} className="bg-white rounded-lg p-3 w-40">
            <img 
              src={member.src} 
              alt={member.alt}
              className="w-24 h-24 rounded-full mx-auto object-cover"
            />
            <div className="text-center mt-2">
              <h3 className="text-sm font-medium">{member.name}</h3>
              <p className="text-xs text-gray-500">{member.role}</p>
              <span className="inline-block text-xs bg-blue-100 text-blue-800 px-2 py-1 rounded mt-2">
                {member.department}
              </span>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
};

export default TeamCarousel;

A scrollable gallery of recipe cards with automatic column sizing and detailed information.

This is a live editor. Play around with it!
const RecipeGallery = () => {
  const recipes = [
    {
      id: 1,
      name: "Quinoa Bowl",
      time: "25 mins",
      difficulty: "Medium",
      calories: "450",
      src: "https://images.unsplash.com/photo-1546069901-ba9599a7e63c",
      alt: "Healthy quinoa bowl",
      category: "Lunch"
    },
    {
      id: 2,
      name: "Grilled Salmon",
      time: "30 mins",
      difficulty: "Medium",
      calories: "520",
      src: "https://images.unsplash.com/photo-1467003909585-2f8a72700288",
      alt: "Grilled salmon dish",
      category: "Dinner"
    },
    {
      id: 3,
      name: "Berry Smoothie",
      time: "10 mins",
      difficulty: "Easy",
      calories: "180",
      src: "https://images.unsplash.com/photo-1553530666-ba11a7da3888",
      alt: "Berry smoothie",
      category: "Drinks"
    },
    {
      id: 4,
      name: "Pasta Primavera",
      time: "35 mins",
      difficulty: "Medium",
      calories: "480",
      src: "https://images.unsplash.com/photo-1556761223-4c4282c73f77",
      alt: "Pasta primavera",
      category: "Dinner"
    },
    {
      id: 5,
      name: "Greek Salad",
      time: "20 mins",
      difficulty: "Easy",
      calories: "280",
      src: "https://images.unsplash.com/photo-1540189549336-e6e99c3679fe",
      alt: "Greek salad",
      category: "Lunch"
    }
  ];

  return (
    <div className="p-4 bg-emerald-50">
      <div className="grid grid-rows-2 auto-cols-fr grid-flow-col gap-4 overflow-x-auto pb-4">
        {recipes.map((recipe) => (
          <div key={recipe.id} className="bg-white rounded-lg shadow-sm p-3 w-52">
            <img 
              src={recipe.src} 
              alt={recipe.alt}
              className="w-full h-28 object-cover rounded-md"
            />
            <div className="mt-2">
              <h3 className="text-sm font-medium">{recipe.name}</h3>
              <span className="inline-block text-xs bg-emerald-100 text-emerald-800 px-2 py-1 rounded mt-1">
                {recipe.category}
              </span>
              <div className="grid grid-cols-2 gap-2 mt-2 text-xs text-gray-600">
                <div>{recipe.time}</div>
                <div>🔥 {recipe.calories} cal</div>
                <div>📊 {recipe.difficulty}</div>
              </div>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
};

export default RecipeGallery;

Event Timeline

A horizontal timeline showing upcoming events with automatic column sizing.

This is a live editor. Play around with it!
const EventTimeline = () => {
  const events = [
    {
      id: 1,
      title: "Tech Conference",
      date: "Mar 15",
      time: "9:00 AM",
      location: "Convention Center",
      category: "Conference",
      attendees: 250
    },
    {
      id: 2,
      title: "Product Launch",
      date: "Mar 18",
      time: "2:00 PM",
      location: "Innovation Hub",
      category: "Launch",
      attendees: 150
    },
    {
      id: 3,
      title: "Workshop",
      date: "Mar 20",
      time: "10:00 AM",
      location: "Training Room",
      category: "Education",
      attendees: 30
    },
    {
      id: 4,
      title: "Networking",
      date: "Mar 22",
      time: "6:00 PM",
      location: "Rooftop Lounge",
      category: "Social",
      attendees: 100
    },
    {
      id: 5,
      title: "Hackathon",
      date: "Mar 25",
      time: "8:00 AM",
      location: "Tech Campus",
      category: "Competition",
      attendees: 200
    },
    {
      id: 6,
      title: "Webinar",
      date: "Mar 28",
      time: "3:00 PM",
      location: "Virtual",
      category: "Online",
      attendees: 500
    }
  ];

  return (
    <div className="p-4 bg-indigo-50">
      <div className="grid grid-rows-3 auto-cols-auto grid-flow-col gap-3 overflow-x-auto pb-4">
        {events.map((event) => (
          <div key={event.id} className="bg-white rounded-lg p-3 w-44">
            <div className="border-l-4 border-indigo-500 pl-2">
              <p className="text-xs font-semibold text-indigo-600">{event.date}</p>
              <h3 className="text-sm font-medium mt-1">{event.title}</h3>
            </div>
            <div className="mt-2 space-y-1 text-xs text-gray-600">
              <p>🕒 {event.time}</p>
              <p>📍 {event.location}</p>
              <p>👥 {event.attendees} attendees</p>
              <span className="inline-block bg-indigo-100 text-indigo-800 px-2 py-1 rounded">
                {event.category}
              </span>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
};

export default EventTimeline;

Customization Examples

Small Cards Layout

A grid of small product cards that automatically adjusts columns based on a fixed width.

This is a live editor. Play around with it!
import tailwindConfig from "./tailwind.config.js";
tailwind.config = tailwindConfig;

const ProductGrid = () => {
  const products = [
    { id: 1, title: 'Laptop', price: '$999', image: 'https://images.unsplash.com/photo-1496181133206-80ce9b88a853?w=150' },
    { id: 2, title: 'Phone', price: '$599', image: 'https://images.unsplash.com/photo-1511707171634-5f897ff02aa9?w=150' },
    { id: 3, title: 'Watch', price: '$299', image: 'https://images.unsplash.com/photo-1523275335684-37898b6baf30?w=150' },
    { id: 4, title: 'Tablet', price: '$499', image: 'https://images.unsplash.com/photo-1542751110-97427bbecf20?w=150' }
  ];

  return (
    <div className="p-4 bg-gray-100 h-screen">
      <div className="grid auto-cols-card grid-flow-col gap-2 overflow-x-auto pb-4">
        {products.map(product => (
          <div key={product.id} className="bg-white rounded-lg shadow-sm p-2">
            <img src={product.image} alt={product.title} className="w-full h-24 object-cover rounded" />
            <h4 className="text-sm font-medium mt-2">{product.title}</h4>
            <p className="text-xs text-gray-600">{product.price}</p>
          </div>
        ))}
      </div>
    </div>
  );
};

export default ProductGrid;

Dynamic News Feed

A responsive news feed layout where columns adjust based on content density.

This is a live editor. Play around with it!
import tailwindConfig from "./tailwind.config.js";
tailwind.config = tailwindConfig;

const NewsFeed = () => {
  const articles = [
    { id: 1, title: 'Breaking News', excerpt: 'Latest updates...', image: 'https://images.unsplash.com/photo-1504711434969-e33886168f5c?w=280' },
    { id: 2, title: 'Tech Updates', excerpt: 'New innovations...', image: 'https://images.unsplash.com/photo-1488590528505-98d2b5aba04b?w=280' },
    { id: 3, title: 'Science Daily', excerpt: 'Recent discoveries...', image: 'https://images.unsplash.com/photo-1507413245164-6160d8298b31?w=280' }
  ];

  return (
    <div className="p-3 bg-white h-full">
      <div className="grid auto-cols-article grid-flow-col gap-3 overflow-x-auto">
        {articles.map(article => (
          <div key={article.id} className="border-b border-gray-200 pb-2">
            <img src={article.image} alt={article.title} className="w-full h-32 object-cover rounded-md" />
            <h3 className="text-sm font-bold mt-2">{article.title}</h3>
            <p className="text-xs text-gray-600 mt-1">{article.excerpt}</p>
          </div>
        ))}
      </div>
    </div>
  );
};

export default NewsFeed;

A gallery of profile cards with auto-sizing columns that maintain visual hierarchy and spacing.

This is a live editor. Play around with it!
import tailwindConfig from "./tailwind.config.js";
tailwind.config = tailwindConfig;

const ProfileGallery = () => {
  const profiles = [
    { id: 1, name: 'Alex', role: 'Designer', image: 'https://images.unsplash.com/photo-1534528741775-53994a69daeb?w=120' },
    { id: 2, name: 'Sam', role: 'Developer', image: 'https://images.unsplash.com/photo-1539571696357-5a69c17a67c6?w=120' },
    { id: 3, name: 'Jordan', role: 'Manager', image: 'https://images.unsplash.com/photo-1517841905240-472988babdf9?w=120' },
    { id: 4, name: 'Taylor', role: 'Artist', image: 'https://images.unsplash.com/photo-1524504388940-b1c1722653e1?w=120' }
  ];

  return (
    <div className="p-4 bg-gray-50 h-screen">
      <div className="grid auto-cols-profile grid-flow-col gap-3 overflow-x-auto">
        {profiles.map(profile => (
          <div key={profile.id} className="bg-white rounded-xl p-3 text-center shadow-sm">
            <div className="w-16 h-16 mx-auto rounded-full overflow-hidden">
              <img src={profile.image} alt={profile.name} className="w-full h-full object-cover" />
            </div>
            <h4 className="text-sm font-medium mt-2">{profile.name}</h4>
            <p className="text-xs text-gray-500">{profile.role}</p>
          </div>
        ))}
      </div>
    </div>
  );
};

export default ProfileGallery;

Best Practices

Maintaining a Consistent Layout Across Projects

When applying auto-cols-* in Tailwind CSS, it is essential to maintain a uniform look and feel throughout your project. Consistency ensures that different sections of the grid align properly, creating a balanced and structured design. Define a standard approach for grid column sizing, ensuring that elements appear harmonious across multiple pages.

Additionally, set a consistent gap between columns using gap-* utilities to create a cleaner appearance. For example, combining auto-cols-fr with gap-4 allows columns to distribute available space evenly while maintaining appropriate separation. This approach enhances readability and usability, making it easier for users to navigate and interact with the interface.

Optimize for Reusability

Building reusable components with auto-cols-* ensures that your grid-based designs remain scalable and adaptable. Instead of manually redefining grid structures for each new section, extract common patterns into modular components that can be repurposed across multiple parts of a project.

For example, a card layout with dynamic content can be built using auto-cols-fr within a responsive container. By wrapping this structure into a reusable component, you can create flexible interfaces without redundant styling.

This approach enhances code maintainability and ensures that future updates require minimal effort.

Accessibility Considerations

Enhance Readability and Navigability

Grid layouts defined with auto-cols-* should prioritize readability and ease of navigation. Proper spacing between columns and well-aligned text contributes to a structured and visually organized design, preventing cognitive overload and ensuring smooth interaction.

To maintain clarity, utilize gap-* utilities to create a balanced separation between columns, making each section distinct. Additionally, use text-left or text-center utilities to align text based on the content type, ensuring that information remains logically structured. For enhanced accessibility, consider defining a clear reading order within the grid, enabling assistive technologies to interpret and navigate content in a user-friendly manner.

Focus on High Contrast

Ensuring high contrast in grid-based designs improves accessibility for users with visual impairments. When using auto-cols-*, it’s crucial to maintain a strong contrast ratio between text and background elements. The combination of bg-*, text-*, and border-* utilities in Tailwind CSS allows for optimal contrast adjustments.

For interactive components, apply hover:bg-opacity-* and focus:outline-* to ensure that elements remain distinguishable when users interact with them. These enhancements make it easier for users to engage with the content, particularly in low-vision scenarios.