A Quick Look At Rendering White Space Using JSX In ReactJS
As I've been getting into ReactJS, I've been surprised a few times at how my JSX code gets translated into rendered HTML. In particular, it took me a little while to understand the rules around rendering white space: when does JXS follow the "natural" HTML concept of white space; and, when does it strip white space out of the rendered content?
White space rendering, in ReactJS, has more to do with the physical structure of your JSX code than it does with the "natural" flow of HTML content. Because, after all, you're not writing HTML - you're writing JSX. It just so happens that your JSX code transpiles down to JavaScript and ReactJS Elements, which ultimately render HTML.
From what I can see, the basic rules around white space in JSX are as follows:
Element nodes will maintain white space when mixed with with non-element nodes on the same physical line of JSX code.
Sibling element nodes, on different physical lines of JXS code, are rendered without white space.
When element and non-element nodes are mixed, non-element text nodes are implicitly wrapped in Span tags. This can create sibling element nodes, on different physical lines of JSX code, which - as in the previous rule - are rendered without white space.
Text nodes, across different physical lines of JSX code, are rendered with natural white space (as they are ultimately transpiled as a single child).
To see this in action, I've put together a small ReactJS demo in which I render JSX code that has various combinations of element and non-element HTML nodes:
Run this demo in my JavaScript Demos project on GitHub.
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>
Rendering White Space Using JSX In ReactJS
</title>
</head>
<body>
<h1>
Rendering White Space Using JSX In ReactJS
</h1>
<div id="content">
<!-- This content will be replaced with the React rendering. -->
</div>
<!-- Load scripts. -->
<script src="../../vendor/reactjs/react-0.13.3.min.js"></script>
<script src="../../vendor/reactjs/JSXTransformer-0.13.3.js"></script>
<script type="text/jsx">
// I manage the Demo widget.
var Demo = React.createClass({
// I render the component based on the current state.
render: function() {
return(
<section>
<p>
{
// This content will render with no visible white space
// since each sibling Element node that is defined on a
// different line of CODE will be rendered right up
// against the other ones.
}
<span>Bro!</span>
<span>You</span>
<span>had</span>
<span>me</span>
<span>at</span>
<span>"White space."</span>
</p>
<p>
{
// This content will render with "expected" white space
// since the Element node is on the same line with its
// other content. As such, the white space around the
// element is preserved.
}
There's <em>literally</em> nothing more exciting!
</p>
<p>
{
// In this case, we're going to lose the white space to
// the LEFT of the first STRONG Element node and the RIGHT
// of the second one. The plain-text lines are implicitly
// wrapped in Span tags, which creates a multi-line sibling
// relationship between Element nodes, which removes white
// space (as we saw in the first example).
}
But don't get me started on
<strong>kerning</strong> and <strong>tracking</strong>
or we'll be here all day.
</p>
<p>
{
// This will render as expected since there are no
// Element nodes. This entire value gets rendered as a
// single value, NO implicit SPAN container.
}
That said, if you want to get groovy on the use of
negative space in design, then I will be more than
happy to chat. I have nowhere else to be at this moment.
</p>
<p>
{
// We can always force white space by interpolating a
// white space literal. This way, when the JSX is
// compiled down into React Element children, the white
// space literal will be an explicit child.
}
<span>Bro!</span>
{ " " }
<span>You</span>
{ " " }
<span>had</span>
{ " " }
<span>me</span>
{ " " }
<span>at</span>
{ " " }
<span>"White space."</span>
</p>
</section>
);
}
});
// --------------------------------------------------------------------------- //
// --------------------------------------------------------------------------- //
// Render the root Demo and mount it inside the given element.
React.render( <Demo />, document.getElementById( "content" ) );
</script>
</body>
</html>
When we run the above code, we get the following browser rendering:
As you can see, the rendering of white space in JSX code doesn't always follow the natural application of white space in a standard HTML document. Once you get used to this behavior, it's easy to fix by either moving your JSX around; or, by explicitly injecting white space literals. But, hopefully, this will help others that are new to the ReactJS world.
Want to use code from this post? Check out the license.
Reader Comments