Lovable projects use Tailwind CSS, so responsive layouts are built with Tailwind breakpoint prefixes (sm:, md:, lg:) rather than traditional CSS media queries. Use Tailwind breakpoints for screen-size responsiveness, custom CSS media queries for print styles and prefers-color-scheme, and the Design view for visual adjustments. Tailwind's mobile-first approach means unprefixed classes apply to all screens, and prefixed classes override at larger widths.
Why traditional CSS media queries behave differently in Lovable projects
Lovable generates projects with Tailwind CSS, which has its own responsive design system built on utility class prefixes. Instead of writing @media (min-width: 768px) in a CSS file, you write md: before any Tailwind class directly in your JSX. This approach is more convenient for AI-generated code because the responsive behavior lives right next to the element it affects. Traditional CSS media queries still work in Lovable projects — Tailwind does not prevent you from using them. But mixing both approaches creates confusion. If a Tailwind class says md:flex and a CSS media query also targets the same breakpoint with different styles, the result depends on CSS specificity, which is hard to debug. There are cases where custom CSS media queries are the right choice: print styles (@media print), dark mode detection (@media (prefers-color-scheme: dark)), reduced motion preferences (@media (prefers-reduced-motion: reduce)), and other feature queries. For screen-size responsiveness, Tailwind breakpoints are almost always the better option in Lovable projects.
- Using traditional @media queries when Tailwind breakpoint prefixes would be more appropriate
- Mixing Tailwind responsive classes with custom CSS media queries on the same element
- Not understanding Tailwind's mobile-first approach — unprefixed classes apply to ALL screens
- CSS media queries in external stylesheets being overridden by Tailwind's utility classes
- Missing responsive behavior because breakpoint prefixes were not added to key layout classes
Error messages you might see
Styles not applying at specific screen sizesThis is a visual bug, not a console error. Tailwind uses a mobile-first approach, so classes without a prefix apply to all screen sizes. If you want something to only appear on desktop, you need to hide it by default and show it with md:block or lg:block.
Unknown at rule @tailwindYour CSS editor or linter does not recognize Tailwind directives. This is a tooling warning, not a real error. Tailwind processes these at build time. You can safely ignore this warning.
The 'dark' variant is not enabledTailwind's dark mode variant needs to be enabled in tailwind.config.ts. Set darkMode to 'class' to use the dark: prefix, or 'media' to follow the OS preference.
Before you start
- A Lovable project with a layout that needs to adapt to different screen sizes
- Basic understanding of Tailwind CSS classes (flex, grid, hidden, block, etc.)
- The Lovable preview panel open for testing responsive behavior
How to fix it
Use Tailwind breakpoint prefixes instead of CSS media queries for layout
Tailwind breakpoints are co-located with your elements, making responsive behavior easier to read and maintain
Use Tailwind breakpoint prefixes instead of CSS media queries for layout
Tailwind breakpoints are co-located with your elements, making responsive behavior easier to read and maintain
Replace custom CSS media queries with Tailwind's built-in breakpoint prefixes. Tailwind uses a mobile-first approach: unprefixed classes apply to all screens, and prefixed classes activate at that breakpoint and above. The default breakpoints are sm: (640px), md: (768px), lg: (1024px), xl: (1280px), and 2xl: (1536px). Apply these directly to your JSX class names.
/* styles.css */.dashboard-grid { display: grid; grid-template-columns: 1fr;}@media (min-width: 768px) { .dashboard-grid { grid-template-columns: 250px 1fr; }}@media (min-width: 1024px) { .dashboard-grid { grid-template-columns: 300px 1fr 250px; }}// JSX with Tailwind breakpoints — no external CSS needed<div className="grid grid-cols-1 md:grid-cols-[250px_1fr] lg:grid-cols-[300px_1fr_250px]"> <aside className="hidden md:block">Sidebar</aside> <main>Content</main> <aside className="hidden lg:block">Right Panel</aside></div>Expected result: On mobile: single column layout. On tablet (md): two columns with sidebar. On desktop (lg): three columns with both sidebars.
Add print styles using a CSS media query
Print styles are one of the few cases where a custom media query is better than Tailwind breakpoints
Add print styles using a CSS media query
Print styles are one of the few cases where a custom media query is better than Tailwind breakpoints
Tailwind has a built-in print: variant, but for complex print layouts you may need a dedicated @media print block. Add this to your global CSS file (usually src/index.css). Print styles should hide navigation, sidebars, and interactive elements while optimizing the main content for paper. This is a case where traditional media queries are the right tool.
// No print styles — page prints with navigation, buttons, etc./* src/index.css — add after Tailwind directives */@media print { /* Hide navigation and interactive elements when printing */ nav, .sidebar, button, .no-print { display: none !important; } /* Remove backgrounds and shadows for cleaner printing */ * { background: white !important; box-shadow: none !important; } /* Ensure content fills the page width */ main { width: 100% !important; margin: 0 !important; padding: 0 !important; }}Expected result: Printing the page shows only the main content without navigation, buttons, or decorative elements.
Configure dark mode using Tailwind's dark variant or a media query
Dark mode improves readability in low-light conditions and is expected by modern users
Configure dark mode using Tailwind's dark variant or a media query
Dark mode improves readability in low-light conditions and is expected by modern users
Lovable projects can support dark mode through Tailwind's dark: prefix. First, check your tailwind.config.ts to ensure darkMode is set to either 'class' (toggle via a CSS class on the HTML element) or 'media' (follows OS preference). Then use the dark: prefix on your Tailwind classes. For OS-based detection, 'media' mode uses @media (prefers-color-scheme: dark) automatically. If this involves theme configuration across many components, RapidDev's engineers have set up dark mode across 600+ Lovable projects.
<div className="bg-white text-gray-900"> <h1 className="text-2xl font-bold">Dashboard</h1> <p className="text-gray-600">Welcome back</p></div><div className="bg-white dark:bg-gray-900 text-gray-900 dark:text-white"> <h1 className="text-2xl font-bold">Dashboard</h1> <p className="text-gray-600 dark:text-gray-300">Welcome back</p></div>// In tailwind.config.ts, ensure:// darkMode: "class" (for manual toggle) or "media" (for OS preference)Expected result: The component automatically switches between light and dark color schemes based on the configured mode.
Handle reduced motion preferences for accessibility
Users with vestibular disorders set prefers-reduced-motion in their OS, and your app should respect it
Handle reduced motion preferences for accessibility
Users with vestibular disorders set prefers-reduced-motion in their OS, and your app should respect it
Tailwind includes a motion-reduce: variant that maps to @media (prefers-reduced-motion: reduce). Use this to disable animations for users who have requested reduced motion in their operating system settings. Apply motion-reduce:transition-none to elements with transitions and motion-reduce:animate-none to elements with animations.
<div className="animate-bounce"> <span>New!</span></div><button className="transition-all duration-300 hover:scale-105"> Click me</button><div className="animate-bounce motion-reduce:animate-none"> <span>New!</span></div><button className="transition-all duration-300 hover:scale-105 motion-reduce:transition-none motion-reduce:hover:scale-100"> Click me</button>Expected result: Users with reduced motion preferences see static elements instead of bouncing or scaling animations.
Complete code example
1import { useState } from "react";2import { Button } from "@/components/ui/button";3import { Menu, X } from "lucide-react";45const ResponsiveLayout = ({ children }: { children: React.ReactNode }) => {6 const [sidebarOpen, setSidebarOpen] = useState(false);78 return (9 <div className="min-h-screen bg-background dark:bg-gray-950">10 {/* Mobile header with menu toggle — hidden on desktop */}11 <header className="md:hidden flex items-center justify-between p-4 border-b">12 <h1 className="text-lg font-semibold">My App</h1>13 <Button14 variant="ghost"15 size="icon"16 onClick={() => setSidebarOpen(!sidebarOpen)}17 >18 {sidebarOpen ? <X /> : <Menu />}19 </Button>20 </header>2122 <div className="flex">23 {/* Sidebar: full-screen overlay on mobile, fixed column on desktop */}24 <aside25 className={`26 fixed inset-0 z-40 bg-background p-6 transition-transform duration-20027 motion-reduce:transition-none28 md:static md:z-auto md:w-64 md:border-r md:translate-x-029 ${sidebarOpen ? "translate-x-0" : "-translate-x-full"}30 `}31 >32 <nav className="space-y-2">33 <a href="/" className="block p-2 rounded hover:bg-muted">Home</a>34 <a href="/dashboard" className="block p-2 rounded hover:bg-muted">Dashboard</a>35 <a href="/settings" className="block p-2 rounded hover:bg-muted">Settings</a>36 </nav>37 </aside>3839 {/* Main content area — responsive padding */}40 <main className="flex-1 p-4 md:p-6 lg:p-8">41 {children}42 </main>43 </div>44 </div>45 );46};4748export default ResponsiveLayout;Best practices to prevent this
- Use Tailwind breakpoint prefixes (sm:, md:, lg:) for all screen-size responsive behavior instead of custom media queries
- Remember Tailwind is mobile-first: unprefixed classes apply to all screens, breakpoint prefixes activate at that width and above
- Use custom CSS @media queries only for print styles, prefers-color-scheme, prefers-reduced-motion, and other feature queries
- Never mix Tailwind responsive classes and CSS media queries targeting the same property on the same element
- Test responsive layouts by resizing the Lovable preview panel or using your browser's device emulation mode
- Use the hidden and block classes with breakpoint prefixes to show/hide elements at specific screen sizes
- Enable dark mode in tailwind.config.ts (darkMode: 'class' or 'media') before using the dark: prefix
- Always add motion-reduce: variants to animated elements for accessibility compliance
Still stuck?
Copy one of these prompts to get a personalized, step-by-step explanation.
I have a Lovable project using Tailwind CSS and I need help with responsive design. Here is my current component: [paste your component code here] Please: 1. Convert any CSS media queries to Tailwind breakpoint prefixes 2. Make the layout single-column on mobile, two-column on tablet (md), and three-column on desktop (lg) 3. Add a mobile menu toggle that shows/hides the sidebar 4. Add dark mode support using Tailwind's dark: variant 5. Add print styles that hide navigation and optimize content for paper
Make @src/components/Layout.tsx fully responsive using Tailwind breakpoints. On mobile (default): single column layout with a hamburger menu that toggles the sidebar. On tablet (md:): two-column layout with a fixed sidebar. On desktop (lg:): wider sidebar and more padding on the main content. Add dark mode support with the dark: variant. Add motion-reduce: variants to all animated elements. Do not use custom CSS media queries for layout — use only Tailwind breakpoint prefixes.
Frequently asked questions
Should I use CSS media queries or Tailwind breakpoints in Lovable?
Use Tailwind breakpoint prefixes (sm:, md:, lg:, xl:) for screen-size responsiveness. They are co-located with your elements, work well with AI-generated code, and are the standard approach in Tailwind projects. Reserve CSS media queries for print styles, color scheme detection, and motion preferences.
What are the default Tailwind breakpoints in Lovable?
Tailwind's default breakpoints are: sm (640px), md (768px), lg (1024px), xl (1280px), and 2xl (1536px). These are min-width breakpoints in a mobile-first system. An md: class activates at 768px and above.
How does Tailwind's mobile-first approach work?
Classes without a breakpoint prefix apply to all screen sizes starting from the smallest. Breakpoint prefixes like md: activate at that width and above, overriding the base class. So 'hidden md:block' means hidden on mobile and visible on tablet and above.
How do I add dark mode to my Lovable project?
Set darkMode to 'class' or 'media' in tailwind.config.ts. With 'class' mode, toggle a 'dark' class on the HTML element. With 'media' mode, it follows the OS preference automatically. Then use the dark: prefix on Tailwind classes: bg-white dark:bg-gray-900.
Can I add print styles in a Lovable project?
Yes. Tailwind has a print: variant you can use on individual elements (print:hidden). For global print styles, add an @media print block in src/index.css after the Tailwind directives. Hide navigation and interactive elements, remove decorative backgrounds, and optimize the layout for paper.
What if I can't fix this myself?
If your responsive layout involves complex breakpoint logic, conditional rendering, or dark mode theming across many components, RapidDev's engineers can help. They have built adaptive layouts for 600+ Lovable projects across all device types.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your issue.
Book a free consultation