JSX vs HTML

A Side-by-Side Cheat Sheet

JSX vs HTML

Quick reference for the differences between JSX and plain HTML — attributes, events, comments, booleans, style, void elements.

3 min read Level 1/5 #react#jsx#html
What you'll learn
  • Translate common HTML to JSX
  • Avoid the most common attribute-naming mistakes

A consolidated cheat sheet you can come back to.

Side By Side

HTMLJSX
<div class="x"><div className="x">
<label for="email"><label htmlFor="email">
<input type="text" readonly><input type="text" readOnly />
<input tabindex="0"><input tabIndex={0} />
<img src="me.png"><img src="me.png" /> (self-closed)
<br><br />
onclick="doStuff()"onClick={doStuff}
style="color: red; font-size: 14px;"style={{ color: "red", fontSize: 14 }}
<!-- a comment -->{/* a comment */}
&amp; / &copy;use the actual char, or {"©"}
data-id="42"data-id="42" (unchanged)
aria-label="Save"aria-label="Save" (unchanged)

Events Are camelCase Props

<button onClick={handleClick} onMouseEnter={handleHover}>
  Click me
</button>

You pass a function, not a string. Inline arrow functions work too:

<button onClick={() => console.log("clicked")}>Click</button>

Boolean Attributes

In HTML you write <input disabled>. In JSX you can do the same, but it’s clearer to pass a JS boolean:

<input disabled />               // always disabled
<input disabled={isLoading} />   // disabled when isLoading

Children Are Just Nested JSX

<section>
  <header>
    <h1>Title</h1>
  </header>
  <p>Body</p>
</section>

Strings Need Quotes; Everything Else Needs Braces

<img src="me.png" />               // string literal
<img src={user.avatarUrl} />        // expression
<img src={`/u/${id}.png`} />        // template literal

Self-Closing vs Open

Element typeExample
Void HTML element<img />, <br />, <input />
Custom, no children<Profile />
With children<Profile>…</Profile>

Up Next

That weird <>...</> you’ve seen — Fragments.

Fragments →