HTML to JSX Converter

Paste HTML and get React-ready JSX — React attribute names, camelCased inline style objects, self-closed void tags, JSX comments and escaped text, converted locally in your browser.

Try:
JSX

About this tool

HTML to JSX Converter turns plain HTML into React-ready JSX. It is the step you hit every time you paste markup from a design export, a CMS, a Bootstrap/Tailwind snippet, an email template, or an old server-rendered template into a React component and the compiler starts complaining about class, unclosed <img> tags, and string style attributes.

The converter rewrites everything JSX is strict about:

Worked example

Input HTML:

<div class="card"><label for="n">Name</label><input id="n" tabindex="2" readonly></div>

JSX output:

<div className="card">
  <label htmlFor="n">Name</label>
  <input id="n" tabIndex={2} readOnly={true} />
</div>

With Wrap in a component set to Card and 4-space indentation, <p style="color: red; font-size: 12px">Hi</p> becomes:

export default function Card() {
    return (
        <p style={{ color: "red", fontSize: "12px" }}>Hi</p>
    );
}

Options

Limits and edge cases

FAQ

Why does JSX need `className` instead of `class`?

JSX compiles to JavaScript, and class is a reserved word there, so React named the DOM property className (the same name the browser's DOM API uses). for has the same problem — it becomes htmlFor. This tool renames both, along with the rest of React's camelCase attribute set.

Why did my `style="…"` string turn into double braces?

React expects a JavaScript object for style, not a CSS string. The outer braces are the JSX expression container and the inner ones are the object literal, which is why it reads as style={{ … }}. Property names are camelCased (font-sizefontSize) and values stay strings, so units like px and % survive untouched.

What happens to `value` and `checked` on a form field?

By default they become defaultValue and defaultChecked. React treats value / checked as a controlled value: without an onChange handler the field would be frozen and React would log a warning. defaultValue / defaultChecked gives you the same initial state with an editable field. Switch the option to Keep as value / checked if you're adding state and a change handler yourself.

Can I convert a whole HTML page?

Yes — paste it and you'll get the <html>/<head>/<body> tree as JSX, with the doctype dropped. In practice you usually want one component's worth of markup: React apps rarely render <html> directly outside a framework's document file, and a full page pulls in <meta>/<script> tags that belong in your framework's head configuration.

Is my HTML uploaded anywhere?

No. The page runs a WebAssembly converter in your browser. The markup is parsed and converted locally, and you can copy or download the JSX without the content leaving your device.

Does it handle SVG icons?

Yes. SVG attributes are camelCased the way React expects (stroke-widthstrokeWidth, stroke-linecapstrokeLinecap, viewboxviewBox, xlink:hrefxlinkHref), and camelCase SVG element names such as <linearGradient> and <clipPath> are preserved even if the source wrote them in lowercase.

Developer & Automation Access

Run it from the terminal

Same engine as this page, headless — via the gizza CLI:

gizza tool html-to-jsx '<div class="card"><label for="n">Name</label><input id="n" tabindex="2" readonly></div>'

New to the CLI? Get gizza →

Open it by URL

Pre-fill and auto-run this tool with query parameters — the names match the API/CLI:

https://gizza.ai/tools/html-to-jsx/?html=%3Cdiv%20class%3D%22card%22%3E%3Clabel%20for%3D%22n%22%3EName%3C%2Flabel%3E%3Cinput%20id%3D%22n%22%20tabindex%3D%222%22%20readonly%3E%3C%2Fdiv%3E&indent=2&component=Card&comments=jsx&boolean_attrs=explicit&value_attrs=default

Machine-readable descriptor: tool.json — title + parameters JSON Schema for agents.