HTML and JSX look nearly identical, which is exactly what makes hand converting between them error prone. A developer moving a static template into a React codebase has to catch every class attribute, every for attribute on a label, every inline style string and every unclosed img or br tag, and missing even one produces a component that fails to compile or silently ignores a style. Doing this by find and replace text catches the common cases and corrupts the rest, particularly when a hyphenated word appears inside a class name or a URL rather than in an attribute name that actually needs renaming.
The conversion runs entirely in your browser using the DOM parser your browser already ships with, so markup pulled from an internal admin tool or an unreleased marketing page never has to leave your machine to be converted.
What this html to jsx converter rewrites
Converting html attributes to jsx props starts with the two reserved words: class becomes className and for becomes htmlFor, since neither class nor for can be used as a JSX prop name directly in JavaScript. Every other hyphenated HTML attribute, such as data attributes and aria attributes, is left in its original lowercase hyphenated form, since React specifically supports those exactly as HTML defines them, unlike CSS properties inside a style attribute which do need camelCasing.
An inline style="color: red; font-size: 14px" string becomes a JSX object literal, style={{ color: 'red', fontSize: '14px' }}, with every CSS property camelCased and every value turned into a quoted string, since JSX only accepts an object for the style prop, never a raw string the way HTML does.
- class becomes className, for becomes htmlFor.
- Inline style strings become camelCased JSX style objects.
- Void elements like img, br, hr and input get an explicit self closing slash.
- HTML comments become JSX comment syntax wrapped in curly braces.
- data- and aria- attributes are left exactly as written, since JSX supports them natively.
Fixing self closing tags and other HTML looseness JSX does not allow
HTML permits a handful of void elements, img, br, hr, input, meta and a few others, to appear without any closing tag or trailing slash at all, and browsers happily accept that. JSX has no equivalent leniency: every element must either have a matching closing tag or be written with an explicit self closing slash, so <img src="logo.png"> has to become <img src="logo.png" />.
HTML also tolerates certain unquoted attribute values and boolean attributes written without an explicit value, such as disabled on its own. This converter normalises those into the form JSX and React expect, quoting values consistently and leaving standalone boolean attributes as JSX shorthand where that is what the attribute means.
Attributes that convert differently depending on context
Not every hyphenated word in the source is an attribute name that needs converting. A class name like "nav-bar" or a URL like "/blog/my-post" contains a hyphen that has nothing to do with attribute naming, and a text based converter that blindly camelCases every hyphenated string will corrupt both. Because this tool parses the HTML as a real DOM tree rather than scanning text, it only ever renames actual attribute names, never the values assigned to them.
The same care applies to the style attribute specifically, since it is the one place where content that looks like CSS property names, which do get camelCased, sits directly next to values, which never do. Parsing the style string as CSS declarations rather than as free text is what keeps a value like "1px solid #333" from being mistakenly altered.
How this html to jsx converter works under the hood
The tool uses the browser's DOMParser to read the HTML into a real, walkable element tree, then recurses through that tree rewriting each tag name, each attribute name and any inline style string according to the rules above, before serialising the result back into JSX formatted text with two space indentation.
Working from an actual parsed DOM, rather than a regular expression applied to raw text, is what lets this converter handle markup with nested elements, mixed quoting styles and nonstandard whitespace correctly, since the browser's own HTML parser has already resolved all of the ambiguity that a hand written pattern matcher would otherwise have to guess at.
How to convert HTML to JSX
- 1
Add your HTML
Paste a block of markup into the input box, or drop an .html file. Nothing is uploaded.
- 2
Convert
Run the converter to rewrite attributes, style strings and self closing tags.
- 3
Review the JSX
Check the output for anything unusual, such as an inline event handler attribute, that needs manual attention.
- 4
Copy into your component
Copy the JSX and paste it directly into a component's return statement.
Related tools worth bookmarking
Sources and further reading
- React docs: Writing markup with JSXThe official explanation of why JSX requires camelCase attributes and an object for the style prop.react.dev
- MDN: DOMParserThe browser API this converter uses to parse HTML into a real, walkable element tree before rewriting it.developer.mozilla.org
- WHATWG: HTML parsing syntaxThe living standard defining which elements are void elements that JSX requires to be explicitly self closed.html.spec.whatwg.org
Frequently asked questions
Common questions about the html to jsx converter.
No. The converter parses HTML with the browser's DOMParser into a real element tree, so it only renames actual attribute names like class to className. A hyphenated class name value such as "nav-bar-item" is an attribute value, not an attribute name, and is left completely untouched.
A style attribute string is parsed into individual CSS declarations, and each property name is camelCased into the form JSX requires, for example font-size becomes fontSize, while every value becomes a quoted string inside the resulting style object. The result is a JSX style object literal ready to paste directly into a component.
Yes. HTML void elements that can appear without a closing tag, including img, br, hr, input and meta, are rewritten with an explicit self closing slash, since JSX requires every element to be either explicitly closed or self closing with no exceptions.
No, and that is intentional. React specifically supports data- and aria- attributes exactly as HTML defines them, in their original lowercase hyphenated form, so this converter leaves them untouched while still renaming class, for and CSS properties inside a style attribute.
No. Parsing and rewriting both happen locally in your browser using DOMParser. Your markup, including anything from an unreleased page or an internal admin tool, is never transmitted, stored or seen by anyone but you.
Yes. The output is valid JSX ready to paste inside a component's return statement or arrow function body. You may still want to extract repeated markup into its own component or replace static text with dynamic props, but the markup itself will compile as written.