akshay-khapare-react-native-responsive-size
v1.0.6
Published
A production-ready React Native package for your app
Maintainers
Readme
React Native Responsive Size
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-sizePeer 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 sizeminSize: Optional minimum font sizemaxSize: 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 contentReal 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 phonestabletSize: 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 functionsReal 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 valuesmaxSize: 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 monitoringReal 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()andgetSafeAreaBottom()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()andgetDeviceSize()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 limitsCause: 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
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
📞 Support
- 📧 Email: [email protected]
- 🐛 Issues: GitHub Issues
- 📖 Documentation: GitHub Wiki
Made with ❤️ for the React Native community
