mobile-responsiveness
hoodini/ai-agents-skills
Build responsive, mobile-first web applications with breakpoints, touch interactions, and adaptive layouts.
What is mobile-responsiveness?
This skill provides patterns for creating web applications that work seamlessly across mobile, tablet, and desktop devices. Use it when implementing responsive layouts, touch interactions, mobile navigation, or optimizing for various screen sizes.
- Define mobile-first CSS breakpoints for tablet (768px), desktop (1024px), and large screens (1280px+)
- Implement fluid typography using CSS clamp() for scalable text across viewport sizes
- Handle touch interactions including swipe detection with configurable distance thresholds
- Build collapsible mobile navigation with hamburger menus and backdrop overlays
- Account for device safe areas (notches, home indicators) using CSS env() variables
- Detect responsive breakpoints at runtime with useMediaQuery React hook
How to install mobile-responsiveness
npx skills add https://github.com/hoodini/ai-agents-skills --skill mobile-responsivenessHow to use mobile-responsiveness
- 1.Set the viewport meta tag in your HTML head with width=device-width and viewport-fit=cover
- 2.Choose a breakpoint strategy: use mobile-first CSS media queries (768px, 1024px, 1280px) or Tailwind utility classes (md:, lg:, xl:)
- 3.For typography, define fluid font sizes using CSS clamp() or Tailwind's responsive text utilities
- 4.Implement touch interactions by tracking touchStart and touchEnd positions, calculating swipe distance, and triggering callbacks
- 5.Create mobile navigation with hidden hamburger button (md:hidden) and fixed overlay menu that transitions based on state
- 6.Test across actual devices or browser DevTools device emulation to verify breakpoints and touch interactions
Use cases
- Creating a product listing page that displays as a single column on mobile, two columns on tablet, and three columns on desktop
- Building a mobile app with swipe-to-dismiss card interactions and touch-friendly navigation
- Implementing a header that collapses to a hamburger menu on screens under 768px width
- Designing fluid typography that scales smoothly from 16px on small phones to 20px on large desktops
- Adapting a bottom navigation bar to avoid overlap with iPhone home indicator using safe-area-inset-bottom
- Frontend developers building cross-device web applications
- React developers implementing responsive component libraries
- Mobile-first web designers translating designs to code
- Teams building progressive web apps (PWAs) for mobile and desktop
mobile-responsiveness FAQ
Mobile-first applies base styles for mobile, then uses min-width media queries to add complexity for larger screens. Desktop-first does the opposite with max-width queries. Mobile-first is recommended because it's simpler and encourages performance optimization.
Use CSS env(safe-area-inset-*) variables for padding and the viewport-fit=cover meta tag. For fixed bottom navigation, use padding-bottom: max(1rem, env(safe-area-inset-bottom)) to respect the home indicator.
Both work; Tailwind is faster for rapid development with utility classes (md:p-8, lg:text-4xl), while custom CSS media queries offer more control. Choose based on your project setup and team preference.
Use the useMediaQuery hook with window.matchMedia() to detect breakpoints at runtime. For example, useMediaQuery('(max-width: 767px)') returns true on mobile devices.
50 pixels is a common threshold that balances responsiveness with avoiding unintended swipes. Adjust based on your use case and user testing.
Full instructions (SKILL.md)
Source of truth, from hoodini/ai-agents-skills.
name: mobile-responsiveness description: Build responsive, mobile-first web applications. Use when implementing responsive layouts, touch interactions, mobile navigation, or optimizing for various screen sizes. Triggers on responsive design, mobile-first, breakpoints, touch events, viewport.
Mobile Responsiveness
Build responsive, mobile-first web applications.
Mobile-First Breakpoints
/* Mobile first - no media query needed for mobile base */
.container {
padding: 1rem;
}
/* Tablet */
@media (min-width: 768px) {
.container {
padding: 2rem;
}
}
/* Desktop */
@media (min-width: 1024px) {
.container {
padding: 3rem;
max-width: 1200px;
margin: 0 auto;
}
}
/* Large desktop */
@media (min-width: 1280px) {
.container {
max-width: 1400px;
}
}
Tailwind Breakpoints
<div className="
p-4 /* Mobile: padding 1rem */
md:p-8 /* Tablet 768px+: padding 2rem */
lg:p-12 /* Desktop 1024px+: padding 3rem */
xl:max-w-6xl /* Large 1280px+: max-width */
">
<h1 className="
text-2xl /* Mobile */
md:text-3xl /* Tablet */
lg:text-4xl /* Desktop */
">
Responsive Heading
</h1>
</div>
Fluid Typography
:root {
/* Fluid font size: 16px at 320px viewport, 20px at 1200px viewport */
--font-size-base: clamp(1rem, 0.9rem + 0.5vw, 1.25rem);
/* Fluid heading */
--font-size-h1: clamp(2rem, 1.5rem + 2.5vw, 4rem);
}
body {
font-size: var(--font-size-base);
}
h1 {
font-size: var(--font-size-h1);
}
Touch Interactions
import { useState } from 'react';
function SwipeableCard({ onSwipeLeft, onSwipeRight, children }) {
const [touchStart, setTouchStart] = useState<number | null>(null);
const [touchEnd, setTouchEnd] = useState<number | null>(null);
const minSwipeDistance = 50;
const onTouchStart = (e: React.TouchEvent) => {
setTouchEnd(null);
setTouchStart(e.targetTouches[0].clientX);
};
const onTouchMove = (e: React.TouchEvent) => {
setTouchEnd(e.targetTouches[0].clientX);
};
const onTouchEnd = () => {
if (!touchStart || !touchEnd) return;
const distance = touchStart - touchEnd;
const isLeftSwipe = distance > minSwipeDistance;
const isRightSwipe = distance < -minSwipeDistance;
if (isLeftSwipe) onSwipeLeft?.();
if (isRightSwipe) onSwipeRight?.();
};
return (
<div
onTouchStart={onTouchStart}
onTouchMove={onTouchMove}
onTouchEnd={onTouchEnd}
>
{children}
</div>
);
}
Mobile Navigation
import { useState } from 'react';
function MobileNav() {
const [isOpen, setIsOpen] = useState(false);
return (
<>
{/* Hamburger button - visible on mobile */}
<button
className="md:hidden p-2"
onClick={() => setIsOpen(!isOpen)}
aria-expanded={isOpen}
aria-label="Toggle menu"
>
<span className={`hamburger ${isOpen ? 'open' : ''}`} />
</button>
{/* Mobile menu */}
<nav
className={`
fixed inset-0 bg-white z-50 transform transition-transform
${isOpen ? 'translate-x-0' : '-translate-x-full'}
md:static md:translate-x-0 md:bg-transparent
`}
>
<ul className="flex flex-col md:flex-row gap-4 p-4 md:p-0">
<li><a href="/">Home</a></li>
<li><a href="/about">About</a></li>
<li><a href="/contact">Contact</a></li>
</ul>
</nav>
{/* Backdrop */}
{isOpen && (
<div
className="fixed inset-0 bg-black/50 z-40 md:hidden"
onClick={() => setIsOpen(false)}
/>
)}
</>
);
}
Safe Areas (Notch/Home Indicator)
/* Account for iPhone notch and home indicator */
.container {
padding-left: env(safe-area-inset-left);
padding-right: env(safe-area-inset-right);
padding-bottom: env(safe-area-inset-bottom);
}
/* Fixed bottom navigation */
.bottom-nav {
position: fixed;
bottom: 0;
left: 0;
right: 0;
padding-bottom: max(1rem, env(safe-area-inset-bottom));
}
Viewport Meta Tag
<meta
name="viewport"
content="width=device-width, initial-scale=1, viewport-fit=cover"
/>
useMediaQuery Hook
import { useState, useEffect } from 'react';
function useMediaQuery(query: string): boolean {
const [matches, setMatches] = useState(false);
useEffect(() => {
const media = window.matchMedia(query);
setMatches(media.matches);
const listener = (e: MediaQueryListEvent) => setMatches(e.matches);
media.addEventListener('change', listener);
return () => media.removeEventListener('change', listener);
}, [query]);
return matches;
}
// Usage
function Component() {
const isMobile = useMediaQuery('(max-width: 767px)');
const isTablet = useMediaQuery('(min-width: 768px) and (max-width: 1023px)');
const isDesktop = useMediaQuery('(min-width: 1024px)');
return isMobile ? <MobileView /> : <DesktopView />;
}
Resources
- Responsive Design: https://web.dev/learn/design/
- Mobile-First CSS: https://developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layout/Responsive_Design
- Viewport Units: https://developer.mozilla.org/en-US/docs/Web/CSS/length#viewport-percentage_lengths
Related skills
More from hoodini/ai-agents-skills and the wider catalog.

mongodb
Work with MongoDB databases using best practices for schemas, queries, and aggregation pipelines.

owasp-security
Implement OWASP Top 10 secure coding practices to prevent common web vulnerabilities.

github-trending
Fetch and display GitHub trending repositories and developers with web scraping or Search API.

tong-jincheng-perspective
Adopt Tong Jincheng's perspective: emotional authenticity and human insight for relationships, social dynamics, and personal growth.

graphify
Structural code index via AST—query symbols before searching, explore unfamiliar codebases faster.

preline-theme-generator
Generate, preview, save, or validate Preline theme CSS using the bundled local generator in this skill. Use when the user asks to create a new Preline theme, match a brand color, translate a mood into a theme, generate light and dark theme CSS, preview theme output without writing files, or review and fix generated theme tokens. Do not use for generic non-Preline CSS work or arbitrary command execution.