shadcn Grid Generator
Draw the layout. Get a shadcn-style component, not a class string.
Named areas. The CSS is a picture of the layout, and only the properties that actually change get repeated inside each media query.
.layout {
display: grid;
grid-template-columns: 1fr;
grid-template-rows: auto 1fr auto;
gap: 16px;
grid-template-areas:
"header"
"main"
"footer";
}
.layout > .header { grid-area: header; }
.layout > .main { grid-area: main; }
.layout > .footer { grid-area: footer; }
.layout > .nav { display: none; }
@media (min-width: 768px) {
.layout {
grid-template-columns: 220px 1fr;
grid-template-areas:
"header header"
"nav main"
"footer footer";
}
.layout > .nav { grid-area: nav; }
}
Layout is the gap in shadcn/ui
shadcn/ui gives you dialogs, comboboxes and forms. It does not give you a grid, because layout is meant to be Tailwind classes on a div — which is fine until the same class string is copied across six pages. This generates that div as a proper component, following the same conventions as shadcn's own primitives.
How to use it
-
Draw the layout
Drag across the grid to create areas. Each one becomes a named part of the component you get back.
-
Set each breakpoint
Move the ruler past a breakpoint marker and rearrange. The responsive prefixes are written for you.
-
Open the shadcn/ui tab
The output panel has a shadcn/ui tab beside CSS, HTML and Tailwind.
-
Paste it into your project
Drop the file in components/, keep the cn() import, and use the compound components as shown in the usage comment.
What the output follows
Three shadcn conventions. cn() merges incoming classes so a caller can override
the defaults without a specificity fight. data-slot gives every part a stable
styling and testing hook. React.ComponentProps<"div"> keeps native props
working, so id, onClick and aria-* pass straight
through.
Compound parts, not one blob
A root component plus one named part per area, exported together and shown with a usage
comment. The point is that col-start-2 md:row-start-1 lives inside
LayoutMain rather than being scattered across every page that renders the
layout.
You do not need shadcn installed
cn() is the only dependency, and it is four lines of clsx plus
tailwind-merge. Swap it for a template literal and the component works in any
React and Tailwind project. If you want the plain version instead, the
Tailwind tab gives you the raw markup.
Frequently asked questions
Does shadcn/ui have a grid component?
What makes a component "shadcn-style"?
cn() to merge incoming classes so callers can override, a data-slot attribute to give the part a styling and testing hook, and React.ComponentProps<"div"> so it still accepts every native prop. The output here follows all three.Why does the output use compound components?
<Layout><LayoutSidebar /><LayoutMain /></Layout> keeps the grid placement with the component instead of scattering col-start-2 across your pages.What is cn() and do I need it?
cn() is shadcn's helper combining clsx and tailwind-merge. It merges class strings and resolves Tailwind conflicts so a className passed by the caller wins over the default. It lives in @/lib/utils in any shadcn project; if yours does not have it, npx shadcn@latest init creates it.Can I use this without shadcn/ui installed?
cn(). Replace it with a template literal, or the two-line clsx + tailwind-merge version, and the component works in any React and Tailwind project.