HTML to JSX: How to Convert HTML for React Components
If you have worked with React, you have encountered JSX. JSX looks like HTML, but it is not HTML. It is a syntax extension for JavaScript that lets you write markup directly inside your component code. When you copy HTML from a template, documentation or a design tool and paste it into a React component, it usually breaks. The differences between HTML and JSX are small but important, and knowing them will save you from frustrating debugging sessions.
What is JSX?
JSX stands for JavaScript XML. It was created by the React team to let developers describe UI structure using a familiar HTML-like syntax inside JavaScript files. Under the hood, JSX is transformed into React.createElement() calls by a compiler like Babel or the TypeScript compiler. This means every JSX element is actually a JavaScript expression, which is why it follows JavaScript rules rather than HTML rules.
// This JSX:
<div className="card">
<h1>Hello</h1>
</div>
// Compiles to:
React.createElement("div", { className: "card" },
React.createElement("h1", null, "Hello")
);Key Differences Between HTML and JSX
Most HTML will work in JSX with only a few changes. Here are the differences you need to know, ordered from most common to least common.
class Becomes className
The class attribute is a reserved keyword in JavaScript. In JSX, you must use className instead. This is by far the most common change you will make when converting HTML.
<!-- HTML -->
<div class="container">
<p class="text-lg font-bold">Hello</p>
</div>
// JSX
<div className="container">
<p className="text-lg font-bold">Hello</p>
</div>for Becomes htmlFor
The for attribute on <label> elements is also a reserved JavaScript keyword (the for loop). In JSX, use htmlFor:
<!-- HTML -->
<label for="email">Email</label>
<input id="email" type="email" />
// JSX
<label htmlFor="email">Email</label>
<input id="email" type="email" />Inline Styles Use Objects
In HTML, the style attribute takes a CSS string. In JSX, it takes a JavaScript object where property names are camelCased and values are strings (or numbers for pixel values).
<!-- HTML -->
<div style="background-color: #333; font-size: 16px; margin-top: 20px;">
// JSX
<div style={{ backgroundColor: "#333", fontSize: "16px", marginTop: "20px" }}>Notice the double curly braces. The outer pair is the JSX expression delimiter, and the inner pair is the JavaScript object literal. CSS property names like background-color become backgroundColor, font-size becomes fontSize, and so on.
Self-Closing Tags Are Required
In HTML, void elements like <img>, <br>, <input>, and <hr> do not need a closing slash. In JSX, every tag must be explicitly closed. Void elements must use the self-closing syntax:
<!-- HTML (valid) -->
<img src="photo.jpg" alt="Photo">
<br>
<input type="text">
<hr>
// JSX (must self-close)
<img src="photo.jpg" alt="Photo" />
<br />
<input type="text" />
<hr />Comments Are Different
HTML comments use <!-- comment -->. In JSX, you use JavaScript comments wrapped in curly braces:
<!-- HTML comment -->
{/* JSX comment */}
{/*
Multi-line JSX comment
*/}Event Handlers Use camelCase
HTML event attributes are lowercase (onclick, onchange, onsubmit). In JSX, they are camelCase and accept functions instead of strings:
<!-- HTML -->
<button onclick="handleClick()">Click</button>
// JSX
<button onClick={handleClick}>Click</button>Other Attribute Changes
Beyond the major differences above, several other HTML attributes have JSX equivalents:
| HTML | JSX | Reason |
|---|---|---|
| class | className | Reserved JS keyword |
| for | htmlFor | Reserved JS keyword |
| tabindex | tabIndex | camelCase convention |
| readonly | readOnly | camelCase convention |
| maxlength | maxLength | camelCase convention |
| colspan | colSpan | camelCase convention |
| charset | charSet | camelCase convention |
A Single Root Element
JSX expressions must return a single root element. If your HTML has multiple sibling elements at the top level, you need to wrap them in a parent element or use a React Fragment:
// This will NOT work
return (
<h1>Title</h1>
<p>Content</p>
);
// Wrap in a div
return (
<div>
<h1>Title</h1>
<p>Content</p>
</div>
);
// Or use a Fragment (no extra DOM node)
return (
<>
<h1>Title</h1>
<p>Content</p>
</>
);Fragments (<>...</>) are the preferred approach when you do not want to add an extra DOM node. They are especially useful when returning table rows or list items where an extra wrapper div would break the HTML structure.
Practical Conversion Example
Here is a complete HTML form converted to JSX, showing all the common changes in one place:
<!-- HTML -->
<form class="signup-form" onsubmit="handleSubmit()">
<label for="name">Name</label>
<input type="text" id="name" class="input" tabindex="1" autofocus>
<label for="bio">Bio</label>
<textarea id="bio" class="input" maxlength="500"></textarea>
<img src="avatar.png" class="avatar">
<br>
<!-- Submit button -->
<button type="submit" class="btn" style="background-color: blue;">
Sign Up
</button>
</form>
// JSX
<form className="signup-form" onSubmit={handleSubmit}>
<label htmlFor="name">Name</label>
<input type="text" id="name" className="input" tabIndex={1} autoFocus />
<label htmlFor="bio">Bio</label>
<textarea id="bio" className="input" maxLength={500}></textarea>
<img src="avatar.png" className="avatar" />
<br />
{/* Submit button */}
<button type="submit" className="btn" style={{ backgroundColor: "blue" }}>
Sign Up
</button>
</form>When You Need HTML to JSX Conversion
There are several common scenarios where you will need to convert HTML to JSX:
- Migrating from static HTML to React. When converting an existing website to a React application, every HTML template needs JSX conversion.
- Using HTML from design tools. Tools like Figma and Webflow export HTML that needs to be adapted for React components.
- Copying from documentation or tutorials. Code examples in blog posts and documentation are often written in plain HTML.
- Integrating third-party widgets. Embed codes from analytics, ads or social media platforms come as HTML snippets.
- Converting email templates. HTML email templates use inline styles and attributes that all need JSX equivalents.
While the changes are predictable and mechanical, they are tedious to do by hand, especially for large HTML blocks. An automated converter handles all the attribute renaming, self-closing tags, style object conversion and comment syntax changes in one step.
Convert HTML to JSX instantly
Paste any HTML and get valid JSX output with all attributes converted automatically. No setup required.
Open HTML to JSX Converter