Skip to main content
RapidDev - Software Development Agency
lovable-issues

Using Media Queries and Tailwind Breakpoints in Lovable Layouts

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.

Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Intermediate8 min read~10 minAll Lovable projects (Tailwind CSS)March 2026RapidDev Engineering Team
TL;DR

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 sizes

This 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 @tailwind

Your 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 enabled

Tailwind'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

1

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.

Before
typescript
/* 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;
}
}
After
typescript
// 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.

2

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.

Before
typescript
// No print styles — page prints with navigation, buttons, etc.
After
typescript
/* 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.

3

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.

Before
typescript
<div className="bg-white text-gray-900">
<h1 className="text-2xl font-bold">Dashboard</h1>
<p className="text-gray-600">Welcome back</p>
</div>
After
typescript
<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.

4

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.

Before
typescript
<div className="animate-bounce">
<span>New!</span>
</div>
<button className="transition-all duration-300 hover:scale-105">
Click me
</button>
After
typescript
<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

src/components/ResponsiveLayout.tsx
1import { useState } from "react";
2import { Button } from "@/components/ui/button";
3import { Menu, X } from "lucide-react";
4
5const ResponsiveLayout = ({ children }: { children: React.ReactNode }) => {
6 const [sidebarOpen, setSidebarOpen] = useState(false);
7
8 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 <Button
14 variant="ghost"
15 size="icon"
16 onClick={() => setSidebarOpen(!sidebarOpen)}
17 >
18 {sidebarOpen ? <X /> : <Menu />}
19 </Button>
20 </header>
21
22 <div className="flex">
23 {/* Sidebar: full-screen overlay on mobile, fixed column on desktop */}
24 <aside
25 className={`
26 fixed inset-0 z-40 bg-background p-6 transition-transform duration-200
27 motion-reduce:transition-none
28 md:static md:z-auto md:w-64 md:border-r md:translate-x-0
29 ${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>
38
39 {/* 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};
47
48export 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.

ChatGPT Prompt

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

Lovable Prompt

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.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your issue.

Book a free consultation

Need help with your Lovable project?

Our experts have built 600+ apps and can solve your issue fast. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.