Convertisseur HTML → JSX / React, gratuit
Convertissez automatiquement du HTML en JSX compatible React. Gère class→className, for→htmlFor, objets style, gestionnaires d'événements, balises auto-fermantes et plus.
Entrée & sortie
Options
Comment ça marche
- Collez du HTML : saisissez un extrait HTML standard (divs, formulaires, tables ou blocs complets) dans la zone d'entrée.
- Choisissez les options : activez l'enveloppement React Fragment et le formatage pretty-print selon les besoins.
- Obtenez le JSX instantanément : le convertisseur transforme automatiquement
class→className,for→htmlFor, les chaînes style en objets style, et ferme les balises auto-fermantes. - Copiez dans votre projet : collez la sortie JSX directement dans vos composants React.
Pourquoi utiliser HTML → JSX ?
Lors de la migration de gabarits HTML vers React, la conversion manuelle est sujette aux erreurs. Oublier un seul className ou laisser une balise non fermée casse le build. Ce convertisseur gère automatiquement tous les changements requis, y compris la conversion des noms de propriétés CSS comme background-color en camelCase backgroundColor dans les attributs style, la transformation des chaînes de gestionnaires d'événements en références de fonctions et la fermeture correcte des éléments void. Cela accélère le prototypage, les migrations de code, et aide les développeurs peu familiers avec les différences de syntaxe JSX.
Conversions clés
- class → className: requis dans les composants React
- for → htmlFor: pour les éléments label
- chaînes style → objets: ex. :
"color:red"→{color:'red'} - Balises auto-fermantes:
<br>→<br /> - Enveloppement par Fragment:
<>…</>extérieur optionnel
What JSX actually is
JSX stands for "JavaScript XML." It's a syntactic extension to JavaScript invented by Jordan Walke at Facebook in 2013 as part of the original React announcement at JSConf US. JSX lets you write XML-like markup directly inside JavaScript code, <div className="hello">World</div>: and a transpiler (today almost always Babel) compiles it to plain function calls: React.createElement('div', {className: 'hello'}, 'World'). The browser never sees JSX directly; what ships is regular JavaScript.
Walke's original motivation was that template languages (Mustache, Handlebars, Angular's old directives) were second-class citizens of the host language, they couldn't use JavaScript's loops, conditionals or variables natively, so each one reinvented its own. JSX inverted the relationship: instead of templates that occasionally do JavaScript, it gave you JavaScript that occasionally does markup. The fact that {condition && <Item />} is a normal JS expression that returns a React element is the load-bearing idea.
Since React 17 (October 2020), the automatic JSX runtime means you no longer have to import React from 'react' in every file that uses JSX, Babel inserts the runtime imports automatically. JSX has also been adopted well beyond React itself: Preact, Solid, Qwik, Hono JSX, Million, Lit, and TypeScript's .tsx all consume the same syntax. The JSX draft spec at facebook.github.io/jsx is intentionally framework-agnostic.
The full list of HTML→JSX differences
- Reserved word renames.
class→className(becauseclassis reserved in JS).for→htmlFor(same reason,foris the loop keyword). These are the two everyone gets bitten by first. - All other attributes are camelCased.
tabindex→tabIndex,readonly→readOnly,maxlength→maxLength,contenteditable→contentEditable. - Two important exceptions stay kebab-case.
aria-*attributes (aria-label,aria-hidden) anddata-*attributes (data-testid) keep their HTML form. Same forxmlns. - Self-closing tags are mandatory for void elements:
<br>becomes<br />,<img>becomes<img />,<input>becomes<input />. JSX is XML-strict where HTML is forgiving. - Inline styles take an object, not a string.
style="color: red; background-color: blue"becomesstyle={{ color: 'red', backgroundColor: 'blue' }}. Note three things: double curly braces (one for the JSX expression, one for the object literal), camelCase property names, string values quoted. Numeric pixel values omit the unit:marginTop: 16, not'16px'. - Event handlers are camelCased and take function references.
onclick="handleClick()"becomesonClick={handleClick}: note the missing parentheses.onClick={handleClick()}would call handleClick at render time and assign its return value as the handler, which is almost always a bug. - Comments use
{/* … */}inside JSX, not<!-- … -->. The HTML comment syntax has no meaning inside JSX. - Fragments wrap multiple siblings. A component must return a single root, so multiple top-level elements need
<>…</>(or the longer<React.Fragment>…</React.Fragment>) wrapped around them. - Conditional rendering uses JS expressions.
{isVisible && <Item />}renders the item only if the condition is truthy;{condition ? <A /> : <B />}picks one of two. - Curly braces in text need escaping. The literal
{inside JSX text content is interpreted as the start of an expression. Use{'{'}or an HTML entity equivalent.
SVG, accessibility, and the rest
SVG works inside JSX with the same camelCase rule for most attributes, viewBox, strokeWidth, fillOpacity. The notable exceptions: xlink:href uses the special xlinkHref spelling (now deprecated in favour of plain href), and xmlns stays as is. Accessibility attributes follow ARIA's own kebab-case convention by exception: aria-label, aria-describedby, role all stay as written.
For CSS, JSX's inline style object is one option. Most production codebases use one of three richer alternatives: CSS Modules (per-file scoped class names compiled by the bundler), Tailwind CSS (utility classes that pass through cleanly via className), or CSS-in-JS libraries like styled-components, Emotion or Vanilla Extract. Tailwind has become the most common choice in new projects since 2022; Tailwind classes need no conversion at all when moving HTML to JSX, they pass through as ordinary className strings.
Common conversion gotchas
- Inline event handlers that call the function.
onclick="alert(1)"in HTML usually becomesonClick={() => alert(1)}in JSX, wrapped in an arrow function so the alert fires on click, not on render. A naive converter that producesonClick={alert(1)}will pop the alert at render time rather than when the user clicks. This converter handles the common cases but worth eyeballing the output. - HTML comments get dropped. Most JSX converters strip HTML comments rather than translating them to
{/* */}form, because the latter only works in specific positions inside JSX. Add comments back manually where you want them. - SVG attribute renames aren't always handled by automated converters.
stroke-width,fill-rule,clip-path,text-anchorall need camelCase forms, check the output carefully if you're pasting SVG from an icon set like Heroicons or Lucide. - Boolean attributes.
<input disabled>in HTML becomes<input disabled />in JSX.<input disabled="false">in HTML is actually disabled (any value enables it), but in JSXdisabled={false}is correctly off, the JSX semantic is more sensible than the HTML one. - HTML entities.
©works in JSX text content but using the literal Unicode character (©) is preferred. works the same. - The
tabindexcase. Should betabIndex. Easy to forget because the value is often0or-1and looks numeric, but the attribute name still needs camelCase.
When you'd reach for this
- Migrating server-rendered templates to React. Pasting a chunk of an existing site's HTML and getting JSX out is the canonical use case.
- Pulling in icons, badges, or design-tool exports. Heroicons, Lucide, Figma's "Copy as SVG" all give you raw HTML/SVG that needs the rename pass.
- Converting Tailwind UI / Flowbite / DaisyUI snippets from their HTML examples to JSX for a React project. The Tailwind classes pass through unchanged; only the structural attributes need conversion.
- Onboarding developers who know HTML but not JSX: seeing the mechanical rules applied automatically is faster than reading a list of differences.
- Quick prototyping when you've drafted markup in plain HTML for sketching purposes and want it inside a React component.
The output works for any JSX consumer, React, Preact, Solid, Qwik, Hono JSX, Million, Lit's html template literal (with minor adjustments). It does not work for React Native, which uses native primitive components like <View> and <Text> rather than HTML elements.
More questions
What's the difference between JSX and HTML?
HTML is a markup language the browser parses directly. JSX is a JavaScript expression syntax that compiles to React.createElement calls, it never reaches the browser as JSX. JSX looks XML-strict (every tag must close, attributes use camelCase) because it's parsed as JavaScript expressions, not as forgiving HTML. The visual similarity is intentional but the underlying semantics are quite different.
Do I still need to import React in every JSX file?
Not since React 17 (October 2020), which introduced the automatic JSX runtime. With it, Babel injects the necessary runtime imports for you, so files that only use JSX don't need a top-of-file import React from 'react'. The classic runtime is still available for older toolchains. Most new projects use the automatic runtime.
Can I use JSX without React?
Yes. JSX is a generic syntax with a draft spec at facebook.github.io/jsx, and many frameworks consume it: Preact, Solid, Qwik, Hono JSX, Million, Lit, and the htm tagged-template variant. The frameworks differ in what JSX compiles to (Preact uses h(…), Solid compiles to fine-grained reactive primitives, etc.) but the syntax is shared.
Why does style take an object instead of a string?
Because the JSX expression syntax already provides curly braces for embedding JavaScript values, and an object literal is the most natural JS representation of a property bag. The style object also allows numbers (most automatically get px) and JS expressions, which a string can't. The trade-off is the slightly awkward double-brace style={{ … }} syntax, outer braces for "this is a JSX expression," inner braces for the object literal.
Does anything get sent to a server?
No. The conversion logic is pure JavaScript that walks your HTML string and rewrites attributes, all in your browser. The HTML you paste never leaves the page, useful when migrating proprietary internal templates or component markup with API endpoints baked in.