TL;DR:
CSS and RN behaves completely differently. To cascade styles using Nativewind use the styled
higher-order component:
import { styled } from 'nativewind';
import { Text } from 'react-native';
export const MyOrangeText = styled(Text, 'font-bold text-4xl text-orange-600');
or define a custom component yourself:
const MyOrangeText = ({children}) => {
return <Text className='font-bold text-4xl text-orange-600'>{children}</Text>
}
To answer the question:
This is a CSS behavior vs React Native behavior problem. React Native's styling only mimics CSS by having similar property names and trying to match as many properties as possible, but it does not have the same kind of property inheritance or "cascading" as CSS.
There are two kinds of properties in CSS:
An inherited
property get the value of its parent's property if not set. color
is an inherited
property, so if you set this property on the parent div
but not set it on the div
's children, all the children will get the same color.
non-inherited
properties are not inherited and they get a default value if not set (e.g. border
will not be inherited if the parent has a border)
That is the reason why in Tailwind CSS the inheritance works by default, because Tailwind is just CSS utility classes and has this same behavior.
In RN there is no inheritance of style properties from parents to children. In RN the style
prop of every component is a plain old JS object. You can also pass an array of styles - the last style in the array has precedence, so you can also use this to merge styles.
The kind of "cascading" you want to achieve would look like the following in RN:
1. With exporting-importing style objects
// somewhere like ./src/styles/text.js
export const { orangeText, blueText } = StyleSheet.create({
orangeText: {
color: 'orange',
},
blueText: {
color: 'blue',
}
)};
// somewhere in a component
import { orangeText } from '../styles/text.js'
const MyComponent = () => {
return (
<View>
<Text style={orangeText}>Orange</Text>
<Text style={orangeText}>Also orange</Text>
</View>
);
}
2. Or creating custom component and passing down a style
prop
// The styles object created with StyleSheet.create
const TextWrapper = () => {
return (
<View>
<MyCustomText textStyle={styles.orangeText}>Orange</MyCustomText>
<MyCustomText textStyle={styles.orangeText}>Also Orange</MyCustomText>
</View>
)
}
// Of course you could just use the build-in TextProps
// but I wanted to show the type of the style property
interface MyCustomTextProps {
textStyle?: StyleProp<TextStyle>;
children?: ReactNode;
}
const MyCustomText = ({ textStyle, children }: MyCustomTextProps): ReactElement => {
return (
<Text style={textStyle}>
{children}
</Text>
);
};
nativewind uses the className
extension on RN components to parse Tailwind CSS utility classes and translates them to RN style
objects.
In essence this:
<Text className='font-bold text-4xl text-black'>Orange</Text>
Gets translated to something like this:
<Text style={[gen.fontBold, gen.text4xl, gen.textBlack]}>Orange</Text>;
const gen = StyleSheet.create({
fontBold: {
fontWeight: '700',
}
text4xl: {
fontSize: 36,
lineHeight: 40,
},
textBlack: {
color: 'rgba(0, 0, 0, 1)',
}
});
Of course this is not exactly how it will look like. nativewind also does optimizations, flattening of the style objects, the names will be different etc. But it will generate style objects and applies them to the style
prop.
So if you set the color
property on the parent View
, it will be simply ignored as View
does not have a color
property.