The Five Differences From HTML That Trip Everyone Up
JSX Rules
JSX looks like HTML but follows JavaScript rules. Here are the surprises — one root element, closed tags, camelCase, `className`, `htmlFor`.
What you'll learn
- Always return one root JSX element
- Self-close void elements
- Use camelCase prop names and the reserved-word fixes
JSX looks like HTML but follows JavaScript rules. Here are the rules that catch newcomers, in order.
1. Return One Root Element
A JSX expression has to evaluate to ONE element. Multiple top-level elements break:
// ✗ Adjacent JSX elements — won't compile
function Bad() {
return (
<h1>Title</h1>
<p>Body</p>
);
} Wrap in a parent, or use a Fragment:
// ✓ One root
function Good() {
return (
<>
<h1>Title</h1>
<p>Body</p>
</>
);
} <>...</> is a Fragment — a “ghost” wrapper that doesn’t render
anything. You’ll see it everywhere.
2. Close Every Tag
HTML lets you skip the closing tag on void elements (<img>,
<br>). JSX doesn’t.
// ✗
<img src="/me.png">
<br>
// ✓ Self-close it
<img src="/me.png" />
<br /> 3. className Instead of class
class is a reserved word in JavaScript. JSX uses className.
<button className="primary">OK</button> 4. htmlFor Instead of for
Same reason — for is a JavaScript keyword.
<label htmlFor="email">Email</label>
<input id="email" type="email" /> 5. camelCase Most of the Time
Multi-word DOM attributes become camelCase in JSX:
| HTML | JSX |
|---|---|
tabindex | tabIndex |
readonly | readOnly |
maxlength | maxLength |
onclick | onClick |
onchange | onChange |
stroke-width (SVG) | strokeWidth |
data-* and aria-* attributes are the exception — they keep their
dashes.
<button data-testid="save" aria-label="Save">💾</button> Inline Styles Are Objects
style is not a string in JSX. It’s an object with camelCase
keys.
// ✗
<div style="color: red; margin-top: 10px">
// ✓
<div style={{ color: "red", marginTop: 10 }}> The double braces are: outer {} for “JS expression”, inner {}
for “this is an object literal”.
Comments Inside JSX
Use a JS comment wrapped in { ... }:
<div>
{/* a JSX comment */}
<h1>Title</h1>
</div> Up Next
Now the fun part — embedding logic inside JSX with { }.