Skip to main content

Textual

Paragraphs#

Paragraphs have a default top and bottom margin. If you use ​enableExperimentalMarginCollapsing prop, margins of adjacents blocks will collapse as per the CSS standard.

A paragraph
import React from 'react';
import { useWindowDimensions } from 'react-native';
import RenderHtml from 'react-native-render-html';
const source = {
html: `<p style="font-size: 1.2rem; padding: 0 10px;">
Lorem ipsum dolor sit amet, consectetur adipiscing
elit, sed do eiusmod tempor incididunt ut labore et
dolore magna aliqua. Ut enim ad minim veniam, quis
nostrud exercitation ullamco laboris nisi ut aliquip
ex ea commodo consequat.
</p>
<p style="color: purple; padding: 0 10px;">
Duis aute irure dolor in
reprehenderit in voluptate velit esse cillum dolore
eu fugiat nulla pariatur. Excepteur sint occaecat
cupidatat non proident, sunt in culpa qui officia
deserunt mollit anim id est laborum.
</p>`
};
export default function App() {
const { width } = useWindowDimensions();
return (
<RenderHtml
contentWidth={width}
source={source}
enableExperimentalMarginCollapsing={true}
/>
);
}
The first paragraph has a font size set in rem. The margins between first and second paragraphs are collapsed thanks to enableExperimentalMarginCollapsing prop.
Press on the button below to show how this code renders on your device.
caution

​enableExperimentalMarginCollapsing is considered experimental because the ​TRE doesn't support ​display CSS property yet. However, margin collapsing should not apply to flex layouts while this prop will apply margin collapsing indiscriminately.

Whitespace Collapsing#

White space collasping occurs in the eponym phase of the ​Transient Render Engine processing step. Insignificant whitespaces are removed from the tree, as per the algorithm depicted in CSS Text Module Level 3.

note

The ​TRE strictly complies with this standard, although only white-space:Β normal; and white-space:Β pre; are supported at the moment.

Example: 'white-space: normal'#

This is the default behavior, with the exception of a handful of tags such as ​<pre>.

Whitespace Collapsing in Action
import React from 'react';
import { useWindowDimensions } from 'react-native';
import RenderHtml from 'react-native-render-html';
const source = {
html: `<div style="white-space: normal; text-align: center;">
<span>This is text!</span>
This is <strong>bold</strong>, <em>italics</em>.
</div>`
};
export default function App() {
const { width } = useWindowDimensions();
return (
<RenderHtml
contentWidth={width}
source={source}
/>
);
}
Notice that the four line breaks and the second space after the coma have been removed.
Press on the button below to show how this code renders on your device.

Example: 'white-space: pre'#

You can set the ​white-space CSS property with inline styles or with classes, id and tags styles.

Whitespace Collapsing Disabled
import React from 'react';
import { useWindowDimensions } from 'react-native';
import RenderHtml from 'react-native-render-html';
const source = {
html: `<div style="white-space: pre; text-align: center;">
<span>This is text!</span>
This is <strong>bold</strong>, <em>italics</em>.
</div>`
};
export default function App() {
const { width } = useWindowDimensions();
return (
<RenderHtml
contentWidth={width}
source={source}
/>
);
}
Notice that the four line breaks and the second space after the coma have been preserved.
Press on the button below to show how this code renders on your device.

Preformatted Content#

Preformatted Text
import React from 'react';
import { useWindowDimensions } from 'react-native';
import RenderHtml from 'react-native-render-html';
const source = {
html: `
<figure>
<pre> ___________________________
< I'm an expert in my field. >
---------------------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
</pre>
<figcaption>
A cow saying, "I'm an expert in my field." The cow is illustrated using preformatted text characters.
</figcaption>
</figure>`
};
export default function App() {
const { width } = useWindowDimensions();
return (
<RenderHtml
contentWidth={width}
source={source}
/>
);
}
Notice that every white-space inside the <pre> tag is preserved while white-spaces outside are collapsed.
Press on the button below to show how this code renders on your device.
note

The default font for the ​<pre> tag is monospace and ​white-space property is "pre". These default styles are set via the ​mixedUAStyles associated with this tag element model. See ​Element Models.

Font Selection#

CSS ​font-family and ​font properties allow a comma-separated list of fonts, but React Native styles fontFamily allows only one font name. With the ​TRE, you can instruct which fonts are available in the system (or fonts you have added), and it will pick the first match! The prop to achieve that is ​systemFonts.

By default, a handful of fonts supported by the current platform are pre-registered (Android, iOS, MacOS and Windows). If you are using expo, just set this prop to Constants.systemFonts. You can also define how generic font names are resolved with the ​fallbackFonts prop.

Example: Arial Font Selection#

Arial Font Selection
import React from 'react';
import { useWindowDimensions } from 'react-native';
import RenderHtml from 'react-native-render-html';
const source = {
html: `<p style="font-family: 'Arial', sans-serif; padding: 10px;">
Lorem ipsum dolor sit amet, consectetur adipiscing
elit, sed do eiusmod tempor incididunt ut labore et
dolore magna aliqua. Ut enim ad minim veniam, quis
nostrud exercitation ullamco laboris nisi ut aliquip
ex ea commodo consequat.
</p>`
};
export default function App() {
const { width } = useWindowDimensions();
return (
<RenderHtml
contentWidth={width}
source={source}
enableExperimentalMarginCollapsing={true}
/>
);
}
This paragraph font family is set to "Arial" (will match on iOS, MacOS and Windows) and should fallback to sans-serif otherwise.
Press on the button below to show how this code renders on your device.

Example: Courier New Font Selection#

Courier New Font Selection
import React from 'react';
import { useWindowDimensions } from 'react-native';
import RenderHtml from 'react-native-render-html';
const source = {
html: `<p style="font-family: 'Courier New', monospace; padding: 10px;">
Lorem ipsum dolor sit amet, consectetur adipiscing
elit, sed do eiusmod tempor incididunt ut labore et
dolore magna aliqua. Ut enim ad minim veniam, quis
nostrud exercitation ullamco laboris nisi ut aliquip
ex ea commodo consequat.
</p>`
};
export default function App() {
const { width } = useWindowDimensions();
return (
<RenderHtml
contentWidth={width}
source={source}
enableExperimentalMarginCollapsing={true}
/>
);
}
This paragraph font family is set to "Courier New" (will match on iOS, MacOS and Windows) and should fallback to monospace otherwise.
Press on the button below to show how this code renders on your device.

Example: Space Mono Font Selection#

Space Mono Font Selection
import React from 'react';
import { useWindowDimensions } from 'react-native';
import RenderHtml, { defaultSystemFonts } from 'react-native-render-html';
import { useFonts, SpaceMono_400Regular } from '@expo-google-fonts/space-mono';
function FontLoader({ children }){
const [fontsLoaded] = useFonts({
'space-mono': SpaceMono_400Regular,
});
if (!fontsLoaded) {
return null;
}
return <>{children}</>;
}
const source = {
html: `<p style="font-family: 'space-mono'; padding: 10px;">
Lorem ipsum dolor sit amet, consectetur adipiscing
elit, sed do eiusmod tempor incididunt ut labore et
dolore magna aliqua. Ut enim ad minim veniam, quis
nostrud exercitation ullamco laboris nisi ut aliquip
ex ea commodo consequat.
</p>`
};
const systemFonts = ["space-mono", ...defaultSystemFonts];
export default function App() {
const { width } = useWindowDimensions();
return (
<FontLoader>
<RenderHtml
contentWidth={width}
source={source}
systemFonts={systemFonts}
enableExperimentalMarginCollapsing={true}
/>
</FontLoader>
);
}
This paragraph font family is set to "Space Mono", which is loaded with Expo font loading helpers and registered via systemFonts prop.
Press on the button below to show how this code renders on your device.
caution

Fonts registered in ​systemFonts should not be surrounded with quotes; however you can surround the font name with quotes in inline and mixed styles, as per CSS standard.

Caveats#

Line Breaks#

Line breaks work seemlessly with the ​<br> element. There is a known bug though in the Foundry release, where line breaks closing an inline formatting context will be printed while they should be ignored. Below is an example for illustration purposes:

Line break bug in v6
import React from 'react';
import { useWindowDimensions } from 'react-native';
import RenderHtml from 'react-native-render-html';
const source = {
html: `<p style="background-color: yellow">
A line with a line break closing
an inline formatting context.<br>
</p>
`
};
export default function App() {
const { width } = useWindowDimensions();
return (
<RenderHtml
contentWidth={width}
source={source}
/>
);
}
A line break closing an inline formatting context should not be printed according to WHATWG HTML standard. Notice that there is an extraneous new line at the end of the sentence.
Press on the button below to show how this code renders on your device.

Hopefully, the bug has been identified and since version 6.1.1 there is a workaround. You just need to pass ​enableExperimentalBRCollapsing prop:

A fix to the line break bug
import React from 'react';
import { useWindowDimensions } from 'react-native';
import RenderHtml from 'react-native-render-html';
const source = {
html: `<p style="background-color: yellow">
A line with a line break closing
an inline formatting context.<br>
</p>
`
};
export default function App() {
const { width } = useWindowDimensions();
return (
<RenderHtml
contentWidth={width}
source={source}
enableExperimentalBRCollapsing={true}
/>
);
}
enableExperimentalBRCollapsing prop prevents this bug from happening
Press on the button below to show how this code renders on your device.

Empty Tags#

React Native has a weird behavior whereby empty ​Text elements span vertically on iOS and Android. I called this "ghost lines". For example:

Ghost lines in React Native
import React from 'react';
import { useWindowDimensions } from 'react-native';
import RenderHtml from 'react-native-render-html';
const source = {
html: `<p style="background-color: yellow">
<span></span>
</p>
`
};
export default function App() {
const { width } = useWindowDimensions();
return (
<RenderHtml
contentWidth={width}
source={source}
/>
);
}
The span element is rendered as an empty Text, but it takes vertical space, approximately 20dpi, independent of font size and line height.
Press on the button below to show how this code renders on your device.

Since version 6.1.1, a new prop, ​enableExperimentalGhostLinesPrevention, prevent this behavior from happening. It will also handle multiple ghost elements:

Ghost lines fix
import React from 'react';
import { useWindowDimensions } from 'react-native';
import RenderHtml from 'react-native-render-html';
const source = {
html: `<p style="background-color: yellow">
<span></span>
<span></span>
</p>
`
};
export default function App() {
const { width } = useWindowDimensions();
return (
<RenderHtml
contentWidth={width}
source={source}
enableExperimentalGhostLinesPrevention={true}
/>
);
}
enableExperimentalGhostLinePrevention prop will attempt to prevent this odd behavior, including with multiple empty tags and whitespaces.
Press on the button below to show how this code renders on your device.