I'm trying to set the color of the text of all elements in a View
to a specific color, this can be done with practicaly any class pretty easily in tailwind by simply giving the class you want to the parent element, like this:
import { Text, View } from 'react-native';
export default function MyComponent() {
return (
<View className='flex-1 items-center justify-center text-orange-600'>
<Text className='font-bold text-4xl'>Some Text</Text>
</View>
);
}
This would make the text whithin the Text
element orange and would do the same for any other element I add inside the Parent element. The problem is that it is not working with nativewind and thus I have to manually set the color on every Text
element individually:
export default function MyComponent() {
return (
<View className='flex-1 items-center justify-center'>
<Text className='font-bold text-4xl text-orange-600'>Some Text</Text>
<Text className='font-bold text-4xl text-orange-600'>Some Other Text</Text>
</View>
);
}
I've seen this question How to access all the direct children of a div in tailwindcss? and the proposed solutions didn't work for me.
If anyone could tell me of a way to not have to manually set the class of each child element I would apreciate it.
Thanks!
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>
}
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.