React Native Capabilities
React Native has roughly two display algorithms: flex, and text-inline. Any element which has a Text
parent will be displayed with the text-inline algorithm, and all other elements will be displayed with the flex algorithm. The former severely limits the set of styles which will be supported, this is what you are stumbling on.
Elements inside text-inline will have the following styles ignored:
- Margins
- Percent-widths
- All flex rules
I suggest you play with a snippet like the one below to have a gist:
import React from 'react';
import {SafeAreaView, useWindowDimensions, View, Text} from 'react-native';
export default function App() {
const {width} = useWindowDimensions();
return (
<SafeAreaView style={{flex: 1}}>
<Text>
Hello world!
<View style={{ /* play with padding, margins, flex... etc! */ }}>
<Text>I'm inside a view!</Text>
</View>
How are you doing?
</Text>
</SafeAreaView>
);
}
Solution 1: force width
Hence, the only way we could achieve what you are looking for via styles would be to set its width
to the passed contentWidth
:
import React from 'react';
import {SafeAreaView, useWindowDimensions, View} from 'react-native';
import RenderHTML, {
CustomTextualRenderer,
useContentWidth,
} from 'react-native-render-html';
const htmlContent = `
<span>Hello</span><span>Goodbye</span>
`;
const RenderedSpan: CustomTextualRenderer = ({TDefaultRenderer, ...props}) => {
const width = useContentWidth();
return (
<View style={{width}}>
<TDefaultRenderer {...props} />
</View>
);
};
const renderers = {
span: RenderedSpan,
};
export default function App() {
const {width} = useWindowDimensions();
return (
<SafeAreaView style={{flex: 1}}>
<RenderHTML
renderers={renderers}
source={{html: htmlContent}}
contentWidth={width}
/>
</SafeAreaView>
);
}
LINK TO SNACK
Solution 2: use Block content model
You suggested setting the span
content model to block
and with the snippet you provided, it works great:
import React from 'react';
import {SafeAreaView, useWindowDimensions, View} from 'react-native';
import RenderHTML, {
defaultHTMLElementModels,
HTMLContentModel,
} from 'react-native-render-html';
const htmlContent = `
<span>Hello</span><span>Goodbye</span>
`;
const customHTMLElementModels = {
span: defaultHTMLElementModels.span.extend({
contentModel: HTMLContentModel.block,
}),
};
export default function App() {
const {width} = useWindowDimensions();
return (
<SafeAreaView style={{flex: 1}}>
<RenderHTML source={{html: htmlContent}} contentWidth={width} customHTMLElementModels={customHTMLElementModels} />
</SafeAreaView>
);
}
The block content model will force the render engine to guarantee rendered span
elements won't have any Text
ascendants, thus securing a flex column display. LINK TO SNACK