Skip to content
tailwind-capacitor logo

Tailwind CSS for Capacitor Apps

tailwind-capacitor

Guide to using Tailwind CSS in Capacitor mobile apps. Covers mobile-first design, touch targets, safe areas, dark mode, and performance optimization. Use this skill when users want to style Capacitor apps with Tailwind.

yeohj0710/wellnessbox0installs0stars

SKILL.md

Full skill instructions

Tailwind CSS for Capacitor Apps

Build beautiful mobile apps with Tailwind CSS and Capacitor.

When to Use This Skill

  • User is using Tailwind in Capacitor app
  • User asks about mobile styling
  • User needs responsive mobile design
  • User wants dark mode with Tailwind
  • User needs safe area handling

Getting Started

Installation

bun add -D tailwindcss postcss autoprefixer
bunx tailwindcss init -p

Configuration

// tailwind.config.js
/​** @type {import('tailwindcss').Config} */
export default {
  content: [
    './​index.html',
    './​src/​**/​*.{js,ts,jsx,tsx,vue,svelte}',
  ],
  theme: {
    extend: {
      // Mobile-first spacing
      spacing: {
        'safe-top': 'env(safe-area-inset-top)',
        'safe-bottom': 'env(safe-area-inset-bottom)',
        'safe-left': 'env(safe-area-inset-left)',
        'safe-right': 'env(safe-area-inset-right)',
      },
      // Minimum touch targets (44px)
      minHeight: {
        'touch': '44px',
      },
      minWidth: {
        'touch': '44px',
      },
    },
  },
  plugins: [],
};

Import Styles

/​* src/​index.css */
@tailwind base;
@tailwind components;
@tailwind utilities;

/​* Mobile-specific base styles */
@layer base {
  html {
    /​* Prevent text size adjustment on orientation change */
    -webkit-text-size-adjust: 100%;
    /​* Smooth scrolling */
    scroll-behavior: smooth;
    /​* Prevent pull-to-refresh on overscroll */
    overscroll-behavior: none;
  }

  body {
    /​* Prevent text selection on long press */
    -webkit-user-select: none;
    user-select: none;
    /​* Disable callout on long press */
    -webkit-touch-callout: none;
    /​* Prevent elastic scrolling on iOS */
    position: fixed;
    width: 100%;
    height: 100%;
    overflow: hidden;
  }

  /​* Enable text selection in inputs */
  input, textarea {
    -webkit-user-select: text;
    user-select: text;
  }
}

Safe Area Handling

Utility Classes

// tailwind.config.js
theme: {
  extend: {
    padding: {
      'safe': 'env(safe-area-inset-bottom)',
      'safe-t': 'env(safe-area-inset-top)',
      'safe-b': 'env(safe-area-inset-bottom)',
      'safe-l': 'env(safe-area-inset-left)',
      'safe-r': 'env(safe-area-inset-right)',
    },
    margin: {
      'safe': 'env(safe-area-inset-bottom)',
      'safe-t': 'env(safe-area-inset-top)',
      'safe-b': 'env(safe-area-inset-bottom)',
    },
  },
},

Usage in Components

// Header with safe area
function Header() {
  return (
    <header className="
      fixed top-0 left-0 right-0
      pt-safe-t  /​* Padding for notch */
      bg-white dark:bg-gray-900
      border-b border-gray-200
    ">
      <div className="px-4 h-14 flex items-center">
        <h1 className="font-semibold">App Title</​h1>
      </​div>
    </​header>
  );
}

// Footer with safe area
function Footer() {
  return (
    <footer className="
      fixed bottom-0 left-0 right-0
      pb-safe-b  /​* Padding for home indicator */
      bg-white dark:bg-gray-900
      border-t border-gray-200
    ">
      <div className="px-4 h-14 flex items-center justify-around">
        <button className="min-h-touch min-w-touch">Home</​button>
        <button className="min-h-touch min-w-touch">Search</​button>
        <button className="min-h-touch min-w-touch">Profile</​button>
      </​div>
    </​footer>
  );
}

// Main content
function Main() {
  return (
    <main className="
      pt-safe-t  /​* Account for header + notch */
      pb-safe-b  /​* Account for footer + home indicator */
      h-screen
      overflow-y-auto
      overscroll-none
    ">
      {/​* Content */​}
    </​main>
  );
}

Touch-Friendly Design

Minimum Touch Targets

// Apple HIG recommends 44x44pt minimum
function TouchableButton() {
  return (
    <button className="
      min-h-[44px] min-w-[44px]
      px-4 py-3
      flex items-center justify-center
      active:bg-gray-100
      rounded-lg
    ">
      Tap Me
    </​button>
  );
}

// Icon button with proper touch target
function IconButton() {
  return (
    <button className="
      h-11 w-11  /​* 44px */
      flex items-center justify-center
      rounded-full
      active:bg-gray-100
    ">
      <svg className="w-6 h-6" />  {/​* Icon smaller than touch area */​}
    </​button>
  );
}

Touch Feedback

/​* Add to index.css */
@layer utilities {
  .touch-feedback {
    @apply transition-colors duration-75;
  }

  .touch-feedback:active {
    @apply bg-black/​5 dark:bg-white/​5;
  }
}
<button className="touch-feedback p-4 rounded-lg">
  With Feedback
</​button>

Disable Hover on Touch

// tailwind.config.js
module.exports = {
  future: {
    hoverOnlyWhenSupported: true, // Disables hover on touch devices
  },
};

Or use media query:

@media (hover: hover) {
  .hover-only:hover {
    @apply bg-gray-100;
  }
}

Dark Mode

System Dark Mode

// tailwind.config.js
module.exports = {
  darkMode: 'media', // or 'class' for manual control
};

Manual Dark Mode

// tailwind.config.js
module.exports = {
  darkMode: 'class',
};
// theme.ts
import { Preferences } from '@capacitor/​preferences';

type Theme = 'light' | 'dark' | 'system';

async function setTheme(theme: Theme) {
  await Preferences.set({ key: 'theme', value: theme });

  if (theme === 'system') {
    const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
    document.documentElement.classList.toggle('dark', prefersDark);
  } else {
    document.documentElement.classList.toggle('dark', theme === 'dark');
  }
}

// Listen for system changes
window.matchMedia('(prefers-color-scheme: dark)')
  .addEventListener('change', (e) => {
    const theme = await Preferences.get({ key: 'theme' });
    if (theme.value === 'system') {
      document.documentElement.classList.toggle('dark', e.matches);
    }
  });

Dark Mode Components

function Card() {
  return (
    <div className="
      bg-white dark:bg-gray-800
      border border-gray-200 dark:border-gray-700
      rounded-xl
      shadow-sm dark:shadow-none
    ">
      <h3 className="text-gray-900 dark:text-white">
        Card Title
      </​h3>
      <p className="text-gray-600 dark:text-gray-400">
        Card content
      </​p>
    </​div>
  );
}

Mobile Patterns

Pull to Refresh Container

function PullToRefresh({ onRefresh, children }) {
  return (
    <div className="
      h-full
      overflow-y-auto
      overscroll-contain
      touch-pan-y
    ">
      {children}
    </​div>
  );
}

Bottom Sheet

function BottomSheet({ isOpen, onClose, children }) {
  return (
    <>
      {/​* Backdrop */​}
      <div
        className={`
          fixed inset-0
          bg-black/​50
          transition-opacity duration-300
          ${isOpen ? 'opacity-100' : 'opacity-0 pointer-events-none'}
        `}
        onClick={onClose}
      />

      {/​* Sheet */​}
      <div
        className={`
          fixed left-0 right-0 bottom-0
          bg-white dark:bg-gray-900
          rounded-t-2xl
          pb-safe-b
          transition-transform duration-300 ease-out
          ${isOpen ? 'translate-y-0' : 'translate-y-full'}
        `}
      >
        {/​* Handle */​}
        <div className="flex justify-center py-2">
          <div className="w-10 h-1 bg-gray-300 rounded-full" />
        </​div>

        {children}
      </​div>
    </>
  );
}

Swipe Actions

function SwipeableItem({ children, onDelete }) {
  return (
    <div className="relative overflow-hidden">
      {/​* Background action */​}
      <div className="
        absolute inset-y-0 right-0
        flex items-center
        bg-red-500
        px-4
      ">
        <span className="text-white">Delete</​span>
      </​div>

      {/​* Foreground content */​}
      <div className="
        relative
        bg-white dark:bg-gray-800
        transform transition-transform
        active:cursor-grabbing
      ">
        {children}
      </​div>
    </​div>
  );
}

Fixed Header with Blur

function BlurHeader() {
  return (
    <header className="
      fixed top-0 left-0 right-0
      pt-safe-t
      bg-white/​80 dark:bg-gray-900/​80
      backdrop-blur-lg
      border-b border-gray-200/​50
      z-50
    ">
      <div className="h-14 px-4 flex items-center">
        <h1 className="font-semibold">Title</​h1>
      </​div>
    </​header>
  );
}

Performance Optimization

Reduce Bundle Size

// tailwind.config.js
module.exports = {
  content: [/​* ... */],
  // Only include used utilities
  safelist: [], // Add dynamic classes here if needed
};

GPU Acceleration

// Use transform for animations (GPU accelerated)
<div className="
  transform transition-transform duration-200
  hover:scale-105
  will-change-transform
">
  Animated Element
</​div>

Avoid Layout Thrashing

// BAD: Causes reflow
<div className="w-full h-auto">

// GOOD: Fixed dimensions
<div className="w-full h-48">

Component Examples

Mobile List Item

function ListItem({ title, subtitle, image, onClick }) {
  return (
    <button
      onClick={onClick}
      className="
        w-full
        flex items-center gap-4
        px-4 py-3
        min-h-[60px]
        active:bg-gray-50 dark:active:bg-gray-800
        text-left
      "
    >
      {image && (
        <img
          src={image}
          className="w-12 h-12 rounded-full object-cover"
          alt=""
        />
      )}
      <div className="flex-1 min-w-0">
        <p className="font-medium text-gray-900 dark:text-white truncate">
          {title}
        </​p>
        {subtitle && (
          <p className="text-sm text-gray-500 truncate">
            {subtitle}
          </​p>
        )}
      </​div>
      <svg className="w-5 h-5 text-gray-400" />
    </​button>
  );
}

Mobile Button

function MobileButton({ children, variant = 'primary', ...props }) {
  const variants = {
    primary: 'bg-blue-500 text-white active:bg-blue-600',
    secondary: 'bg-gray-100 text-gray-900 active:bg-gray-200',
    danger: 'bg-red-500 text-white active:bg-red-600',
  };

  return (
    <button
      className={`
        w-full
        min-h-[48px]
        px-6 py-3
        font-semibold
        rounded-xl
        transition-colors duration-75
        disabled:opacity-50
        ${variants[variant]}
      `}
      {...props}
    >
      {children}
    </​button>
  );
}

Mobile Input

function MobileInput({ label, error, ...props }) {
  return (
    <label className="block">
      {label && (
        <span className="text-sm font-medium text-gray-700 dark:text-gray-300 mb-1 block">
          {label}
        </​span>
      )}
      <input
        className={`
          w-full
          px-4 py-3
          text-base  /​* Prevents iOS zoom */
          bg-gray-50 dark:bg-gray-800
          border rounded-xl
          placeholder-gray-400
          focus:outline-none focus:ring-2 focus:ring-blue-500
          ${error
            ? 'border-red-500'
            : 'border-gray-200 dark:border-gray-700'
          }
        `}
        {...props}
      />
      {error && (
        <span className="text-sm text-red-500 mt-1 block">{error}</​span>
      )}
    </​label>
  );
}

Resources

More skills from yeohj0710

capacitor-testing logo
yeohj0710/wellnessbox

capacitor-testing

Complete testing guide for Capacitor apps covering unit tests, integration tests, E2E tests, and native testing. Includes Jest, Vitest, Playwright, Appium, and native testing frameworks. Use this skill when users need to test their mobile apps.

0 0
View
vercel-composition-patterns logo
yeohj0710/wellnessbox

vercel-composition-patterns

Composition patterns for building flexible, maintainable React components. Avoid boolean prop proliferation by using compound components, lifting state, and composing internals. These patterns make codebases easier for both humans and AI agents to work with as they scale.

0 0
View

Postgres performance optimization and best practices from Supabase. Use this skill when writing, reviewing, or optimizing Postgres queries, schema designs, or database configurations.

0 0
View
next-upgrade logo
yeohj0710/wellnessbox

next-upgrade

Upgrade Next.js to the latest version following official migration guides and codemods

0 0
View
capacitor-deep-linking logo
yeohj0710/wellnessbox

capacitor-deep-linking

Complete guide to implementing deep links and universal links in Capacitor apps. Covers iOS Universal Links, Android App Links, custom URL schemes, and navigation handling. Use this skill when users need to open their app from links.

0 0
View
vercel-deploy logo
yeohj0710/wellnessbox

vercel-deploy

Deploy applications and websites to Vercel. Use when the user requests deployment actions like "deploy my app", "deploy and give me the link", "push this live", or "create a preview deployment".

0 0
View
capacitor-keyboard logo
yeohj0710/wellnessbox

capacitor-keyboard

Guide to handling keyboard in Capacitor apps including visibility detection, accessory bar, scroll behavior, and input focus. Use this skill when users have keyboard-related issues.

0 0
View
frontend-design logo
yeohj0710/wellnessbox

frontend-design

Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, artifacts, posters, or applications (examples include websites, landing pages, dashboards, React components, HTML/CSS layouts, or when styling/beaut...

0 0
View
ios-android-logs logo
yeohj0710/wellnessbox

ios-android-logs

Guide to accessing device logs on iOS and Android for Capacitor apps. Covers command-line tools, GUI applications, filtering, and real-time streaming. Use this skill when users need to view device logs for debugging.

0 0
View
vercel-react-native-skills logo
yeohj0710/wellnessbox

vercel-react-native-skills

Comprehensive best practices for React Native and Expo applications. Contains rules across multiple categories covering performance, animations, UI patterns, and platform-specific optimizations.

0 0
View
capacitor-app-store logo
yeohj0710/wellnessbox

capacitor-app-store

Complete guide to publishing Capacitor apps to Apple App Store and Google Play Store. Covers app preparation, screenshots, metadata, review guidelines, and submission process. Use this skill when users are ready to publish their app.

0 0
View
develop-ai-functions-example logo
yeohj0710/wellnessbox

develop-ai-functions-example

Develop examples for AI SDK functions. Use when creating, running, or modifying examples under examples/ai-functions/src to validate provider support, demonstrate features, or create test fixtures.

0 0
View

Popular AI tools

Kaiber logo
Video

Kaiber

Generate, edit, and beat-sync AI video with leading models in one workspace.

Paid
View
Vimcal logo
Productivity

Vimcal

The world's fastest calendar for remote work

Free
View

Transform Your Design with AI Designer by ImgCreator.ai

Freemium
View
Akool AI logo
Content & writing

Akool AI

Revolutionizing Video Production with AI-Powered Creativity

Paid
View

Extend an image past the frame and let AI fill the new aspect ratio.

Freemium
View
StarByFace logo
Security

StarByFace

Discover your celebrity doppelgänger with StarByFace!

Free
View
C

ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.

Freemium
View
Opus Clip logo
Coding & apps

Opus Clip

Opus.ai: Revolutionize Your Web Experience

Free
View