Lesson 7 of 26
StyleSheet and Styling Patterns
Why React Native uses StyleSheet.create instead of CSS, how unitless numbers work as density-independent pixels, and how to combine and conditionally apply styles.
CSS on the web gives you cascading rules, selectors, and a browser engine
that parses a stylesheet file. React Native has none of that. Styling here
is plain JavaScript objects, validated and referenced through
StyleSheet.create, using a unit system that isn't CSS's either. None of
it is CSS wearing a disguise — it's worth understanding on its own terms.
StyleSheet.create is not a CSS parser
import { View, Text, StyleSheet } from "react-native";
function Card({ title }) {
return (
<View style={styles.card}>
<Text style={styles.title}>{title}</Text>
</View>
);
}
const styles = StyleSheet.create({
card: {
backgroundColor: "#fff",
borderRadius: 8,
padding: 16,
},
title: {
fontSize: 18,
fontWeight: "600",
color: "#111",
},
});styles.card and styles.title are plain JavaScript objects — a defined
subset of style properties specific to React Native, not the full CSS
property list, and not parsed from any stylesheet syntax. StyleSheet.create
takes those objects and does two useful things with them: it validates
that the properties you wrote are recognized style properties (catching
typos like a misspelled property name at the point you define the style,
rather than silently doing nothing), and it lets the resulting styles be
referenced consistently by identity rather than recreated as brand-new
objects on every single render — a small but real efficiency and
correctness win compared to writing equivalent plain object literals
inline everywhere.
You could, technically, skip StyleSheet.create and just use plain
objects directly as style values — React Native will still apply them.
StyleSheet.create is the established convention because of the
validation and reference-stability benefits above, not because plain
objects are actually forbidden.
Numbers are unitless — and that unit is not px
This is the detail that surprises people coming straight from CSS: React Native style numbers have no unit suffix at all.
const styles = StyleSheet.create({
box: {
width: 100, // not "100px" — just the number 100
height: 100,
margin: 12,
},
});There's no px, no em, no rem — just a number. Those numbers are
density-independent units: the platform scales them appropriately for
the actual physical pixel density of the device's screen, so a width: 100
box reads as roughly the same physical size across devices with very
different raw pixel densities, rather than 100 raw hardware pixels (which
would look wildly different in physical size on a low-density screen
versus a high-density one). This is conceptually close to what CSS's px
unit is trying to approximate on the web (a CSS pixel is also not
literally one hardware pixel on high-density displays) — but in React
Native there's no unit keyword at all; a bare number is simply understood
to mean this density-independent unit throughout the entire style system.
Percentages are supported as strings where it makes sense for a property
(width: "50%"), but the plain-number case is the default you'll reach
for constantly.
Combining styles: the array pattern
A single style object gets limiting fast once you need a base style plus
situational variations. React Native's style prop accepts an array, and
merges the objects in order — later entries win when properties conflict:
function Button({ label, selected }) {
return (
<View style={[styles.button, selected && styles.buttonSelected]}>
<Text style={[styles.label, selected && styles.labelSelected]}>{label}</Text>
</View>
);
}
const styles = StyleSheet.create({
button: {
padding: 10,
borderRadius: 6,
backgroundColor: "#eee",
},
buttonSelected: {
backgroundColor: "#3366ff",
},
label: {
color: "#111",
},
labelSelected: {
color: "#fff",
},
});selected && styles.buttonSelected evaluates to either the style object
(when selected is true) or false (when it's not) — and React Native's
array style form simply ignores falsy entries in the array, which makes
this a very common, idiomatic way to express "apply this extra style
conditionally."
Inline styles: fine when a value depends on data
StyleSheet.create styles are defined once, ahead of time — they can't
depend on a specific prop value at render time (like an exact color
computed from a piece of data). For that, a plain inline style object is
the right, ordinary tool, usually combined with a StyleSheet.create base
via the array pattern:
function ProgressBar({ percent }) {
return (
<View style={styles.track}>
<View style={[styles.fill, { width: `${percent}%` }]} />
</View>
);
}
const styles = StyleSheet.create({
track: {
height: 8,
borderRadius: 4,
backgroundColor: "#eee",
overflow: "hidden",
},
fill: {
height: 8,
backgroundColor: "#3366ff",
},
});Here, styles.fill covers everything static about the bar's fill, and the
inline { width: `${percent}%` } covers the one property that genuinely
depends on a prop. Reaching for an inline object isn't a shortcut you
should feel bad about — it's the correct tool specifically when a style
value can't be known ahead of time.
What to remember
- StyleSheet.create validates plain JS style objects and lets them be referenced efficiently — it is not a CSS parser, and the properties it accepts are a defined RN-specific subset, not full CSS.
- Style numbers are unitless density-independent units, not CSS px — there is no unit suffix at all.
- The array form of
stylemerges styles in order, with later entries overriding conflicting properties from earlier ones — the standard pattern for conditional styling. - Falsy entries (like false from a && expression) in a style array are simply ignored, which is why
selected && styles.selectedis idiomatic. - Inline style objects are the right tool when a value depends on props or state at render time; StyleSheet.create styles are for everything static.
Check yourself
3 questions · pass 3/3 to unlock ScrollView vs. FlatList
1.What kind of thing does StyleSheet.create actually work with?
2.In
style={{ width: 100 }}, what does the number 100 represent?3.What does style={[styles.a, styles.b]} do, and why is this pattern useful?
3 left to answer