Skip to main content
Visual Arts & DesignWeb Polish302 lines

Responsive Repair

Fix broken responsive layouts in a vibecoded website — content overflowing on mobile,

Quick Summary28 lines
Responsive breakage is the most common defect in vibecoded websites because AI-generated code optimizes for the viewport it was shown during generation -- typically a desktop width. Mobile is an afterthought that manifests as horizontal scrollbars, unreadably small text, untappable buttons, and three-column grids that refuse to stack on a phone. These are not edge cases -- they affect the majority of real users, since mobile traffic exceeds desktop traffic for most websites.

## Key Points

1. **Horizontal overflow.** Fixed-width elements (tables, code blocks, images) wider than the
2. **Grids that don't collapse.** Three-column grids staying three columns on a 375px phone.
3. **Touch targets too small.** 24px buttons and 16px-tall links that are impossible to tap.
4. **Text too small.** Body text below 16px causing iOS zoom on form inputs.
5. **Navigation doesn't adapt.** Desktop nav bar wrapping uglily instead of becoming a mobile menu.
6. **Modals don't fit.** Fixed-width modals overflowing on small screens.
7. **Images break layout.** Images without max-width extending beyond their containers.
8. **Padding doesn't scale.** Same 48px padding on desktop and mobile, cramping content.
- **320px** — Smallest phone (iPhone SE)
- **375px** — Standard phone (iPhone 12/13/14)
- **428px** — Large phone (iPhone Pro Max)
- **768px** — Tablet portrait (iPad)

## Quick Example

```tsx
/* BEFORE: Fixed 3 columns everywhere */
<div className="grid grid-cols-3 gap-6">

/* AFTER: Responsive columns */
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4 md:gap-6">
```
skilldb get web-polish-skills/Responsive RepairFull skill: 302 lines
Paste into your CLAUDE.md or agent config

Responsive Layout Repair

Core Philosophy

Responsive breakage is the most common defect in vibecoded websites because AI-generated code optimizes for the viewport it was shown during generation -- typically a desktop width. Mobile is an afterthought that manifests as horizontal scrollbars, unreadably small text, untappable buttons, and three-column grids that refuse to stack on a phone. These are not edge cases -- they affect the majority of real users, since mobile traffic exceeds desktop traffic for most websites.

The foundation of responsive repair is defensive CSS. A small set of global rules -- max-width: 100% on images, box-sizing: border-box on everything, font-size: 16px on inputs to prevent iOS zoom, and min-height: 44px on tap targets -- catches the majority of vibecode responsive failures before any component-level work begins. Apply these first, then address component-specific issues.

Consistent breakpoints are non-negotiable. When each component invents its own media query values, the site has no coherent responsive behavior -- elements collapse and rearrange at random viewport widths. A single set of breakpoints (matching Tailwind defaults or a custom system) applied everywhere creates predictable, testable responsive behavior.

You are a responsive design specialist who fixes the mobile and tablet breakage that vibecoded sites invariably ship with. When code is generated for a desktop viewport and mobile is an afterthought, you get horizontal scrollbars, text too small to read, buttons too small to tap, and layouts that crumble below 768px.

Common Vibecoded Responsive Failures

  1. Horizontal overflow. Fixed-width elements (tables, code blocks, images) wider than the viewport causing horizontal scrollbars.
  2. Grids that don't collapse. Three-column grids staying three columns on a 375px phone.
  3. Touch targets too small. 24px buttons and 16px-tall links that are impossible to tap.
  4. Text too small. Body text below 16px causing iOS zoom on form inputs.
  5. Navigation doesn't adapt. Desktop nav bar wrapping uglily instead of becoming a mobile menu.
  6. Modals don't fit. Fixed-width modals overflowing on small screens.
  7. Images break layout. Images without max-width extending beyond their containers.
  8. Padding doesn't scale. Same 48px padding on desktop and mobile, cramping content.

The Fix Process

Step 1: Set the Foundation

/* Prevent ALL overflow issues — this catches most vibecode breakage */
html {
  overflow-x: hidden;
}

/* Every image and media respects its container */
img, video, svg, iframe, canvas {
  max-width: 100%;
  height: auto;
}

/* Prevent iOS zoom on form inputs */
input, select, textarea {
  font-size: 16px; /* iOS zooms if font-size < 16px */
}

/* Minimum tap target size */
button, a, [role="button"], input[type="checkbox"], input[type="radio"] {
  min-height: 44px;
  min-width: 44px;
}

/* Box sizing everywhere */
*, *::before, *::after {
  box-sizing: border-box;
}

Step 2: Define Consistent Breakpoints

Use the same breakpoints everywhere. Don't invent per-component breakpoints.

/* Mobile-first breakpoints */
/* Default: 0-639px    (mobile) */
/* sm:      640-767px  (large phone / small tablet) */
/* md:      768-1023px (tablet) */
/* lg:      1024-1279px (small desktop) */
/* xl:      1280+px    (large desktop) */

/* In Tailwind these are default. In CSS: */
@media (min-width: 640px)  { /* sm */ }
@media (min-width: 768px)  { /* md */ }
@media (min-width: 1024px) { /* lg */ }
@media (min-width: 1280px) { /* xl */ }

Step 3: Fix Grids

/* BEFORE: Fixed 3 columns everywhere */
<div className="grid grid-cols-3 gap-6">

/* AFTER: Responsive columns */
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4 md:gap-6">

Common patterns:

1 col mobile → 2 col tablet → 3 col desktop:
  grid-cols-1 sm:grid-cols-2 lg:grid-cols-3

1 col mobile → 2 col desktop:
  grid-cols-1 md:grid-cols-2

Full width mobile → sidebar + content desktop:
  flex flex-col lg:flex-row

Stack mobile → inline desktop:
  flex flex-col sm:flex-row

Step 4: Fix Container Width

/* One max-width container used everywhere */
.container {
  width: 100%;
  max-width: 1280px;
  margin-left: auto;
  margin-right: auto;
  padding-left: 1rem;    /* 16px on mobile */
  padding-right: 1rem;
}

@media (min-width: 640px) {
  .container {
    padding-left: 1.5rem;  /* 24px on tablet */
    padding-right: 1.5rem;
  }
}

@media (min-width: 1024px) {
  .container {
    padding-left: 2rem;    /* 32px on desktop */
    padding-right: 2rem;
  }
}

Step 5: Fix Tables

Tables are the most common overflow offender:

/* Option 1: Horizontal scroll wrapper */
<div className="overflow-x-auto -mx-4 px-4 md:mx-0 md:px-0">
  <table className="min-w-[600px] w-full">
    {/* table content */}
  </table>
</div>

/* Option 2: Cards on mobile, table on desktop */
<div className="hidden md:block">
  <Table data={items} />
</div>
<div className="md:hidden space-y-3">
  {items.map(item => <MobileCard key={item.id} item={item} />)}
</div>

/* Option 3: Collapse columns on mobile */
<table>
  <thead>
    <tr>
      <th>Name</th>
      <th>Email</th>
      <th className="hidden md:table-cell">Phone</th>
      <th className="hidden lg:table-cell">Role</th>
      <th>Actions</th>
    </tr>
  </thead>
</table>

Step 6: Fix Navigation

/* Desktop: horizontal nav */
<nav className="hidden lg:flex items-center gap-6">
  {links.map(link => (
    <a key={link.href} href={link.href}>{link.label}</a>
  ))}
</nav>

/* Mobile: hamburger + slide-out or bottom sheet */
<button className="lg:hidden" onClick={() => setMenuOpen(true)}>
  <Menu className="h-6 w-6" />
</button>

{/* Mobile menu */}
{menuOpen && (
  <div className="fixed inset-0 z-50 lg:hidden">
    <div className="fixed inset-0 bg-black/50" onClick={() => setMenuOpen(false)} />
    <nav className="fixed inset-y-0 right-0 w-72 bg-white shadow-xl p-6">
      <button onClick={() => setMenuOpen(false)} className="mb-6">
        <X className="h-6 w-6" />
      </button>
      {links.map(link => (
        <a key={link.href} href={link.href} className="block py-3 text-lg">
          {link.label}
        </a>
      ))}
    </nav>
  </div>
)}

Step 7: Fix Modals on Mobile

/* Modal content should be full-width on mobile, centered on desktop */
<DialogContent className={cn(
  'w-full',
  // Mobile: full width with margins
  'mx-4 max-h-[85vh]',
  // Desktop: centered with max-width
  'md:mx-auto md:max-w-md'
)}>

Step 8: Fix Typography Scaling

/* Text that's too big on mobile */
.hero-title {
  font-size: 2rem;      /* 32px mobile */
}
@media (min-width: 768px) {
  .hero-title {
    font-size: 3rem;    /* 48px tablet */
  }
}
@media (min-width: 1024px) {
  .hero-title {
    font-size: 3.75rem; /* 60px desktop */
  }
}

/* Or use clamp for fluid sizing */
.hero-title {
  font-size: clamp(2rem, 1rem + 5vw, 3.75rem);
}

Step 9: Fix Spacing

/* Section padding that scales */
.section {
  padding-top: 3rem;     /* 48px mobile */
  padding-bottom: 3rem;
}
@media (min-width: 768px) {
  .section {
    padding-top: 5rem;   /* 80px tablet+ */
    padding-bottom: 5rem;
  }
}

/* Gap that scales */
.card-grid {
  gap: 1rem;             /* 16px mobile */
}
@media (min-width: 768px) {
  .card-grid {
    gap: 1.5rem;         /* 24px tablet+ */
  }
}

Testing Checklist

Test at these widths:

  • 320px — Smallest phone (iPhone SE)
  • 375px — Standard phone (iPhone 12/13/14)
  • 428px — Large phone (iPhone Pro Max)
  • 768px — Tablet portrait (iPad)
  • 1024px — Tablet landscape / small laptop
  • 1280px — Standard desktop
  • 1920px — Large desktop

At each width, verify:

  • No horizontal scrollbar
  • All text is readable (min 16px body)
  • All tap targets are at least 44px
  • Navigation works
  • Modals fit the screen
  • Images don't overflow
  • Tables don't break layout
  • Forms are usable

Anti-Patterns

  • Don't hide content on mobile that users need. Collapsing secondary info is fine; removing navigation items is not.
  • Don't use display: none to "fix" overflow. Find and fix the actual overflow source.
  • Don't use viewport units (vw/vh) for layout — they don't account for mobile browser chrome. Use dvh or percentages instead.
  • Don't set fixed heights on content areas. Content length varies; let heights be flexible.
  • Don't assume hover is available on mobile. Touch devices don't hover.

Install this skill directly: skilldb add web-polish-skills

Get CLI access →