Appendix D
🔄 Web to Native Quick Reference
Mapping HTML, CSS, and Web APIs to React Native equivalents
HTML → React Native Components
📦 Container Elements
| HTML | React Native | Notes |
|---|---|---|
<div> |
<View> |
Universal container |
<section> |
<View> |
No semantic difference |
<article> |
<View> |
No semantic difference |
<header> |
<View> |
Use accessibility props |
<footer> |
<View> |
Use accessibility props |
<main> |
<View> |
Usually the root View |
<nav> |
<View> + Navigation |
Use Expo Router / React Navigation |
<span> |
<Text> (nested) |
For inline text styling |
📝 Text Elements
| HTML | React Native | Notes |
|---|---|---|
<p> |
<Text> |
All text in Text component |
<h1>-<h6> |
<Text style={styles.h1}> |
Style manually, use accessibilityRole="header" |
<strong>, <b> |
<Text style={{fontWeight: 'bold'}}> |
Nested Text for inline |
<em>, <i> |
<Text style={{fontStyle: 'italic'}}> |
Nested Text for inline |
<a> |
<Link> or <Text onPress> |
Expo Router Link or Linking API |
<br> |
{'\n'} |
Newline character in Text |
<hr> |
<View style={styles.divider} /> |
Style as line |
// Heading styles example
const styles = StyleSheet.create({
h1: { fontSize: 32, fontWeight: 'bold', marginBottom: 16 },
h2: { fontSize: 24, fontWeight: 'bold', marginBottom: 12 },
h3: { fontSize: 20, fontWeight: '600', marginBottom: 8 },
divider: { height: 1, backgroundColor: '#ccc', marginVertical: 16 },
});
🖼️ Media Elements
| HTML | React Native | Notes |
|---|---|---|
<img> |
<Image> |
Remote images need dimensions |
<video> |
<Video> from expo-av |
expo-av package |
<audio> |
Audio from expo-av |
expo-av package |
<svg> |
<Svg> |
react-native-svg |
<canvas> |
<Canvas> |
@shopify/react-native-skia |
<iframe> |
<WebView> |
react-native-webview |
📋 List Elements
| HTML | React Native | Notes |
|---|---|---|
<ul>, <ol> |
<FlatList> or <View> |
FlatList for long lists |
<li> |
<View> + <Text> |
Add bullet/number manually |
<dl>, <dt>, <dd> |
<View> + <Text> |
Style manually |
// Bullet list example
const BulletList = ({ items }) => (
<View>
{items.map((item, index) => (
<View key={index} style={styles.listItem}>
<Text style={styles.bullet}>•</Text>
<Text style={styles.itemText}>{item}</Text>
</View>
))}
</View>
);
// Numbered list example
const NumberedList = ({ items }) => (
<View>
{items.map((item, index) => (
<View key={index} style={styles.listItem}>
<Text style={styles.number}>{index + 1}.</Text>
<Text style={styles.itemText}>{item}</Text>
</View>
))}
</View>
);
📝 Form Elements
| HTML | React Native | Notes |
|---|---|---|
<form> |
<View> |
No form element, handle submit manually |
<input type="text"> |
<TextInput> |
Use keyboardType prop |
<input type="password"> |
<TextInput secureTextEntry> |
secureTextEntry prop |
<input type="email"> |
<TextInput keyboardType="email-address"> |
Shows @ on keyboard |
<input type="number"> |
<TextInput keyboardType="numeric"> |
Number pad keyboard |
<textarea> |
<TextInput multiline> |
multiline prop |
<select> |
Picker / Modal | @react-native-picker/picker or custom |
<input type="checkbox"> |
<Switch> or custom |
expo-checkbox for actual checkbox |
<input type="radio"> |
Custom component | Build with Pressable + View |
<button> |
<Pressable> or <Button> |
Pressable more flexible |
<label> |
<Text> |
Use accessibilityLabel on input |
👆 Interactive Elements
| HTML | React Native | Notes |
|---|---|---|
<button> |
<Pressable> |
Recommended for custom buttons |
<a href> |
<Link> / Linking.openURL |
Expo Router Link for internal |
<details>/<summary> |
Custom accordion | Build with state + Animated |
<dialog> |
<Modal> |
Built-in Modal component |
CSS → StyleSheet
📐 Box Model
| CSS | React Native | Notes |
|---|---|---|
width: 100px |
width: 100 |
Numbers are density-independent pixels |
width: 50% |
width: '50%' |
Strings for percentages |
margin: 10px 20px |
marginVertical: 10, marginHorizontal: 20 |
No shorthand |
padding: 10px |
padding: 10 |
Single value works |
border: 1px solid black |
borderWidth: 1, borderColor: 'black' |
No shorthand, no border-style |
border-radius: 8px |
borderRadius: 8 |
Same |
box-sizing |
N/A | Always border-box |
🎨 Colors & Background
| CSS | React Native | Notes |
|---|---|---|
color: red |
color: 'red' |
Named colors work |
color: #ff0000 |
color: '#ff0000' |
Hex colors work |
color: rgb(255,0,0) |
color: 'rgb(255,0,0)' |
RGB works |
color: rgba(255,0,0,0.5) |
color: 'rgba(255,0,0,0.5)' |
RGBA works |
background-color |
backgroundColor |
camelCase |
background-image |
<ImageBackground> |
Use ImageBackground component |
linear-gradient |
<LinearGradient> |
expo-linear-gradient |
opacity: 0.5 |
opacity: 0.5 |
Same |
✏️ Typography
| CSS | React Native | Notes |
|---|---|---|
font-size: 16px |
fontSize: 16 |
Number only |
font-weight: bold |
fontWeight: 'bold' |
Or '100'-'900' |
font-style: italic |
fontStyle: 'italic' |
Same |
font-family: Arial |
fontFamily: 'Arial' |
Must be installed/loaded |
line-height: 24px |
lineHeight: 24 |
Number only |
text-align: center |
textAlign: 'center' |
Same values |
text-decoration: underline |
textDecorationLine: 'underline' |
Different property name |
text-transform: uppercase |
textTransform: 'uppercase' |
Same |
letter-spacing: 2px |
letterSpacing: 2 |
Number only |
🚫 Not Supported in React Native
float,clear- Use Flexbox insteaddisplay: inline,display: block- Only flex, noneposition: fixed- Use absolute with Dimensionsbackground-image- Use ImageBackground componentcalc()- Calculate in JavaScriptvar(), CSS variables - Use JS constants:hover,:focus- Use Pressable state@mediaqueries - Use Dimensions API or useWindowDimensionstransition,animation- Use Animated API or Reanimatedbox-shadow(Android) - Use elevation or react-native-shadowcursor- Not applicable to touch- Pseudo-elements (
::before,::after) - Create actual components
Layout Differences
📏 Flexbox Defaults
| Property | CSS Default | React Native Default |
|---|---|---|
flexDirection |
row |
column |
alignContent |
stretch |
flex-start |
flexShrink |
1 |
0 |
// Web-like row layout
<View style={{ flexDirection: 'row' }}>
<View style={{ flex: 1 }} />
<View style={{ flex: 1 }} />
</View>
// RN default column layout
<View>
<View /> {/* Stacks vertically */}
<View />
</View>
📱 Responsive Design
// CSS media query equivalent
import { useWindowDimensions } from 'react-native';
function ResponsiveComponent() {
const { width, height } = useWindowDimensions();
const isTablet = width >= 768;
const isLandscape = width > height;
return (
<View style={[
styles.container,
isTablet && styles.tabletContainer,
isLandscape && styles.landscapeContainer,
]}>
{/* Content */}
</View>
);
}
// Or use Platform
import { Platform } from 'react-native';
const styles = StyleSheet.create({
container: {
padding: Platform.select({
ios: 20,
android: 16,
}),
},
});
Events Mapping
🖱️ Mouse/Touch Events
| Web Event | React Native | Notes |
|---|---|---|
onClick |
onPress |
On Pressable, TouchableOpacity |
onMouseDown |
onPressIn |
Touch start |
onMouseUp |
onPressOut |
Touch end |
onLongClick |
onLongPress |
Press and hold |
onMouseEnter/Leave |
N/A | No hover on touch devices |
onScroll |
onScroll |
On ScrollView/FlatList |
⌨️ Input Events
| Web Event | React Native | Notes |
|---|---|---|
onChange |
onChangeText |
Receives string directly |
onInput |
onChangeText |
Same as onChange in RN |
onFocus |
onFocus |
Same |
onBlur |
onBlur |
Same |
onSubmit (form) |
onSubmitEditing |
On TextInput return key |
onKeyDown |
onKeyPress |
Limited support |
Web APIs → React Native/Expo
🌐 Browser APIs
| Web API | React Native / Expo |
|---|---|
fetch() |
fetch() - Built-in |
localStorage |
AsyncStorage / expo-secure-store |
sessionStorage |
In-memory state / Context |
window.location |
expo-linking / Expo Router |
window.open() |
Linking.openURL() |
history.push() |
router.push() (Expo Router) |
history.back() |
router.back() |
alert() |
Alert.alert() |
confirm() |
Alert.alert() with buttons |
prompt() |
Custom Modal with TextInput |
console.log() |
console.log() - Same |
setTimeout/setInterval |
Same - Built-in |
📍 Device APIs
| Web API | Expo Package |
|---|---|
navigator.geolocation |
expo-location |
navigator.mediaDevices (camera) |
expo-camera / expo-image-picker |
Notification API |
expo-notifications |
Clipboard API |
expo-clipboard |
Vibration API |
expo-haptics |
DeviceOrientation API |
expo-sensors |
Battery API |
expo-battery |
Network Information API |
expo-network |
Share API |
expo-sharing / Share |
File API |
expo-file-system |
Common Patterns
🔗 Link to External URL
// Web
<a href="https://google.com" target="_blank">Open Google</a>
// React Native
import { Linking, Pressable, Text } from 'react-native';
<Pressable onPress={() => Linking.openURL('https://google.com')}>
<Text style={{ color: 'blue' }}>Open Google</Text>
</Pressable>
🖼️ Background Image
// Web CSS
.hero {
background-image: url('hero.jpg');
background-size: cover;
}
// React Native
import { ImageBackground } from 'react-native';
<ImageBackground
source={require('./hero.jpg')}
style={styles.hero}
resizeMode="cover"
>
<Text>Content over image</Text>
</ImageBackground>
📜 Scrollable Page
// Web - automatic scrolling
<div className="page">
{/* Long content scrolls automatically */}
</div>
// React Native - explicit ScrollView
import { ScrollView } from 'react-native';
<ScrollView contentContainerStyle={styles.page}>
{/* Content */}
</ScrollView>
// Or SafeAreaView + ScrollView
<SafeAreaView style={{ flex: 1 }}>
<ScrollView>
{/* Content */}
</ScrollView>
</SafeAreaView>
💅 Conditional Styling
// Web with className
<div className={`btn ${isActive ? 'active' : ''}`}>
// React Native with style array
<View style={[styles.btn, isActive && styles.active]}>
// Or Pressable with function
<Pressable
style={({ pressed }) => [
styles.btn,
pressed && styles.pressed,
isActive && styles.active,
]}
>
⏳ Loading State
// Web
{isLoading ? <div className="spinner"></div> : <Content />}
// React Native
import { ActivityIndicator } from 'react-native';
{isLoading ? (
<ActivityIndicator size="large" color="#0000ff" />
) : (
<Content />
)}
⚡ Quick Reference Card
| I want to... | Use this |
|---|---|
| Create a container | <View> |
| Display text | <Text> |
| Show an image | <Image> |
| Make scrollable | <ScrollView> or <FlatList> |
| Handle tap | <Pressable onPress> |
| Text input | <TextInput> |
| Toggle/switch | <Switch> |
| Show loading | <ActivityIndicator> |
| Modal/dialog | <Modal> |
| Safe areas | <SafeAreaView> |
| Navigate | Expo Router / router.push() |
| Store data | AsyncStorage / SecureStore |