npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

akshay-khapare-react-native-responsive-size

v1.0.6

Published

A production-ready React Native package for your app

Readme

React Native Responsive Size

NPM version MIT License

A production-ready React Native package for creating responsive UIs across all device sizes. This package provides a comprehensive, efficient API to handle responsive sizing, with built-in caching for performance optimization and full TypeScript support.

✨ Features

  • 🎯 Complete Responsive Solution: 15 functions covering all responsive design needs
  • 📱 Universal Device Support: Works seamlessly on phones, tablets, and all screen sizes
  • 🚀 Performance Optimized: Smart caching system with automatic memory management
  • 🔄 Auto Orientation Handling: Automatically adapts to orientation changes
  • 🛡️ Safe Area Ready: Built-in support for notches, status bars, and home indicators
  • 📊 Device Intelligence: Advanced device detection and categorization
  • 🎨 Automatic Style Processing: Transform entire style objects with one function
  • 🔒 TypeScript Native: Fully typed for complete developer safety
  • 🧹 Memory Safe: Automatic cleanup prevents memory leaks

📦 Installation

npm install akshay-khapare-react-native-responsive-size

Peer Dependencies

# These are likely already in your React Native project
npm install react react-native

🚀 Quick Start

import {
  scale,
  wp,
  hp,
  fs,
  spacing,
  radius,
  getSafeAreaTop,
  getSafeAreaBottom,
} from 'akshay-khapare-react-native-responsive-size';

const styles = StyleSheet.create({
  container: {
    width: wp(100), // 100% width
    height: hp(100), // 100% height
    paddingTop: getSafeAreaTop(), // Safe for notches
    padding: spacing(16), // Responsive padding
  },
  title: {
    fontSize: fs(24), // Responsive font
    marginBottom: spacing(12), // Responsive margin
  },
  button: {
    height: scale(44), // Responsive height
    borderRadius: radius(8), // Responsive radius
  },
});

📚 Quick Reference

| Function | Purpose | Best For | | -------------------------- | -------------------------- | --------------------------------- | | scale() | Main responsive scaling | Button heights, icons, borders | | wp() | Width percentage | Container widths, cards, columns | | hp() | Height percentage | Headers, modals, sections | | fs() | Font size with constraints | All text with min/max limits | | spacing() | Padding & margin | All spacing between elements | | radius() | Border radius | Rounded corners, circles | | getSafeAreaTop() | Top safe area | Header padding for notches | | getSafeAreaBottom() | Bottom safe area | Footer padding for home indicator | | getScreenDimensions() | Screen info | Layout calculations | | isTablet() | Tablet detection | Device-specific layouts | | getDeviceSize() | Device category | Granular responsive design | | responsiveSize() | Device-specific values | Different sizes per device type | | createResponsiveStyles() | Auto-process styles | Batch style transformation | | getCacheStats() | Performance monitoring | Debug & optimization | | cleanup() | Memory cleanup | App lifecycle management |


📖 Complete API Documentation

scale(size: number, useWidth?: boolean): number

Purpose: The main responsive function that scales any value proportionally.

Parameters:

  • size: Base size in pixels (designed for iPhone 12 Pro: 390x844)
  • useWidth: Optional. Use width for scaling instead of height

When to use:

  • Scaling button heights, image sizes, icon dimensions
  • Any UI element that should grow/shrink with screen size
  • When you want consistent proportions across all devices

Use Cases:

// ✅ Good use cases
scale(44); // Button height
scale(24); // Icon size
scale(100); // Image width/height
scale(2); // Border width
scale(50, true); // Scale based on width instead of height

// ❌ Avoid for
scale(16); // Font size (use fs() instead)
scale(20); // Padding (use spacing() instead)

Real Examples:

const styles = StyleSheet.create({
  avatar: {
    width: scale(60),
    height: scale(60),
    borderRadius: scale(30),
  },
  iconButton: {
    width: scale(44),
    height: scale(44),
  },
  progressBar: {
    height: scale(4),
    borderRadius: scale(2),
  },
});

wp(percentage: number): number

Purpose: Converts width percentage to pixels.

When to use:

  • Container widths, card widths, grid columns
  • When you think in percentages: "I want this 80% wide"
  • Creating responsive layouts without flexbox

Use Cases:

// ✅ Perfect for
wp(90); // Card that's 90% of screen width
wp(48); // Two columns with 48% each (+ 4% gap)
wp(100); // Full width container

// ❌ Don't use for
wp(1); // Very small values (use scale() instead)

Real Examples:

const styles = StyleSheet.create({
  card: {
    width: wp(90), // 90% width card
    alignSelf: 'center',
  },
  twoColumnItem: {
    width: wp(48), // Two items per row
  },
  threeColumnItem: {
    width: wp(30), // Three items per row
  },
  fullWidthHeader: {
    width: wp(100), // Full width
  },
});

hp(percentage: number): number

Purpose: Converts height percentage to pixels.

When to use:

  • Header heights, modal heights, section heights
  • When you want consistent height ratios
  • Creating layouts that adapt to screen height

Use Cases:

// ✅ Great for
hp(10); // Header that's 10% of screen height
hp(80); // Modal that takes 80% of screen
hp(25); // Four equal sections

// ❌ Avoid for
hp(1); // Very small values (use scale() instead)

Real Examples:

const styles = StyleSheet.create({
  header: {
    height: hp(12), // 12% screen height
  },
  heroSection: {
    height: hp(40), // 40% for hero image
  },
  bottomSheet: {
    height: hp(60), // 60% modal height
  },
  tabBar: {
    height: hp(8), // 8% for tab navigation
  },
});

fs(size: number, minSize?: number, maxSize?: number): number

Purpose: Responsive font size with minimum/maximum constraints for accessibility.

Parameters:

  • size: Base font size
  • minSize: Optional minimum font size
  • maxSize: Optional maximum font size

When to use:

  • All text elements where you want responsive sizing
  • When you need to ensure readability on all devices
  • Accessibility compliance with font size limits

Use Cases:

// ✅ Essential for
fs(16); // Body text
fs(24, 20, 28); // Heading with min/max limits
fs(12, 10); // Small text with minimum size
fs(32, undefined, 36); // Large title with max limit

// ❌ Don't use for
fs(44); // Large UI elements (use scale() instead)

Real Examples:

const styles = StyleSheet.create({
  heading: {
    fontSize: fs(28, 24, 32), // Never smaller than 24, max 32
  },
  bodyText: {
    fontSize: fs(16, 14), // Never smaller than 14
  },
  caption: {
    fontSize: fs(12, 10, 14), // Between 10-14
  },
  largeTitle: {
    fontSize: fs(34, 28, 40), // Large but limited
  },
});

spacing(size: number): number

Purpose: Responsive spacing for padding and margins.

When to use:

  • All padding and margin values
  • Consistent spacing system across your app
  • When elements need to breathe more/less on different screens

Use Cases:

// ✅ Perfect for
spacing(16); // Standard padding
spacing(8); // Small margins
spacing(24); // Large padding
spacing(4); // Tight spacing

// ❌ Avoid for
spacing(100); // Large distances (use scale() or hp()/wp())

Real Examples:

const styles = StyleSheet.create({
  container: {
    padding: spacing(16),
    marginBottom: spacing(20),
  },
  card: {
    margin: spacing(12),
    padding: spacing(16),
  },
  buttonGroup: {
    gap: spacing(8), // React Native 0.71+
  },
  section: {
    marginVertical: spacing(24),
    paddingHorizontal: spacing(16),
  },
});

radius(size: number): number

Purpose: Responsive border radius for consistent rounded corners.

When to use:

  • All border radius values
  • Buttons, cards, images, input fields
  • Maintaining visual consistency across screen sizes

Use Cases:

// ✅ Ideal for
radius(8); // Standard button radius
radius(12); // Card corners
radius(50); // Circular elements (with equal width/height)
radius(4); // Small input corners

// ❌ Avoid for
radius(0); // No radius (just use 0)

Real Examples:

const styles = StyleSheet.create({
  button: {
    borderRadius: radius(8),
  },
  card: {
    borderRadius: radius(12),
  },
  avatar: {
    width: scale(60),
    height: scale(60),
    borderRadius: radius(30), // Perfect circle
  },
  input: {
    borderRadius: radius(6),
  },
});

getSafeAreaTop(): number

Purpose: Get safe area top padding with accurate device detection for notches and status bars.

When to use:

  • Header components that need to avoid status bar/notch
  • Fixed positioned elements at the top
  • Full-screen modals or overlays

Device Handling:

  • iOS: Detects notch devices (iPhone X+) vs older devices
  • Android: Uses StatusBar.currentHeight with fallback
  • Landscape: Returns 0 on iOS landscape mode

Use Cases:

// ✅ Essential for
paddingTop: getSafeAreaTop(); // Headers
top: getSafeAreaTop(); // Fixed positioned elements
marginTop: getSafeAreaTop(); // Full-screen content

// ❌ Don't add to
// Normal screen content (StatusBar handles this automatically)

Real Examples:

const styles = StyleSheet.create({
  header: {
    paddingTop: getSafeAreaTop(),
    height: scale(60) + getSafeAreaTop(),
    backgroundColor: '#007AFF',
  },
  overlay: {
    position: 'absolute',
    top: getSafeAreaTop(),
    left: 0,
    right: 0,
  },
  fullScreenModal: {
    flex: 1,
    paddingTop: getSafeAreaTop(),
  },
});

getSafeAreaBottom(): number

Purpose: Get safe area bottom padding for home indicator on newer devices.

When to use:

  • Tab bars, bottom navigation
  • Fixed positioned elements at the bottom
  • Modals with bottom buttons
  • Any content that should clear the home indicator

Device Handling:

  • iPhone X+ Portrait: Returns 34 for home indicator
  • iPhone X+ Landscape: Returns 21 for side home indicator
  • Older devices: Returns 0
  • Android: Returns 0 (handled by system)

Use Cases:

// ✅ Critical for
paddingBottom: getSafeAreaBottom(); // Tab bars
bottom: getSafeAreaBottom(); // Fixed bottom elements
marginBottom: getSafeAreaBottom(); // Bottom content

// ❌ Don't add to
// Mid-screen content

Real Examples:

const styles = StyleSheet.create({
  tabBar: {
    paddingBottom: getSafeAreaBottom(),
    height: scale(60) + getSafeAreaBottom(),
  },
  bottomButton: {
    position: 'absolute',
    bottom: spacing(16) + getSafeAreaBottom(),
    left: spacing(16),
    right: spacing(16),
  },
  modalFooter: {
    paddingBottom: spacing(16) + getSafeAreaBottom(),
  },
});

getScreenDimensions(): object

Purpose: Get current screen dimensions with additional device characteristics.

Returns:

{
  width: number;
  height: number;
  isLandscape: boolean;
  aspectRatio: number;
  diagonal: number;
}

When to use:

  • Complex layout calculations
  • Custom responsive logic
  • Orientation-specific layouts
  • Performance monitoring

Use Cases:

// ✅ Useful for
const { width, isLandscape } = getScreenDimensions();
const { aspectRatio } = getScreenDimensions(); // Layout decisions
const { diagonal } = getScreenDimensions(); // Size categorization

// ❌ Avoid for
// Simple responsive sizing (use scale/wp/hp instead)

Real Examples:

import { getScreenDimensions } from 'akshay-khapare-react-native-responsive-size';

const CustomComponent = () => {
  const { width, height, isLandscape, aspectRatio } = getScreenDimensions();

  const dynamicStyle = {
    flexDirection: isLandscape ? 'row' : 'column',
    aspectRatio: aspectRatio > 2 ? 1.5 : 1.2, // Adjust for very tall screens
  };

  return <View style={dynamicStyle}>{/* content */}</View>;
};

isTablet(): boolean

Purpose: Enhanced tablet detection with multiple criteria for better accuracy.

Detection Logic:

  • Aspect ratio < 1.8 (tablets are less elongated)
  • Minimum dimension ≥ 600px
  • Diagonal size consideration
  • Multiple criteria prevent false positives

When to use:

  • Showing different layouts for tablets vs phones
  • Conditional rendering based on device type
  • Adjusting grid columns or navigation patterns

Use Cases:

// ✅ Perfect for
const columns = isTablet() ? 3 : 2; // Grid columns
const showSidebar = isTablet(); // Tablet-specific UI
const fontSize = isTablet() ? 18 : 16; // Different base sizes

// ❌ Avoid for
// Fine-grained responsive sizing (use scale() instead)

Real Examples:

const styles = StyleSheet.create({
  container: {
    flexDirection: isTablet() ? 'row' : 'column',
  },
  gridItem: {
    width: isTablet() ? wp(30) : wp(48), // 3 vs 2 columns
  },
  modal: {
    width: isTablet() ? wp(70) : wp(90), // Smaller modal on tablets
  },
});

getDeviceSize(): 'small' | 'medium' | 'large' | 'tablet'

Purpose: Device size category for more granular responsive design.

Categories:

  • 'small': Height < 700 (iPhone SE, etc.)
  • 'medium': Height 700-850 (iPhone 12, 13, etc.)
  • 'large': Height > 850 (iPhone 12 Pro Max, etc.)
  • 'tablet': Detected as tablet device

When to use:

  • Fine-tuned responsive design
  • Different layouts for device categories
  • Accessibility improvements for small screens

Use Cases:

// ✅ Excellent for
const deviceSize = getDeviceSize();
const padding = deviceSize === 'small' ? 12 : 16; // Less padding on small devices
const gridCols = deviceSize === 'tablet' ? 4 : 2; // More columns on tablets

// ❌ Don't use for
// Simple scaling (use scale() instead)

Real Examples:

const getResponsiveStyles = () => {
  const deviceSize = getDeviceSize();

  return StyleSheet.create({
    container: {
      padding: deviceSize === 'small' ? spacing(12) : spacing(16),
    },
    grid: {
      flexDirection: deviceSize === 'tablet' ? 'row' : 'column',
    },
    text: {
      fontSize: {
        small: fs(14),
        medium: fs(16),
        large: fs(18),
        tablet: fs(20),
      }[deviceSize],
    },
  });
};

responsiveSize(phoneSize: number, tabletSize?: number, deviceSizes?: object): number

Purpose: Responsive value with device-specific scaling and custom sizes per device type.

Parameters:

  • phoneSize: Base size for phones
  • tabletSize: Optional size for tablets (defaults to phoneSize * 0.8)
  • deviceSizes: Optional custom sizes for each device category

When to use:

  • When you need completely different values per device type
  • Complex responsive designs with device-specific requirements
  • Fine-tuning user experience per device category

Use Cases:

// ✅ Perfect for
responsiveSize(40); // Auto tablet adjustment
responsiveSize(40, 50); // Custom tablet size
responsiveSize(40, 50, { small: 35, large: 45 }); // Per-device customization

// ❌ Overkill for
// Simple proportional scaling (use scale() instead)

Real Examples:

const styles = StyleSheet.create({
  button: {
    height: responsiveSize(44, 52), // Taller buttons on tablets
  },
  avatar: {
    width: responsiveSize(60, 80, {
      small: 50, // Smaller on small phones
      medium: 60, // Standard size
      large: 70, // Larger on big phones
      tablet: 90, // Much larger on tablets
    }),
  },
  card: {
    padding: responsiveSize(16, 24, {
      small: 12, // Less padding on small screens
      tablet: 32, // More padding on tablets
    }),
  },
});

createResponsiveStyles<T>(styles: T): T

Purpose: Create responsive styles object with automatic processing of numeric values.

Auto-Processing Rules:

  • Properties with 'padding'/'margin'/'spacing' → spacing()
  • Properties with 'fontSize'/'size' → fs()
  • Properties with 'radius'/'border' → radius()
  • Properties with 'width'/'height' → scale()
  • Other numbers remain unchanged
  • Nested objects are processed recursively

When to use:

  • Processing entire style objects at once
  • Reducing repetitive function calls
  • Consistent responsive styling across components

Use Cases:

// ✅ Time-saving for
const baseStyles = {
  padding: 16, // → spacing(16)
  fontSize: 18, // → fs(18)
  borderRadius: 8, // → radius(8)
  width: 100, // → scale(100)
};

// ❌ Not needed for
// Single values or when you need specific functions

Real Examples:

// Input styles
const baseStyles = {
  container: {
    padding: 16,
    marginBottom: 20,
    borderRadius: 12,
  },
  title: {
    fontSize: 24,
    marginBottom: 8,
  },
  button: {
    height: 44,
    paddingHorizontal: 20,
    borderRadius: 8,
  },
};

// Auto-processed output
const responsiveStyles = createResponsiveStyles(baseStyles);
// Result:
// {
//   container: {
//     padding: spacing(16),
//     marginBottom: spacing(20),
//     borderRadius: radius(12),
//   },
//   title: {
//     fontSize: fs(24),
//     marginBottom: spacing(8),
//   },
//   button: {
//     height: scale(44),
//     paddingHorizontal: spacing(20),
//     borderRadius: radius(8),
//   },
// }

getCacheStats(): { size: number; maxSize: number }

Purpose: Get cache statistics for performance monitoring and debugging.

Returns:

  • size: Current number of cached values
  • maxSize: Maximum cache size (100 entries)

When to use:

  • Performance debugging
  • Memory usage monitoring
  • Development/testing phases
  • Optimization analysis

Use Cases:

// ✅ Useful for
const { size, maxSize } = getCacheStats();
console.log(`Cache: ${size}/${maxSize}`); // Monitor cache usage

// ❌ Don't use in
// Production unless for performance monitoring

Real Examples:

// Development helper
const PerformanceMonitor = () => {
  const [cacheStats, setCacheStats] = useState(getCacheStats());

  useEffect(() => {
    const interval = setInterval(() => {
      setCacheStats(getCacheStats());
    }, 5000);

    return () => clearInterval(interval);
  }, []);

  return __DEV__ ? (
    <Text>
      Cache: {cacheStats.size}/{cacheStats.maxSize}
    </Text>
  ) : null;
};

// Performance logging
const logPerformance = () => {
  const stats = getCacheStats();
  console.log('Responsive Size Cache Stats:', stats);

  if (stats.size === stats.maxSize) {
    console.warn('Cache is full - consider monitoring usage patterns');
  }
};

cleanup(): void

Purpose: Clean up resources and remove listeners to prevent memory leaks.

What it does:

  • Removes dimension change listeners
  • Clears the cache
  • Prevents memory leaks

When to use:

  • App unmounting/cleanup
  • Memory optimization
  • Testing teardown
  • Development hot reloads

Use Cases:

// ✅ Essential for
useEffect(() => {
  return () => cleanup(); // Component cleanup
}, []);

// App-level cleanup
AppState.addEventListener('change', (state) => {
  if (state === 'background') cleanup();
});

// ❌ Don't call
// During normal app usage (it will re-initialize automatically)

Real Examples:

// React component cleanup
const MyComponent = () => {
  useEffect(() => {
    return () => {
      // Cleanup when component unmounts
      cleanup();
    };
  }, []);

  return <View>{/* content */}</View>;
};

// App-level cleanup
const App = () => {
  useEffect(() => {
    const handleAppStateChange = (nextAppState: string) => {
      if (nextAppState === 'background') {
        cleanup(); // Clean up when app goes to background
      }
    };

    const subscription = AppState.addEventListener(
      'change',
      handleAppStateChange
    );

    return () => {
      subscription?.remove();
      cleanup(); // Final cleanup
    };
  }, []);

  return <NavigationContainer>{/* app content */}</NavigationContainer>;
};

// Test cleanup
afterEach(() => {
  cleanup(); // Clean up between tests
});

🎨 Complete Usage Examples

import React from 'react';
import { View, Text, TouchableOpacity, StyleSheet } from 'react-native';
import {
  scale,
  wp,
  hp,
  fs,
  spacing,
  radius,
  getSafeAreaTop,
  getSafeAreaBottom,
} from 'akshay-khapare-react-native-responsive-size';

const ResponsiveScreen = () => {
  return (
    <View style={styles.container}>
      <View style={styles.header}>
        <Text style={styles.headerTitle}>My App</Text>
      </View>

      <View style={styles.content}>
        <View style={styles.card}>
          <Text style={styles.cardTitle}>Welcome!</Text>
          <Text style={styles.cardSubtitle}>
            This layout adapts to all screen sizes
          </Text>

          <TouchableOpacity style={styles.button}>
            <Text style={styles.buttonText}>Get Started</Text>
          </TouchableOpacity>
        </View>
      </View>

      <View style={styles.footer}>
        <Text style={styles.footerText}>Footer Content</Text>
      </View>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#f5f5f5',
  },
  header: {
    height: scale(60) + getSafeAreaTop(),
    paddingTop: getSafeAreaTop(),
    backgroundColor: '#007AFF',
    justifyContent: 'center',
    alignItems: 'center',
  },
  headerTitle: {
    fontSize: fs(20),
    color: 'white',
    fontWeight: 'bold',
  },
  content: {
    flex: 1,
    padding: spacing(16),
    justifyContent: 'center',
  },
  card: {
    backgroundColor: 'white',
    padding: spacing(24),
    borderRadius: radius(12),
    width: wp(90),
    alignSelf: 'center',
    shadowColor: '#000',
    shadowOffset: { width: 0, height: scale(2) },
    shadowOpacity: 0.1,
    shadowRadius: radius(4),
    elevation: scale(3),
  },
  cardTitle: {
    fontSize: fs(28),
    fontWeight: 'bold',
    marginBottom: spacing(8),
    textAlign: 'center',
  },
  cardSubtitle: {
    fontSize: fs(16),
    color: '#666',
    textAlign: 'center',
    marginBottom: spacing(24),
  },
  button: {
    backgroundColor: '#007AFF',
    height: scale(48),
    borderRadius: radius(8),
    justifyContent: 'center',
    alignItems: 'center',
  },
  buttonText: {
    color: 'white',
    fontSize: fs(16),
    fontWeight: '600',
  },
  footer: {
    height: scale(50) + getSafeAreaBottom(),
    paddingBottom: getSafeAreaBottom(),
    backgroundColor: '#333',
    justifyContent: 'center',
    alignItems: 'center',
  },
  footerText: {
    color: 'white',
    fontSize: fs(14),
  },
});

export default ResponsiveScreen;
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
import {
  createResponsiveStyles,
  isTablet,
  getDeviceSize,
} from 'akshay-khapare-react-native-responsive-size';

const AutoProcessingExample = () => {
  // Define base styles with raw numbers
  const baseStyles = {
    container: {
      padding: 16,
      backgroundColor: '#fff',
    },
    header: {
      height: 60,
      marginBottom: 20,
      paddingHorizontal: 16,
      borderRadius: 8,
      backgroundColor: '#007AFF',
    },
    title: {
      fontSize: 24,
      marginBottom: 8,
    },
    subtitle: {
      fontSize: 16,
      marginBottom: 16,
    },
    card: {
      padding: 20,
      marginBottom: 16,
      borderRadius: 12,
      backgroundColor: '#f9f9f9',
    },
    button: {
      height: 44,
      paddingHorizontal: 20,
      borderRadius: 8,
      backgroundColor: '#007AFF',
    },
    buttonText: {
      fontSize: 16,
    },
  };

  // Auto-process all numeric values
  const styles = StyleSheet.create(createResponsiveStyles(baseStyles));

  return (
    <View style={styles.container}>
      <View style={styles.header}>
        <Text style={[styles.title, { color: 'white' }]}>
          Auto-Processed Layout
        </Text>
      </View>

      <Text style={styles.subtitle}>
        Device: {getDeviceSize()} {isTablet() && '(Tablet)'}
      </Text>

      <View style={styles.card}>
        <Text style={styles.subtitle}>
          All numeric values in styles are automatically processed:
        </Text>
        <Text>• padding → spacing()</Text>
        <Text>• fontSize → fs()</Text>
        <Text>• borderRadius → radius()</Text>
        <Text>• height → scale()</Text>
      </View>
    </View>
  );
};

export default AutoProcessingExample;
import React from 'react';
import { View, Text, ScrollView, StyleSheet } from 'react-native';
import {
  wp,
  hp,
  fs,
  spacing,
  radius,
  isTablet,
  getDeviceSize,
  responsiveSize,
  getSafeAreaTop,
} from 'akshay-khapare-react-native-responsive-size';

const DeviceSpecificLayout = () => {
  const deviceSize = getDeviceSize();
  const tablet = isTablet();

  // Device-specific configurations
  const gridColumns = tablet ? 3 : 2;
  const cardWidth = tablet ? wp(30) : wp(45);

  const renderCard = (title: string, index: number) => (
    <View key={index} style={[styles.card, { width: cardWidth }]}>
      <Text style={styles.cardTitle}>{title}</Text>
      <Text style={styles.cardText}>Optimized for {deviceSize} devices</Text>
    </View>
  );

  return (
    <ScrollView
      style={styles.container}
      contentContainerStyle={styles.scrollContent}
    >
      <View style={styles.header}>
        <Text style={styles.headerTitle}>Device-Specific Layout</Text>
        <Text style={styles.headerSubtitle}>
          Device: {deviceSize} {tablet && '(Tablet)'}
        </Text>
      </View>

      <View style={styles.infoCard}>
        <Text style={styles.infoTitle}>Responsive Configuration</Text>
        <Text style={styles.infoText}>Grid Columns: {gridColumns}</Text>
        <Text style={styles.infoText}>Card Width: {cardWidth}px</Text>
        <Text style={styles.infoText}>
          Button Height: {responsiveSize(44, 52)}px
        </Text>
      </View>

      <Text style={styles.sectionTitle}>Responsive Grid</Text>

      <View style={styles.grid}>
        {Array.from({ length: 6 }, (_, i) => renderCard(`Card ${i + 1}`, i))}
      </View>
    </ScrollView>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#f5f5f5',
  },
  scrollContent: {
    paddingTop: getSafeAreaTop(),
    padding: spacing(16),
  },
  header: {
    backgroundColor: '#007AFF',
    padding: spacing(20),
    borderRadius: radius(12),
    marginBottom: spacing(20),
  },
  headerTitle: {
    fontSize: fs(24),
    color: 'white',
    fontWeight: 'bold',
    textAlign: 'center',
  },
  headerSubtitle: {
    fontSize: fs(16),
    color: 'rgba(255,255,255,0.8)',
    textAlign: 'center',
    marginTop: spacing(8),
  },
  infoCard: {
    backgroundColor: 'white',
    padding: spacing(16),
    borderRadius: radius(8),
    marginBottom: spacing(20),
  },
  infoTitle: {
    fontSize: fs(18),
    fontWeight: 'bold',
    marginBottom: spacing(8),
  },
  infoText: {
    fontSize: fs(14),
    color: '#666',
    marginBottom: spacing(4),
  },
  sectionTitle: {
    fontSize: fs(20),
    fontWeight: 'bold',
    marginBottom: spacing(16),
  },
  grid: {
    flexDirection: 'row',
    flexWrap: 'wrap',
    justifyContent: 'space-between',
  },
  card: {
    backgroundColor: 'white',
    padding: spacing(16),
    borderRadius: radius(8),
    marginBottom: spacing(12),
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.1,
    shadowRadius: 4,
    elevation: 2,
  },
  cardTitle: {
    fontSize: fs(16),
    fontWeight: 'bold',
    marginBottom: spacing(8),
  },
  cardText: {
    fontSize: fs(12),
    color: '#666',
  },
});

export default DeviceSpecificLayout;

🎯 Best Practices

✅ Do's

  • Use specific functions: fs() for fonts, spacing() for padding/margin, radius() for borders
  • Implement safe areas: Always use getSafeAreaTop() and getSafeAreaBottom() for headers and footers
  • Test on multiple devices: Verify your layouts on different screen sizes
  • Cache-friendly patterns: Reuse the same values to benefit from caching
  • Device-specific optimizations: Use isTablet() and getDeviceSize() for tailored experiences

❌ Don'ts

  • Don't mix units: Avoid mixing responsive functions with fixed pixel values
  • Don't ignore safe areas: Never assume headers/footers work without safe area handling
  • Don't over-optimize: Start with basic functions before using advanced features
  • Don't forget cleanup: Call cleanup() when appropriate to prevent memory leaks
  • Don't cache bust unnecessarily: Avoid random values that prevent cache hits

🔧 Troubleshooting

Cause: Using fixed pixel values instead of responsive functions.

Solution:

// ❌ Wrong
const styles = StyleSheet.create({
  button: {
    height: 44, // Fixed pixels
    padding: 16, // Fixed pixels
  },
});

// ✅ Correct
const styles = StyleSheet.create({
  button: {
    height: scale(44), // Responsive
    padding: spacing(16), // Responsive
  },
});

Cause: Not using font size constraints or wrong base size.

Solution:

// ❌ Wrong
fontSize: scale(16), // Uses height scaling, not font scaling

// ✅ Correct
fontSize: fs(16, 14, 20), // Font scaling with min/max limits

Cause: Not accounting for safe areas.

Solution:

// ❌ Wrong
const styles = StyleSheet.create({
  header: {
    height: 60,
    backgroundColor: '#007AFF',
  },
});

// ✅ Correct
const styles = StyleSheet.create({
  header: {
    height: scale(60) + getSafeAreaTop(),
    paddingTop: getSafeAreaTop(),
    backgroundColor: '#007AFF',
  },
});

Cause: Cache misses due to dynamic values or cache is full.

Solution:

// Check cache performance
const stats = getCacheStats();
console.log('Cache usage:', stats);

// Ensure consistent values for better caching
const STANDARD_PADDING = 16;
const buttonPadding = spacing(STANDARD_PADDING); // Good for caching

// Clean up if needed
cleanup();

Cause: Using different base values instead of a consistent spacing system.

Solution:

// ✅ Create a spacing scale
const SPACING = {
  xs: 4,
  sm: 8,
  md: 16,
  lg: 24,
  xl: 32,
};

// Use consistently throughout the app
const styles = StyleSheet.create({
  container: {
    padding: spacing(SPACING.md),
    marginBottom: spacing(SPACING.lg),
  },
});

📄 License

MIT License - see LICENSE file for details.

🤝 Contributing

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

📞 Support


Made with ❤️ for the React Native community