Learn how to convert HTML to JSX quickly and safely. Step-by-step rules, examples, tools, and best practices to move static markup into React with confidence.
If you need to convert HTML to JSX for a React project, you’re in the right place. This guide shows you the fastest, safest path from plain HTML to clean, production-ready JSX. You’ll get rules, examples, and a repeatable process—plus a free workflow you can run in minutes.
Quick answer (Featured Snippet): To convert HTML to JSX: 1) Replace class with className and for with htmlFor. 2) Close void tags (img, input, br). 3) Convert style to a JS object. 4) Use camelCase props (tabIndex, readOnly). 5) Wrap dynamic values in {}. 6) Remove inline scripts; use onClick, onSubmit, etc. 7) For raw HTML, use dangerouslySetInnerHTML.
AI Overview: Converting HTML to JSX means adapting markup to React’s JavaScript-first syntax. Key steps include renaming attributes (class → className, for → htmlFor), closing self-closing tags, converting inline styles to objects, camelCasing attributes, and moving scripts to event handlers. Use a reliable converter for speed, then lint, test, and refactor into components. This guide covers rules, edge cases (SVG, forms, props), and pitfalls, with examples and tooling tips to ship JSX that compiles, reads well, and scales.
“Convert HTML to JSX” means taking standard HTML markup and transforming it into JSX, the syntax React uses to describe UI in JavaScript. JSX looks like HTML, but it is not a string—it compiles to JavaScript function calls (like React.createElement). That adds rules:
In short, you keep the structure of the HTML but adapt it to React’s rules so it compiles and runs in your app.
Most teams start with existing HTML: marketing pages, prototypes, CMS themes, or UI libraries. To move into React, you must convert that HTML to JSX. Doing it well:
Without a reliable process, you’ll chase compile errors and subtle bugs. With one, you ship faster and safer.
Note: Converters are fast, but they don’t know your component structure. Plan to refactor after.
Example:
<!-- HTML -->
<label for="email" class="form-label">Email</label>
<input id="email" class="form-control" maxlength="64" />
// JSX
<label htmlFor="email" className="form-label">Email</label>
<input id="email" className="form-control" maxLength={64} />
Void elements must be self-closed in JSX:
<!-- HTML -->
<img src="/logo.png">
// JSX
<img src="/logo.png" />
<!-- HTML -->
<div style="background-color: #fff; padding: 16px; line-height: 1.5"></div>
// JSX
<div style={{ backgroundColor: '#fff', padding: 16, lineHeight: 1.5 }} />
Warning: Do not overuse inline styles. Prefer CSS Modules, styled-components, or Tailwind for maintainability.
// JSX
<h2>{title}</h2>
<img src={avatarUrl} alt={user.name} />
<button disabled={isLoading}>Save</button>
Inline JS like onclick="..." or <script> blocks won’t run inside JSX. Replace them with event handlers and hooks.
<!-- HTML -->
<button onclick="increment()">Add</button>
<script>
function increment(){ counter++ }
</script>
// JSX
function Counter(){
const [count, setCount] = useState(0);
return <button onClick={() => setCount(c => c + 1)}>Add ({count})</button>;
}
If you need to inject raw HTML, use dangerouslySetInnerHTML with sanitized input only.
<div dangerouslySetInnerHTML={{ __html: sanitizedHtml }} />
Warning: Never pass user-generated HTML without sanitizing. Consider DOMPurify or server-side sanitization.
{/* This is a JSX comment */}
<p>Hello{' '}<strong>world</strong></p>
<!-- HTML -->
<svg viewBox="0 0 20 20"><path stroke-width="2" /></svg>
// JSX
<svg viewBox="0 0 20 20"><path strokeWidth={2} /></svg>
Tip: For complex SVGs, use SVGR to convert SVG files into React components.
In React, inputs are often “controlled.” After conversion, decide if you’ll control value via state.
function EmailField(){
const [email, setEmail] = useState('');
return (
<label htmlFor="email">
Email
<input
id="email"
type="email"
value={email}
onChange={e => setEmail(e.target.value)}
/>
</label>
);
}
Boolean props are true by presence in HTML, but JSX is explicit:
<!-- HTML -->
<input disabled>
// JSX
<input disabled /> // OK, true by presence
// or
<input disabled={true} />
<div data-test="hero" aria-live="polite">Loading…</div>
import logo from './logo.svg';
<img src={logo} alt="Logo" />
After your first pass:
function Card({ title, children }){
return (
<section className="card">
<h3>{title}</h3>
<div className="content">{children}</div>
</section>
);
}
Original HTML:
<section class="hero">
<h1>Build faster with Acme</h1>
<p class="lead">Modern tools to ship in days, not months.</p>
<a href="#signup" class="btn btn-primary">Get Started</a>
<img src="/img/hero.png" alt="Screenshot">
</section>
Converted JSX:
export function Hero(){
return (
<section className="hero">
<h1>Build faster with Acme</h1>
<p className="lead">Modern tools to ship in days, not months.</p>
<a href="#signup" className="btn btn-primary">Get Started</a>
<img src="/img/hero.png" alt="Screenshot" />
</section>
);
}
Refactor with props:
export function Hero({ title, subtitle, ctaHref = '#signup', ctaText = 'Get Started', imageSrc }){
return (
<section className="hero">
<h1>{title}</h1>
<p className="lead">{subtitle}</p>
<a href={ctaHref} className="btn btn-primary">{ctaText}</a>
{imageSrc && <img src={imageSrc} alt="Screenshot" />}
</section>
);
}
Original HTML:
<nav class="navbar">
<button class="navbar-toggler" aria-controls="nav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div id="nav" class="collapse navbar-collapse">
<ul class="navbar-nav">
<li class="nav-item"><a class="nav-link" href="/">Home</a></li>
</ul>
</div>
</nav>
Converted JSX with state:
function Navbar(){
const [open, setOpen] = useState(false);
return (
<nav className="navbar">
<button
className="navbar-toggler"
aria-controls="nav"
aria-expanded={open}
aria-label="Toggle navigation"
onClick={() => setOpen(o => !o)}
>
<span className="navbar-toggler-icon" />
</button>
<div id="nav" className={`collapse navbar-collapse ${open ? 'show' : ''}`}>
<ul className="navbar-nav">
<li className="nav-item"><a className="nav-link" href="/">Home</a></li>
</ul>
</div>
</nav>
);
}
Original HTML may include inline styles and <script> tags. In React:
import DOMPurify from 'dompurify';
function PostBody({ html }){
const safe = useMemo(() => DOMPurify.sanitize(html), [html]);
return <div className="post-body" dangerouslySetInnerHTML={{ __html: safe }} />;
}
| Method | Speed | Accuracy | Best For | Pros | Cons |
|---|---|---|---|---|---|
| Manual conversion | Slow | High (with expertise) | Small snippets, learning JSX | Full control, teaches nuances | Time-consuming, easy to miss details |
| ZenixTools HTML → JSX converter | Very fast | High for syntax | Most HTML blocks | Handles className, self-closing, styles | Needs human review for behavior |
| Babel/AST codemod | Fast at scale | High with tests | Large codebases | Automates repetitive changes | Setup time, requires JS tooling |
| SVGR (for SVG) | Fast | Excellent for SVG | Icons, charts | Produces React components | SVG-only |
| Framework helpers (Next.js, Vite) | N/A | N/A | Asset handling | Streamlines imports, images |
Converting HTML to JSX is a repeatable process once you know the rules. Start with a converter to save time, then fix attributes, styles, and event handlers. Sanitize any raw HTML. Refactor into components, add types and tests, and keep accessibility in focus. With these steps, you can convert HTML to JSX confidently and ship clean React code faster.
Ready to move faster? Paste your markup into the ZenixTools HTML to JSX Converter, fix small issues in seconds, then refactor with our JSX Linter & Formatter. Convert HTML to JSX today and turn static snippets into scalable React components.
A practical, expert guide to convert base64 to string across languages, with steps, examples, pitfalls, and best practices.
Learn how to convert from base64 string to text, files, and images using ZenixTools, code snippets, and CLI. Covers decoding rules, pitfalls, best practices, and real-world examples.
| Doesn’t convert markup by itself |