Menu

Tailwind CSS Grid Auto Rows

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

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-rows, allowing both beginner and advanced developers to define implicit row sizing with minimal effort.

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

Overview of Grid Auto Rows

Adding the Grid Auto Rows

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

This is a live editor. Play around with it!
export default function AutoRowsDemo() {
  return (
    <div className="grid grid-cols-2 grid-rows-2 grid-flow-row auto-rows-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-rows 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-rows-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-rows</code></p>
      <div className="grid grid-cols-2 grid-rows-2 grid-flow-row hover:auto-rows-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-rows 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-rows</code> on the <code>md</code> breakpoint</p>
      <div className="grid grid-cols-2 grid-rows-2 grid-flow-row md:auto-rows-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 Rows

Extending the Theme

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

This is especially useful if you have repeated patterns in your design system—like rows that always need to be at least 200px long 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-row auto-rows-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-row auto-rows-[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

Recipe Card Grid

A collection of recipe cards with varying content lengths, using auto rows to maintain consistent heights.

This is a live editor. Play around with it!
const RecipeGrid = () => {
  const recipes = [
    {
      id: 1,
      name: "Avocado Toast",
      time: "10 min",
      difficulty: "Easy",
      src: "https://images.unsplash.com/photo-1588137378633-dea1336ce1e2",
      alt: "Avocado toast with eggs",
      ingredients: ["Bread", "Avocado", "Eggs", "Salt", "Pepper"]
    },
    {
      id: 2,
      name: "Berry Smoothie Bowl",
      time: "15 min",
      difficulty: "Easy",
      src: "https://images.unsplash.com/photo-1494315153767-9c231f2dfe79",
      alt: "Smoothie bowl with berries and granola",
      ingredients: ["Mixed Berries", "Banana", "Yogurt", "Honey", "Granola"]
    },
    {
      id: 3,
      name: "Quinoa Buddha Bowl",
      time: "25 min",
      difficulty: "Medium",
      src: "https://images.unsplash.com/photo-1546069901-ba9599a7e63c",
      alt: "Vegetarian buddha bowl",
      ingredients: ["Quinoa", "Chickpeas", "Kale", "Sweet Potato", "Tahini"]
    },
    {
      id: 4,
      name: "Chia Pudding",
      time: "5 min + 4h",
      difficulty: "Easy",
      src: "https://images.unsplash.com/photo-1551239326-fd02c74548ec",
      alt: "Chia seed pudding with fruits",
      ingredients: ["Chia Seeds", "Almond Milk", "Vanilla", "Maple Syrup"]
    },
    {
      id: 5,
      name: "Mediterranean Salad",
      time: "20 min",
      difficulty: "Easy",
      src: "https://images.unsplash.com/photo-1540189549336-e6e99c3679fe",
      alt: "Fresh mediterranean salad",
      ingredients: ["Cucumber", "Tomatoes", "Olives", "Feta", "Olive Oil"]
    },
    {
      id: 6,
      name: "Overnight Oats",
      time: "10 min + 8h",
      difficulty: "Easy",
      src: "https://images.unsplash.com/photo-1517673132405-a56a62b18caf",
      alt: "Jar of overnight oats",
      ingredients: ["Oats", "Milk", "Chia Seeds", "Honey", "Fruits"]
    }
  ];

  return (
    <div className="p-4 bg-green-50">
      <div className="grid grid-cols-2 grid-rows-2 grid-flow-row auto-rows-fr gap-4">
        {recipes.map((recipe) => (
          <div key={recipe.id} className="bg-white rounded-lg shadow p-3 flex flex-col gap-4 gap-3 pt-5">
            <img
              src={recipe.src}
              alt={recipe.alt}
              className="w-20 h-20 object-cover rounded-lg"
            />
            <div className="flex flex-wrap gap-2">
              <h3 className="text-sm font-semibold mb-1">{recipe.name}</h3>
              <div className="flex gap-2 mb-1">
                <span className="text-xs bg-green-100 text-green-700 px-2 py-0.5 rounded">
                  {recipe.time}
                </span>
                <span className="text-xs bg-blue-100 text-blue-700 px-2 py-0.5 rounded">
                  {recipe.difficulty}
                </span>
              </div>
              <div className="flex flex-wrap gap-1">
                {recipe.ingredients.map((ingredient, idx) => (
                  <span key={idx} className="text-xs text-gray-600">
                    {ingredient}{idx < recipe.ingredients.length - 1 ? "," : ""}
                  </span>
                ))}
              </div>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
};

export default RecipeGrid;

Task Board Layout

A kanban-style task board with cards of varying content length, using auto rows for consistent card heights.

This is a live editor. Play around with it!
const TaskBoard = () => {
  const tasks = [
    {
      id: 1,
      title: "Update Homepage Design",
      priority: "High",
      dueDate: "2024-02-10",
      assignee: "Sarah K.",
      status: "In Progress",
      tags: ["Design", "Frontend"]
    },
    {
      id: 2,
      title: "Fix Payment Gateway Bug",
      priority: "Critical",
      dueDate: "2024-02-08",
      assignee: "Mike R.",
      status: "Pending",
      tags: ["Backend", "Bug"]
    },
    {
      id: 3,
      title: "Write API Docs",
      priority: "Medium",
      dueDate: "2024-02-15",
      assignee: "Alex M.",
      status: "Todo",
      tags: ["Documentation"]
    },
    {
      id: 4,
      title: "Implement User Authentication",
      priority: "High",
      dueDate: "2024-02-12",
      assignee: "Chris L.",
      status: "In Progress",
      tags: ["Security", "Backend"]
    },
    {
      id: 5,
      title: "Create Email Templates",
      priority: "Low",
      dueDate: "2024-02-20",
      assignee: "Emma S.",
      status: "Todo",
      tags: ["Marketing", "Design"]
    },
    {
      id: 6,
      title: "Optimize Database Queries",
      priority: "Medium",
      dueDate: "2024-02-18",
      assignee: "David P.",
      status: "Pending",
      tags: ["Database", "Performance"]
    }
  ];

  return (
    <div className="p-4 bg-gray-100">
      <div className="grid grid-cols-2 grid-rows-2 auto-rows-fr gap-3">
        {tasks.map((task) => (
          <div key={task.id} className="bg-white rounded-lg p-3 shadow-sm">
            <div className="flex justify-between items-start mb-2">
              <h3 className="text-sm font-medium">{task.title}</h3>
              <span className={`text-xs px-2 py-1 rounded ${
                task.priority === "High" ? "bg-orange-100 text-orange-700" :
                task.priority === "Critical" ? "bg-red-100 text-red-700" :
                task.priority === "Medium" ? "bg-blue-100 text-blue-700" :
                "bg-gray-100 text-gray-700"
              }`}>
                {task.priority}
              </span>
            </div>
            <div className="flex flex-col gap-1">
              <div className="flex items-center gap-2">
                <span className="text-xs text-gray-500">Due:</span>
                <span className="text-xs">{task.dueDate}</span>
              </div>
              <div className="flex items-center gap-2">
                <span className="text-xs text-gray-500">Assignee:</span>
                <span className="text-xs">{task.assignee}</span>
              </div>
              <div className="flex flex-wrap gap-1 mt-1">
                {task.tags.map((tag, idx) => (
                  <span key={idx} className="text-xs bg-gray-100 px-2 py-0.5 rounded">
                    {tag}
                  </span>
                ))}
              </div>
              <span className={`text-xs mt-1 px-2 py-0.5 rounded-full w-fit ${
                task.status === "In Progress" ? "bg-yellow-100 text-yellow-700" :
                task.status === "Pending" ? "bg-purple-100 text-purple-700" :
                "bg-gray-100 text-gray-700"
              }`}>
                {task.status}
              </span>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
};

export default TaskBoard;

Team Member Directory

A grid of team member cards with photos and varying amounts of information, using auto rows for consistent presentation.

This is a live editor. Play around with it!
const TeamDirectory = () => {
  const team = [
    {
      id: 1,
      name: "Emily Chen",
      role: "Product Designer",
      department: "Design",
      location: "San Francisco",
      src: "https://images.unsplash.com/photo-1494790108377-be9c29b29330",
      alt: "Emily Chen profile photo",
      skills: ["UI/UX", "Prototyping", "User Research"]
    },
    {
      id: 2,
      name: "Marcus Johnson",
      role: "Senior Developer",
      department: "Engineering",
      location: "New York",
      src: "https://images.unsplash.com/photo-1500648767791-00dcc994a43e",
      alt: "Marcus Johnson profile photo",
      skills: ["React", "Node.js", "AWS"]
    },
    {
      id: 3,
      name: "Sophie Williams",
      role: "Marketing Manager",
      department: "Marketing",
      location: "London",
      src: "https://images.unsplash.com/photo-1534528741775-53994a69daeb",
      alt: "Sophie Williams profile photo",
      skills: ["Strategy", "Analytics", "Content"]
    },
    {
      id: 4,
      name: "Carlos Rodriguez",
      role: "Data Scientist",
      department: "Analytics",
      location: "Berlin",
      src: "https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d",
      alt: "Carlos Rodriguez profile photo",
      skills: ["Python", "ML", "Statistics"]
    },
    {
      id: 5,
      name: "Lisa Thompson",
      role: "Product Manager",
      department: "Product",
      location: "Toronto",
      src: "https://images.unsplash.com/photo-1438761681033-6461ffad8d80",
      alt: "Lisa Thompson profile photo",
      skills: ["Strategy", "Agile", "Leadership"]
    },
    {
      id: 6,
      name: "James Wilson",
      role: "UX Researcher",
      department: "Design",
      location: "Sydney",
      src: "https://images.unsplash.com/photo-1472099645785-5658abf4ff4e",
      alt: "James Wilson profile photo",
      skills: ["User Testing", "Interviews", "Analysis"]
    }
  ];

  return (
    <div className="p-4 bg-purple-50">
      <div className="grid grid-cols-1 grid-rows-1 grid-flow-rows auto-rows-fr gap-3">
        {team.map((member) => (
          <div key={member.id} className="bg-white rounded-lg p-3 shadow-sm flex gap-3">
            <img
              src={member.src}
              alt={member.alt}
              className="w-16 h-16 rounded-full object-cover"
            />
            <div className="flex-1">
              <h3 className="text-sm font-semibold">{member.name}</h3>
              <p className="text-xs text-purple-600 mb-1">{member.role}</p>
              <div className="flex items-center gap-1 mb-1">
                <span className="text-xs text-gray-500">{member.department}</span>
                <span className="text-xs text-gray-400">•</span>
                <span className="text-xs text-gray-500">{member.location}</span>
              </div>
              <div className="flex flex-wrap gap-1">
                {member.skills.map((skill, idx) => (
                  <span 
                    key={idx}
                    className="text-xs bg-purple-100 text-purple-700 px-2 py-0.5 rounded-full"
                  >
                    {skill}
                  </span>
                ))}
              </div>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
};

export default TeamDirectory;

Blog Post Grid

A responsive grid of blog post cards with featured images and varying content lengths, using auto rows for consistent presentation.

This is a live editor. Play around with it!
const BlogGrid = () => {
  const posts = [
    {
      id: 1,
      title: "The Future of Remote Work",
      category: "Business",
      readTime: "5 min",
      date: "Feb 1, 2024",
      src: "https://images.unsplash.com/photo-1516387938699-a93567ec168e",
      alt: "Person working on laptop",
      excerpt: "Exploring the evolving landscape of remote work and its impact on business culture.",
      author: {
        name: "Alex Morgan",
        avatar: "https://images.unsplash.com/photo-1472099645785-5658abf4ff4e"
      }
    },
    {
      id: 2,
      title: "Sustainable Living Tips",
      category: "Lifestyle",
      readTime: "4 min",
      date: "Feb 3, 2024",
      src: "https://images.unsplash.com/photo-1542601906990-b4d3fb778b09",
      alt: "Eco-friendly products",
      excerpt: "Simple ways to reduce your carbon footprint and live more sustainably.",
      author: {
        name: "Emma Wilson",
        avatar: "https://images.unsplash.com/photo-1494790108377-be9c29b29330"
      }
    },
    {
      id: 3,
      title: "AI in Healthcare",
      category: "Technology",
      readTime: "6 min",
      date: "Feb 5, 2024",
      src: "https://images.unsplash.com/photo-1576091160399-112ba8d25d1d",
      alt: "Medical technology",
      excerpt: "How artificial intelligence is revolutionizing healthcare delivery and patient care.",
      author: {
        name: "David Chen",
        avatar: "https://images.unsplash.com/photo-1500648767791-00dcc994a43e"
      }
    },
    {
      id: 4,
      title: "Mindful Meditation Guide",
      category: "Wellness",
      readTime: "3 min",
      date: "Feb 7, 2024",
      src: "https://images.unsplash.com/photo-1506126613408-eca07ce68773",
      alt: "Peaceful meditation setting",
      excerpt: "A beginner's guide to starting a daily meditation practice.",
      author: {
        name: "Sarah Lee",
        avatar: "https://images.unsplash.com/photo-1534528741775-53994a69daeb"
      }
    },
    {
      id: 5,
      title: "Urban Gardening Tips",
      category: "Lifestyle",
      readTime: "4 min",
      date: "Feb 9, 2024",
      src: "https://images.unsplash.com/photo-1466692476868-aef1dfb1e735",
      alt: "Small urban garden",
      excerpt: "Creating your own green space in the city with limited space.",
      author: {
        name: "Mike Brown",
        avatar: "https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d"
      }
    },
    {
      id: 6,
      title: "Digital Privacy Guide",
      category: "Technology",
      readTime: "5 min",
      date: "Feb 11, 2024",
      src: "https://images.unsplash.com/photo-1563013544-824ae1b704d3",
      alt: "Computer security concept",
      excerpt: "Essential tips for protecting your online privacy and security.",
      author: {
        name: "Lisa Park",
        avatar: "https://images.unsplash.com/photo-1438761681033-6461ffad8d80"
      }
    }
  ];

  return (
    <div className="p-4 bg-blue-50">
      <div className="grid grid-cols-1 grid-rows-1 auto-rows-[140px] gap-4">
        {posts.map((post) => (
          <div key={post.id} className="bg-white rounded-lg shadow-sm overflow-hidden">
            <div className="flex h-full">
              <img
                src={post.src}
                alt={post.alt}
                className="w-24 object-cover"
              />
              <div className="p-3 flex-1">
                <div className="flex items-center gap-2 mb-1">
                  <span className="text-xs bg-blue-100 text-blue-700 px-2 py-0.5 rounded-full">
                    {post.category}
                  </span>
                  <span className="text-xs text-gray-500">{post.readTime}</span>
                </div>
                <h3 className="text-sm font-semibold mb-1">{post.title}</h3>
                <p className="text-xs text-gray-600 mb-2 line-clamp-2">{post.excerpt}</p>
                <div className="flex items-center gap-2">
                  <img
                    src={post.author.avatar}
                    alt={`${post.author.name}'s avatar`}
                    className="w-5 h-5 rounded-full object-cover"
                  />
                  <span className="text-xs text-gray-600">{post.author.name}</span>
                  <span className="text-xs text-gray-400">•</span>
                  <span className="text-xs text-gray-500">{post.date}</span>
                </div>
              </div>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
};

export default BlogGrid;

A responsive product grid showcasing electronics items with equal height rows, maintaining consistent spacing and alignment.

This is a live editor. Play around with it!
const ProductGallery = () => {
  const products = [
    {
      id: 1,
      name: "Wireless Earbuds",
      price: "$129.99",
      src: "https://images.unsplash.com/photo-1590658268037-6bf12165a8df",
      alt: "White wireless earbuds in charging case",
      rating: 4.5,
      stock: "In Stock"
    },
    {
      id: 2,
      name: "Smart Watch",
      price: "$199.99",
      src: "https://images.unsplash.com/photo-1579586337278-3befd40fd17a",
      alt: "Black smartwatch displaying fitness data",
      rating: 4.8,
      stock: "Low Stock"
    },
    {
      id: 3,
      name: "Noise-Canceling Headphones",
      price: "$299.99",
      src: "https://images.unsplash.com/photo-1583394838336-acd977736f90",
      alt: "Black over-ear headphones",
      rating: 4.7,
      stock: "In Stock"
    },
    {
      id: 4,
      name: "Bluetooth Speaker",
      price: "$79.99",
      src: "https://images.unsplash.com/photo-1608043152269-423dbba4e7e1",
      alt: "Portable bluetooth speaker in black",
      rating: 4.3,
      stock: "In Stock"
    },
    {
      id: 5,
      name: "Wireless Charger",
      price: "$39.99",
      src: "https://images.unsplash.com/photo-1554227231-54aa5db01c51",
      alt: "White wireless charging pad",
      rating: 4.4,
      stock: "Out of Stock"
    },
    {
      id: 6,
      name: "USB-C Hub",
      price: "$49.99",
      src: "https://images.unsplash.com/photo-1625723044792-44de16ccb4e9",
      alt: "Multi-port USB hub in silver",
      rating: 4.6,
      stock: "In Stock"
    }
  ];

  return (
    <div className="p-4 bg-gray-50">
      <div className="grid grid-cols-2 grid-rows-1 auto-rows-[190px] gap-3">
        {products.map((product) => (
          <div key={product.id} className="bg-white rounded-lg shadow-sm p-2">
            <img
              src={product.src}
              alt={product.alt}
              className="w-full h-24 object-cover rounded-md mb-2"
            />
            <h3 className="text-xs font-medium truncate">{product.name}</h3>
            <div className="flex justify-between items-center mt-1">
              <span className="text-xs font-bold text-blue-600">{product.price}</span>
              <span className="text-xs text-gray-500">★{product.rating}</span>
            </div>
            <span className={`text-xs ${
              product.stock === "Out of Stock" 
                ? "text-red-500" 
                : product.stock === "Low Stock" 
                  ? "text-orange-500" 
                  : "text-green-500"
            }`}>
              {product.stock}
            </span>
          </div>
        ))}
      </div>
    </div>
  );
};

export default ProductGallery;

Customization Examples

Small Cards Layout

A grid of small product cards that automatically adjusts rows 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-rows-card grid-flow-row grid-cols-2 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 rows 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-rows-article grid-flow-row 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 rows 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-rows-profile grid-flow-row grid-cols-2 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

Maintain Design Consistency

Using the auto-rows-* utility in Tailwind CSS should align with a structured design system to ensure visual harmony. Defining consistent row sizes across different sections prevents unexpected layout shifts. When applying auto-rows-min or auto-rows-max, consider their impact on elements with dynamic content, such as user-generated text or interactive elements.

Maintaining a predictable structure is particularly important in large-scale applications, where multiple developers may contribute. By using auto-rows-fr, you can distribute space proportionally, creating a balanced interface that adapts to varying amounts of content.

Optimize for Reusability

A well-structured grid system using auto-rows-* should be designed for scalability and reusability. Creating reusable components that adapt to different content types ensures consistency throughout a project. By encapsulating grid layouts within these components, different sections can remain flexible without redundant code.

For example, a card layout can use auto-rows-min to prevent content-heavy cards from collapsing while keeping shorter content compact. A generic grid component that accepts auto-rows-* values as props improves adaptability across various contexts. This approach reduces maintenance effort and maintains a consistent design system.

Reusability also plays a key role in responsive design. Defining breakpoints within reusable components allows layouts to adjust seamlessly to different screen sizes. By focusing on scalability, auto-rows-* can be effectively used across multiple sections while ensuring a consistent user experience.

Accessibility Considerations

Enhance Readability and Navigability

When rows are too compressed, text and interactive elements can become difficult to distinguish, impacting readability. Using auto-rows-fr distributes space dynamically, maintaining an organized layout that improves user engagement.

For navigability, defining consistent row heights prevents erratic jumps when navigating through content with assistive technologies.

Additionally, pairing auto-rows-* with focus-visible:outline-* ensures that interactive elements remain accessible. Clear focus indicators guide users through interactive components, improving overall accessibility. By considering readability and navigability, auto-rows-* contributes to an inclusive design.

Focus on High Contrast

Ensuring sufficient contrast is crucial for users with visual impairments. When using auto-rows-* in grid layouts, maintaining clear text and background contrast improves accessibility. Pairing bg-* utilities with auto-rows-* prevents readability issues caused by blending colors.

For example, light-colored text on a white background can become unreadable, especially when text wraps across multiple lines. Using text-black or text-white ensures proper contrast. Adding border-* utilities alongside auto-rows-* helps separate sections, making content easier to distinguish.