responsive-mobile-first

Mobile-first responsive patterns with sticky headers, floating CTAs, accessible navigation, and touch-friendly interactions. Use when implementing responsive layouts, mobile navigation, or ensuring touch-friendly UI.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "responsive-mobile-first" with this command: npx skills add canatufkansu/claude-skills/canatufkansu-claude-skills-responsive-mobile-first

Responsive Mobile-First

Breakpoint Strategy

// Tailwind default breakpoints (mobile-first)
// sm: 640px
// md: 768px
// lg: 1024px
// xl: 1280px
// 2xl: 1536px

// Write base styles for mobile, add breakpoints for larger screens
<div className="
  px-4 md:px-6 lg:px-8        // Padding increases
  text-sm md:text-base         // Font size scales
  grid-cols-1 md:grid-cols-2   // Grid expands
">

Sticky Header

// components/layout/Header.tsx
'use client';

import { useState, useEffect } from 'react';
import { cn } from '@/lib/utils';

export function Header() {
  const [isScrolled, setIsScrolled] = useState(false);

  useEffect(() => {
    const handleScroll = () => setIsScrolled(window.scrollY > 10);
    window.addEventListener('scroll', handleScroll);
    return () => window.removeEventListener('scroll', handleScroll);
  }, []);

  return (
    <header
      className={cn(
        'fixed top-0 left-0 right-0 z-50 transition-all duration-300',
        isScrolled
          ? 'bg-background/95 backdrop-blur-sm shadow-sm'
          : 'bg-transparent'
      )}
    >
      <nav className="container mx-auto px-4 h-16 flex items-center justify-between">
        <Logo />
        
        {/* Desktop Navigation */}
        <div className="hidden md:flex items-center gap-6">
          <NavLinks />
          <Button>Book Now</Button>
        </div>
        
        {/* Mobile Menu Button */}
        <MobileMenuButton className="md:hidden" />
      </nav>
    </header>
  );
}

Mobile Navigation Drawer

'use client';

import { useState } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import { X, Menu } from 'lucide-react';

export function MobileNav() {
  const [isOpen, setIsOpen] = useState(false);

  return (
    <>
      <button
        onClick={() => setIsOpen(true)}
        className="md:hidden p-2"
        aria-label="Open menu"
      >
        <Menu className="w-6 h-6" />
      </button>

      <AnimatePresence>
        {isOpen && (
          <>
            {/* Backdrop */}
            <motion.div
              initial={{ opacity: 0 }}
              animate={{ opacity: 1 }}
              exit={{ opacity: 0 }}
              onClick={() => setIsOpen(false)}
              className="fixed inset-0 bg-black/50 z-50 md:hidden"
            />
            
            {/* Drawer */}
            <motion.div
              initial={{ x: '100%' }}
              animate={{ x: 0 }}
              exit={{ x: '100%' }}
              transition={{ type: 'tween', duration: 0.3 }}
              className="fixed top-0 right-0 bottom-0 w-80 bg-background z-50 md:hidden"
            >
              <div className="p-4 flex justify-end">
                <button
                  onClick={() => setIsOpen(false)}
                  className="p-2"
                  aria-label="Close menu"
                >
                  <X className="w-6 h-6" />
                </button>
              </div>
              
              <nav className="px-4 space-y-4">
                <NavLink href="/" onClick={() => setIsOpen(false)}>
                  Home
                </NavLink>
                <NavLink href="/services" onClick={() => setIsOpen(false)}>
                  Services
                </NavLink>
                {/* More links */}
              </nav>
              
              <div className="absolute bottom-8 left-4 right-4">
                <Button className="w-full" size="lg">
                  Book a Session
                </Button>
              </div>
            </motion.div>
          </>
        )}
      </AnimatePresence>
    </>
  );
}

Floating Mobile CTA

// components/FloatingCTA.tsx
'use client';

import { useState, useEffect } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import Link from 'next/link';
import { useLocale } from 'next-intl';

export function FloatingCTA() {
  const [isVisible, setIsVisible] = useState(false);
  const locale = useLocale();

  useEffect(() => {
    const handleScroll = () => {
      // Show after scrolling past hero
      setIsVisible(window.scrollY > 500);
    };
    
    window.addEventListener('scroll', handleScroll);
    return () => window.removeEventListener('scroll', handleScroll);
  }, []);

  return (
    <AnimatePresence>
      {isVisible && (
        <motion.div
          initial={{ y: 100, opacity: 0 }}
          animate={{ y: 0, opacity: 1 }}
          exit={{ y: 100, opacity: 0 }}
          className="fixed bottom-6 left-4 right-4 z-40 md:hidden"
        >
          <Link
            href={`/${locale}/book`}
            className="block w-full bg-primary text-primary-foreground text-center py-4 rounded-full font-medium shadow-lg"
          >
            Book a Session
          </Link>
        </motion.div>
      )}
    </AnimatePresence>
  );
}

Responsive Grid Patterns

// 1-2-3 column grid
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 md:gap-6">
  {items.map(item => <Card key={item.id} {...item} />)}
</div>

// Sidebar layout
<div className="flex flex-col lg:flex-row gap-8">
  <main className="flex-1">{/* Main content */}</main>
  <aside className="w-full lg:w-80">{/* Sidebar */}</aside>
</div>

// Hero with text/image
<div className="flex flex-col-reverse md:flex-row items-center gap-8">
  <div className="flex-1">{/* Text content */}</div>
  <div className="w-full md:w-1/2">{/* Image */}</div>
</div>

Touch-Friendly Targets

// Minimum 44x44px touch targets
<button className="min-h-[44px] min-w-[44px] p-3">
  <Icon className="w-5 h-5" />
</button>

// Adequate spacing between interactive elements
<div className="flex gap-3">
  <Button>Primary</Button>
  <Button variant="outline">Secondary</Button>
</div>

// Large tap areas for cards
<Link href={href} className="block p-4 md:p-6">
  <Card />
</Link>

Responsive Typography

// Heading scale
<h1 className="text-3xl md:text-4xl lg:text-5xl xl:text-6xl font-bold">
  Main Heading
</h1>

<h2 className="text-2xl md:text-3xl lg:text-4xl font-semibold">
  Section Heading
</h2>

// Body text
<p className="text-base md:text-lg leading-relaxed">
  Body content with comfortable reading line height.
</p>

// Small text
<span className="text-xs md:text-sm text-muted-foreground">
  Caption or meta text
</span>

Responsive Spacing

// Section padding
<section className="py-12 md:py-16 lg:py-24">

// Container with responsive padding
<div className="container mx-auto px-4 md:px-6 lg:px-8">

// Stack spacing
<div className="space-y-4 md:space-y-6 lg:space-y-8">

Hide/Show Utilities

// Show only on mobile
<div className="block md:hidden">Mobile only</div>

// Show only on desktop
<div className="hidden md:block">Desktop only</div>

// Different content per breakpoint
<span className="md:hidden">Menu</span>
<span className="hidden md:inline">Navigation</span>

Responsive Images

import Image from 'next/image';

// Full-width responsive image
<div className="relative aspect-video w-full">
  <Image
    src="/hero.jpg"
    alt="Hero"
    fill
    className="object-cover"
    sizes="100vw"
    priority
  />
</div>

// Responsive sizes attribute
<Image
  src="/service.jpg"
  alt="Service"
  fill
  sizes="(max-width: 768px) 100vw, (max-width: 1024px) 50vw, 33vw"
/>

Container Component

// components/shared/Container.tsx
import { cn } from '@/lib/utils';

interface ContainerProps {
  children: React.ReactNode;
  className?: string;
  size?: 'default' | 'narrow' | 'wide';
}

export function Container({ 
  children, 
  className,
  size = 'default' 
}: ContainerProps) {
  return (
    <div
      className={cn(
        'mx-auto px-4 md:px-6',
        {
          'max-w-7xl': size === 'default',
          'max-w-4xl': size === 'narrow',
          'max-w-screen-2xl': size === 'wide',
        },
        className
      )}
    >
      {children}
    </div>
  );
}

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

next-intl-i18n

No summary provided by upstream source.

Repository SourceNeeds Review
General

json-ld-schemas

No summary provided by upstream source.

Repository SourceNeeds Review
General

framer-motion-animations

No summary provided by upstream source.

Repository SourceNeeds Review