responsive
Use to make an existing desktop-oriented UI work on mobile and tablet, or to fix overflow, wrapping, clipping, or cramped layouts at narrow widths. Not for new UI, use ui for that.
SKILL.mdskills/responsive/SKILL.md
GitHubResponsive
Take a desktop layout and make it work at every width. Audit in this order: page shell, navigation, text and forms, overflow, then the component patterns.
Steps
- Look at the desktop layout. Find overflow, wrapping, clipping, cramped areas, desktop-only navigation, tables, forms, pagination, stat grids, and divider-separated layouts.
- Apply mobile-first classes and breakpoint-specific layout changes.
- Use container queries where a component's layout depends on the space it's given, not the viewport.
- Check mobile, tablet, and desktop.
- Run the project's format, lint, typecheck, and tests if it has them.
Page shell and breakpoints
- Every layout adapts from mobile to desktop. Use
sm:,md:,lg:and so on to change grid columns, spacing, font sizes, and visibility. - Multi-column desktop layouts, sidebars, secondary nav, filter panels, collapse to one column on small screens. A mobile menu, a disclosure, or another compact pattern. Never shrunken columns.
- Use
min-h-dvh,min-h-svh, ormin-h-lvh. Nevermin-h-screen.
Navigation and pagination
- Every app has a mobile navigation menu below
lg, whether the desktop nav is in a header or a sidebar. A dialog or disclosure panel with a hamburger. Hide header nav withhidden lg:flex, sidebar nav withhidden lg:block, and the mobile toggle and menu at desktop widths withlg:hidden. - Horizontal menus, tabs, tab bars, pill navs, never overflow their parent. Scroll horizontally when items don't fit.
- When pagination has both page numbers and previous and next, hide the page numbers on mobile.
Text, forms, and touch targets
- Body text, subheadings, form controls, and icons are larger on mobile and scale down at
sm:. Write the mobile size as the default and the desktop size withsm:.text-2xl/8 sm:text-xl/8,text-base/7 sm:text-sm/6,text-lg/6 sm:text-sm/6,size-5 sm:size-4,py-2.5 sm:py-1.5. This covers body text, subheadings, stat values, labels, badges, buttons, select and input padding, and icons. Not h1s. Page titles stay the same or get smaller on mobile. - Body and paragraph text is at least
text-base(16px) on mobile. Nevertext-xs.text-smonly atsm:or above, sotext-base/7 sm:text-sm/6, never a baretext-sm/6for body copy. - If a text input's font is under
16px, addmax-sm:text-base/{lh}to lift it to 16px on mobile. - Checkboxes, radios, and toggles are larger on mobile.
size-5 sm:size-4for checkboxes and radios,w-11 sm:w-9for toggles. - Small and icon buttons meet the 48x48px touch target. Make the button
relativeand add a direct child<span class="absolute top-1/2 left-1/2 size-[max(100%,3rem)] -translate-1/2 pointer-fine:hidden" aria-hidden="true" />when the visual button is smaller. - Never fix a cramped heading group by constraining the wrapper with
max-w-*ormax-lg:max-w-*. Constrain each text element withmax-w-[*ch].
Overflow and flexible sizing
- Add
min-w-0to any flex child that has to shrink below its content. Fluid content beside a fixed sidebar, truncated labels, a flexible input beside a fixed button. - Add
shrink-0to any flex child that must not compress. Icons, SVGs, images, logos, avatars, fixed-size controls. - Tables scroll horizontally when the columns won't fit. Wrap in an outer
overflow-x-auto whitespace-nowrapdiv with negative margins matching the container, and an innerinline-block min-w-full align-middlediv with matching horizontal padding. - Table headings never wrap.
whitespace-nowrapon every<th>.
Component patterns
- Use container queries,
@container, for anything whose layout depends on available space rather than the viewport. Dashboard widgets, feature cards, pricing tiers, testimonial grids. - Put the
@containerelement as close to the responsive content as you can. A direct wrapper around the items. Never a page-level container. - Dashboard widgets use container queries, not media queries. Truncate stat and metric card titles so they never wrap.
- Divider-separated grids get reconfigured at every breakpoint where the column count changes. Reset first and last item padding, drop vertical dividers when collapsing to one column, add horizontal dividers between rows.
- Wrapped logo clouds stay balanced at every breakpoint. Use a grid or layout that avoids an uneven last row like
5+1. - Pricing card emphasis uses breakpoint-scoped grid rows and columns. Below that breakpoint the cards stack normally.
- Image and screenshot border radius uses
min()with viewport units instead of a fixedrounded-*.rounded-[min(1vw,12px)].
Check
Narrow, medium, and desktop all work. Mobile navigation exists and desktop navigation is hidden below lg. Tables, tabs, pagination, form controls, stat grids, and divider grids all behave on a narrow screen.