HTML to JSX Converter
Convert HTML to JSX with automatic attribute conversion.
Reviewed by Aygul Dovletova · Last reviewed
How to Use the HTML to JSX Converter
- Paste HTML into the input pane. A marketing page hero, a CodePen snippet, an Email HTML template, or the output of a Figma-to-HTML exporter all work.
- Read the JSX in the output pane - it updates as you type. Every attribute that React renames (
class,for, event handlers, boolean attributes) has already been rewritten. - Copy the JSX and paste it directly into a React component. The output is a valid return value for a functional component or a JSX expression inside a variable.
- Wrap the result in a single root element or a
<>...</>fragment if your source has multiple siblings. React requires exactly one root element per component return.
What Gets Transformed
The converter handles every difference between HTML5 syntax and the JSX dialect that React parses. Attribute renames include class to className, for to htmlFor, tabindex to tabIndex, readonly to readOnly, maxlength to maxLength, colspan to colSpan, and all SVG attribute renames defined in the React docs (over 150 of them). Every inline event handler is camelCased: onclick becomes onClick, onmouseenter becomes onMouseEnter, oninput becomes onInput.
Style strings are parsed into style objects. style="background-color: red; font-size: 14px" becomes style={{ backgroundColor: "red", fontSize: "14px" }} - CSS property names are camelCased and numeric pixel values can be optionally converted to numbers. Void elements (<br>, <img>, <input>, <hr>, <meta>, <link>) receive the self-closing slash that JSX requires. HTML comments <!-- comment --> convert to JSX comments {/* comment */} so they survive inside component source. Boolean attributes like disabled and checked keep the attribute name and receive ={true} only if they originally had no value.
Why and When
- Porting a static HTML mock or Tailwind UI snippet into a React component without hand-renaming 30 attributes.
- Converting a design-system reference (Bootstrap, Material, Tailwind UI) into a React-native JSX template.
- Pulling a prototype out of a CodePen, where HTML is the default, into a Vite + React setup.
- Migrating a legacy Rails or Django template fragment into a React Server Component.
- Creating the body of a reusable React component from an email template hand-coded in HTML.
- Teaching the differences between HTML and JSX by pasting a complete page and watching each transform land.
Pitfalls You Should Know
- Multiple root elements. JSX requires a single root. If you paste a snippet with siblings at the top level you must wrap them in a fragment. The converter keeps them separate; wrap before using.
- JavaScript-reserved words. HTML
classbecomes JSXclassName;foron labels becomeshtmlFor. Any attribute you add manually after conversion must follow the same rules. - Boolean attributes. HTML
<input disabled>is short fordisabled="", which React would interpret as an empty string (still truthy). The converter emitsdisabled={true}to be explicit, which also matches how TypeScript types expect booleans. - Comments inside
<head>. JSX fragments do not directly render HTML comments in the DOM - they are JavaScript comments, stripped at compile time. If you need a real HTML comment at runtime, render it via a raw-HTML escape hatch or keep it on the server side. - Inline event handler code. HTML event handlers use string bodies:
onclick="alert(1)". The converter rewrites the attribute name but keeps the body as a string, which React will not execute. Rewrite the body to a real function reference.
Why JSX Differs from HTML
JSX is a syntax extension to ECMAScript defined by Facebook for use with React. The spec is deliberately JavaScript-first: attribute names that collide with JavaScript reserved words (class, for) must be renamed, and attribute values that are JavaScript expressions go in curly braces rather than quoted strings. Void elements must self-close because JSX is parsed as a tree, not by HTML\'s forgiving parser. The style object form exists because React needs a way to pass per-key updates rather than diffing style strings character by character. All of these differences are rooted in JSX being compiled to React.createElement() calls and the fact that attribute names map to object property names.
Alternative Tools
Inside VS Code the "HTML to JSX" extension by Riazxrazor runs the same transformations. IDE-embedded converters are handy because they apply to selections rather than a whole paste. For bulk conversions of a large template library, html-react-parser or html-to-jsx on npm can automate the process in a build script. React DevTools also offers a copy-as-JSX context menu on inspected DOM nodes, which is the fastest path if you want to lift an existing component. This in-browser tool is best for one-off snippets and for learners who want to see the transformations explicitly rather than trust a build step.
Frequently Asked Questions
Does the converter output React or Preact compatible JSX?
Both. The JSX dialect is a syntax extension, not a library-specific format - any library that compiles JSX through Babel or esbuild (React, Preact, Inferno, Hyperapp) accepts the same output. A handful of attributes differ (<code>className</code> in React is still <code>class</code> in Preact, though Preact accepts both), but this converter uses the React spelling to be maximally compatible. Preact alias packages also let you use React-style names unchanged.
Will inline styles be converted into style objects?
Yes. A <code>style</code> attribute string gets parsed into key-value pairs and emitted as a JavaScript object with camelCased keys. <code>background-color</code> becomes <code>backgroundColor</code>, vendor prefixes like <code>-webkit-transform</code> become <code>WebkitTransform</code> (the capital letter is intentional for vendor prefixes in React). Values stay as strings, which is the format React expects; numeric unitless values like <code>lineHeight: 1.5</code> work as numbers too but the converter keeps them as strings to preserve what you wrote.
Is my HTML ever sent to a server?
No. The converter is a Preact component in the page bundle, running entirely on your main thread. Clicking Convert invokes local JavaScript; no fetch or websocket goes out. You can watch DevTools Network to confirm. That matters for HTML from internal dashboards or customer-facing templates you would not want inspected by a third party.
What happens with custom data attributes?
They pass through unchanged. React preserves <code>data-*</code> and <code>aria-*</code> attributes verbatim because they are in the spec-allowed list of hyphenated attribute names that are valid HTML and valid JSX. Custom attributes without a prefix (like <code>custom-thing</code>) also pass through, though they will emit a DOM warning in React if the target element is not a custom element.
Does it handle SVG attributes?
Yes. SVG in React has its own list of renames - most notably <code>stroke-width</code> to <code>strokeWidth</code>, <code>fill-opacity</code> to <code>fillOpacity</code>, <code>clip-path</code> to <code>clipPath</code>, and <code>xlink:href</code> to <code>xlinkHref</code> (though React 19 also accepts <code>href</code> directly for SVG). The converter applies all of them. Pasting a full <code><svg></code> element produces JSX that renders identically to the source.
What about form elements like <code><select></code>?
Controlled form elements need special handling in React. This converter transforms the attribute names (<code>value</code>, <code>defaultValue</code>, <code>checked</code>, <code>defaultChecked</code>) correctly, but you still need to wire up <code>onChange</code> handlers yourself. HTML <code><option selected></code> becomes JSX <code><option selected={true}></code>, which React will warn about because you should use the parent <code><select></code>'s <code>defaultValue</code> instead.
How are self-closing tags handled?
Void elements (<code>br</code>, <code>hr</code>, <code>img</code>, <code>input</code>, <code>meta</code>, <code>link</code>, <code>source</code>, <code>track</code>, <code>wbr</code>, and a few others) receive a closing slash in the JSX output. HTML allows bare <code><br></code> but JSX requires <code><br /></code> because the parser needs explicit tag closure. Non-void elements with empty content are also collapsed to self-closing form for brevity.
Will this work for Vue or Svelte templates?
No. Vue and Svelte have their own template dialects with their own directives (<code>v-if</code>, <code>:class</code>, <code>{#if}</code>). This tool only targets the React/JSX subset of differences from HTML. For Vue, inline <code>class</code> and <code>style</code> mostly work as-is because Vue keeps the HTML spellings; for Svelte the same applies. Use framework-specific converters for those targets.
Does the converter rename <code>onclick="doSomething()"</code> correctly?
It renames the attribute (to <code>onClick</code>) but the value stays as a string. React expects the value to be a function reference, not a string, so <code>onClick="doSomething()"</code> would not execute. After conversion, rewrite the body to <code>{handleClick}</code> referencing a function in scope. The converter cannot do this safely because the string body is arbitrary JavaScript that might reference identifiers the component does not have.
What if my HTML includes script or style tags?
They pass through as JSX but are unlikely to behave as you want. React renders <code><script></code> into the DOM as an inert element - it does not execute the code. <code><style></code> renders as a real stylesheet, but CSS inside is not scoped. For application styles, move them to a CSS file or a CSS-in-JS library. For scripts, load them through <code>useEffect</code> with a dynamic <code><script></code> element or a library like <code>react-helmet</code>.
More Developer Tools
Base64 Encoder & Decoder
Encode UTF-8 text to Base64 online or decode Base64 back to UTF-8 and plain text. Runs in your browser with no upload.
Open toolBulk URL Encode / Decode
Encode or decode many URLs at once. Paste a newline-separated list and the tool processes each line in parallel, preserving order and blank lines.
Open toolCode Screenshot
Create beautiful code snippet images with customizable themes.
Open toolColor Converter
Convert colors between HEX, RGB, HSL and CMYK formats.
Open toolCron Expression Parser
Parse cron expressions into human-readable schedules with next run times.
Open toolCSS Formatter / Minifier
Format, beautify and minify CSS code.
Open tool