HTML to JSX Converter

Paste HTML on the left and this converter writes JSX on the right as you type: class becomes className, for becomes htmlFor, inline styles turn into camelCase objects, void tags like img and input are self-closed, comments move into braces, and several top-level elements get a fragment. The conversion runs only in your browser.

What changes between HTML and JSX
HTMLJSXWhy
class="box"className="box"class is a reserved word in JavaScript
for="email"htmlFor="email"for is a reserved word too
style="font-weight: bold"style={{ fontWeight: 'bold' }}style takes an object with camelCase keys
<img src="a.png"><img src="a.png" />Every tag must be closed
onclick="go()"onClick={go}Events are camelCase and take a function
data-id="7", aria-label="Close"unchangeddata- and aria- keep their dashes

Updated

Copying a snippet from a template, an email builder or an icon set into a React component usually breaks on a dozen small differences. This tool applies the rules React documents for JSX, explains each change it made, and can wrap the result in a named component ready to paste.

Converter

The sample below is converted live; replace it with your own HTML.

<!-- Signup card -->
<div class="card" style="padding: 16px; border-radius: 12px; --accent: #4f98fb">
  <label for="email">Email</label>
  <input id="email" type="email" value="" tabindex="0" autofocus>
  <button class="btn" onclick="subscribe()" aria-label="Subscribe">Join {free}</button>
</div>
<p>No spam.<br>Unsubscribe any time.</p>
<>
  {/* Signup card */}
  <div className="card" style={{ padding: '16px', borderRadius: '12px', '--accent': '#4f98fb' }}>
    <label htmlFor="email">Email</label>
    <input id="email" type="email" defaultValue="" tabIndex={0} autoFocus />
    <button className="btn" onClick={() => { /* subscribe() */ }} aria-label="Subscribe">Join {'{'}free{'}'}</button>
  </div>
  <p>No spam.<br />Unsubscribe any time.</p>
</>

Changes made

Attribute renames the converter applies

HTML attribute to JSX prop
HTMLJSX
classclassName
forhtmlFor
tabindextabIndex
readonlyreadOnly
maxlengthmaxLength
colspan / rowspancolSpan / rowSpan
autocompleteautoComplete
srcsetsrcSet
crossorigincrossOrigin
value on inputdefaultValue
checked on inputdefaultChecked
stroke-widthstrokeWidth
fill-rulefillRule
viewboxviewBox

The three rules behind every conversion

React's own introduction to JSX boils the differences down to three rules: return a single root element, close every tag, and write most attribute names in camelCase. Almost everything the converter does is one of those three.

The exceptions are reserved words and the dashed families. class and for are renamed because JavaScript reserves them, while aria- and data- attributes keep their HTML spelling.

What still needs a human

Inline scripts and event handler strings are code, not markup, so they need rewriting as functions in your component. The converter flags them instead of guessing.

Repeated blocks such as list items are often better as an array mapped to JSX. After converting, look for copy-pasted siblings and turn them into data plus a map call.

How it works

  1. Paste or type HTML into the input box. The JSX output updates on every keystroke.
  2. Optionally type a component name to wrap the output in an exported function component.
  3. Read the list of changes under the output; each note explains one rewrite the converter made.
  4. Copy the JSX into your component file and replace any empty event handlers with real functions.

Tips

Frequently asked questions

Why does React use className instead of class?

JSX compiles to JavaScript, where class is a reserved word. React therefore names the prop className. The same reasoning turns the label attribute for into htmlFor.

Do data- and aria- attributes change in JSX?

No. React's docs note that, for historical reasons, aria-* and data-* attributes are written exactly as in HTML, with dashes. Most other multi-word attributes become camelCase.

How do I write inline styles in JSX?

Pass an object to style with camelCase property names, for example style={{ fontWeight: 'bold', marginTop: 8 }}. React adds px to plain numbers for most properties. The outer braces open a JavaScript expression and the inner ones are the object.

Why do I get an error about multiple root elements?

A component can return only one element. Wrap siblings in a parent element or an empty fragment, written <> and </>. The converter does this for you when the HTML has more than one top-level node.

Is my HTML sent anywhere?

No. The conversion is plain JavaScript running in this page. Nothing you paste is uploaded or stored.

Related: React chart libraries, React icons guide, React Hook Form examples, React interview questions.

Start for free or see all free tools. We.Inc is free to start, with no card needed. AI building is on paid plans from $20 a month.

More in Free Tools

We.Inc is an AI-powered website builder you can resell under your own brand. Launch a branded client dashboard, bill on Stripe Connect, and deliver AI-generated websites in minutes. White-label plans start at $99 a month for 25 client sites, with a 7-day free trial and no per-site fees.

Product

Who It's For

Features

Resources

Company

View Sitemap