Best Practices

Get Perfect Conversions

How to structure your HTML and write AI prompts so every page converts to native Elementor widgets with full visual fidelity.

Tested with all major AI builders:

ChatGPT / Codex Claude / Stitch Lovable Vercel v0 Bolt Manus Cursor

1 The AI Prompt to Use

Paste this into ChatGPT, Claude, Lovable, v0, or any AI code generator. It produces HTML that converts at 90%+ native widget rate:

Copy this prompt

Build me a complete, single-file HTML page for [describe your page].

Requirements:
- Single HTML file with all CSS in one <style> block in the <head>
- Use semantic HTML: <section>, <article>, <h1>-<h6>, <p>, <ul>, <li>
- Each page section should be a <section> tag as a direct child of <body> or <main>
- For multi-column layouts use display:flex with flex children
- CSS Grid with grid-template-columns is fine for card grids
- Use CSS classes for styling (not inline styles)
- Load Google Fonts via a <link> tag in <head>
- All colors as hex (#1a1a2e) or rgb/rgba — avoid hsl() if possible
- Buttons should be <a> tags with background-color, padding, border-radius
- Images should use absolute URLs (https://...)
- For tabbed content: use buttons with onclick that toggle panel visibility by id
- For FAQ/accordion: use <details>/<summary> or visible question + hidden answer pattern
- For contact forms: use native <form> with <input>/<textarea> elements
- Include a <script> at the bottom for any interactive behavior
- Make it fully self-contained — no external CSS files or JS files

💡

CSS variables, CSS Grid, clamp(), calc(), HSL colors, and Tailwind CDN all work. The converter resolves variables, converts HSL to hex, handles grid layouts, and preprocesses Tailwind utility classes. The prompt above just produces the cleanest results.

2 Page Structure

The converter maps your HTML hierarchy directly to Elementor containers. A clean, flat structure means more native widgets and fewer HTML fallbacks.

✓ Do

  • Use <section> for each page section
  • Put all CSS in a single <style> block
  • Use CSS classes for styling (.hero, .card)
  • Separate sections for hero, features, pricing, footer
  • Meaningful heading hierarchy: h1, h2, h3
  • Plain text in <p> tags, lists in <ul>/<li>

✗ Don’t

  • Deeply nested divs (5+ levels) for visual layout
  • External CSS files (./style.css)
  • Everything inside one giant wrapper div
  • Multiple <h1> tags on one page
  • Text content without a wrapper tag

3 Layout & Columns

Flex columns (recommended)

The converter detects flex rows and maps each child to an Elementor column container:

Flex row with equal columns

<div class="features-grid">
  <div class="feature-card">...</div>
  <div class="feature-card">...</div>
  <div class="feature-card">...</div>
</div>

<!-- CSS -->
.features-grid { display: flex; gap: 24px; }
.feature-card { flex: 1; }

CSS Grid (also works)

Grid layouts with grid-template-columns: repeat(N, 1fr) are automatically chunked into N-column rows:

Grid with 3 columns, 6 items = 2 rows of 3

.card-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
}

Section widths

Use max-width on a centered inner wrapper to control content width:

Section with max-width centering

<section style="padding:80px 24px; background:#f8f9fa;">
  <div class="container" style="max-width:1120px; margin:0 auto;">
    <!-- content here -->
  </div>
</section>

4 Styling & Colors

✓ All supported

  • Hex colors: #1a1a2e, #fff
  • RGB/RGBA: rgba(0,0,0,0.5)
  • HSL/HSLA: hsl(220, 20%, 6%)
  • CSS variables:
  • Linear & radial gradients
  • Google Fonts via <link>
  • Font sizes in px, em, rem
  • clamp() for responsive sizing
  • Box shadows, border-radius, opacity
  • Dark themes (dark body background)

⚠ Best to avoid

  • Modern HSL without commas: hsl(220 20% 6%) — works but hsl(220, 20%, 6%) is safer
  • Local/self-hosted fonts via @font-face
  • color-mix(), oklch() — too new
  • backdrop-filter on many elements (performance)

💡

CSS variables are fully resolved. If your :root defines --primary: #6366f1 and elements use color: , the converter resolves it to #6366f1 in the Elementor output. No manual replacement needed.

5 Interactive Elements

Tabs (day switchers, monthly/yearly toggles, category tabs)

Use buttons with onclick that toggle panel visibility. The converter detects this pattern and creates a native Elementor Tabs widget:

Tab pattern (auto-detected)

<div class="tab-buttons">
  <button onclick="showTab('tab1')">Monthly</button>
  <button onclick="showTab('tab2')">Yearly</button>
</div>
<div id="tab1" style="display:block">...monthly content...</div>
<div id="tab2" style="display:none">...yearly content...</div>

<!-- Also works with data-tab, aria-controls, href="#id" + role="tab" -->

FAQ / Accordion

Use <details>/<summary> or a question+hidden-answer pattern. Both are auto-detected as Elementor Accordion widgets:

FAQ pattern (auto-detected)

<!-- Option A: native HTML details/summary -->
<details>
  <summary>What does this product do?</summary>
  <p>It converts HTML pages to Elementor templates.</p>
</details>

<!-- Option B: class-based FAQ pattern -->
<div class="faq-item">
  <button class="faq-q">What does this product do?</button>
  <div class="faq-a" style="max-height:0; overflow:hidden">
    <p>It converts HTML pages to Elementor templates.</p>
  </div>
</div>

Contact forms

Native HTML forms with <input>, <textarea>, and <button type="submit"> are preserved in full:

Form (preserved with all fields)

<form class="contact-form">
  <input type="text" placeholder="Name" required>
  <input type="email" placeholder="Email" required>
  <textarea placeholder="Message"></textarea>
  <button type="submit">Send</button>
</form>

6 What Converts to What

The converter maps HTML elements to native Elementor widgets wherever possible:

HTML Pattern Elementor Widget Notes
<h1> – <h6> Heading Font, color, alignment, size all mapped
<p>, text blocks Text Editor Full rich text with inline formatting
<a> styled as button Button Needs background-color + padding
<img> Image Alt text, dimensions, border-radius preserved
<img> with position:absolute; inset:0 Container background Cover images promoted to container bg automatically
<iframe> (YouTube/Vimeo) Video Video ID extracted automatically
div/section containers Container Flex, grid, background, padding, border all mapped
CSS Grid (repeat(N, 1fr)) Container rows Auto-chunked into N-column rows
Button tabs + id panels Tabs onclick, data-tab, aria-controls all detected
Question + hidden answer Accordion details/summary, faq-item, collapsible patterns
Thin horizontal <div> Divider 1-4px height with background-color
Font Awesome icons (<i class="fas...">) Icon Maps to Elementor's native icon library
Decorative SVGs (position:absolute) Overlay Positioned correctly via injected CSS
<form> with inputs HTML widget All form fields preserved inside the form
Inline SVG icons HTML widget Pixel-perfect, fully editable as raw HTML
<nav>, sticky header HTML widget Nav menu is Elementor Pro only
Slider/carousel Static content First slide extracted, nav arrows stripped

HTML widgets are pixel-perfect — they render exactly like the original. They’re fully editable as raw HTML inside Elementor’s editor.

7 Images & Media

Use absolute URLs

Images with absolute URLs (https://...) work immediately after conversion. The converter also resolves relative paths (./photo.jpg) against the page’s base URL — but uploading images to your WordPress Media Library gives the best results.

Unsplash and placeholder images work great for prototyping. Ask your AI to use https://images.unsplash.com/photo-... URLs. They render immediately in both the original HTML and the converted Elementor page.

Cover images

An <img> with position:absolute; inset:0 (or width:100%; height:100%) inside a positioned parent is automatically promoted to the Elementor container’s background image with background-size: cover.

8 What to Avoid

External CSS & JS files

The converter reads inline <style> blocks only. External files (./style.css, ./app.js) are invisible. Keep everything in one file.

Extremely deep nesting

More than 4-5 levels of nested divs for purely decorative purposes reduces accuracy. Each extra level adds a container wrapper.

CSS animations on text content

Elements with CSS animations (animation: property) and visible text are kept as HTML widgets to preserve the animation. To get editable text, separate the animated layer from the text:

Separating animated backgrounds from text

<section style="position:relative; padding:100px 24px;">
  <!-- Animated layer (becomes HTML widget) -->
  <div style="position:absolute; inset:0; animation:glow 8s infinite; pointer-events:none;">
    ...
  </div>
  <!-- Text (becomes native heading/text widgets) -->
  <div style="position:relative; z-index:1;">
    <h1>Your Heading</h1>
    <p>Your text here.</p>
  </div>
</section>

Tailwind CDN

Tailwind utility classes (flex, grid, w-full, bg-blue-600, p-4, etc.) are supported — the converter includes a Tailwind preprocessor that translates them to CSS. However, a <style> block with explicit CSS classes produces slightly more predictable results for complex layouts.

9 Pre-Conversion Checklist

Before converting, quickly verify:

  • ✔ Page opens correctly in a browser
  • ✔ All CSS is inside a <style> block (not in external files)
  • ✔ Images use absolute URLs or are hosted online
  • ✔ Google Fonts are loaded via a <link> tag in <head>
  • ✔ File size is under 5MB
  • ✔ Interactive elements (tabs, accordion) work in the browser
  • ✔ No references to external local files

💡

Tip: Ask your AI to generate a fully self-contained HTML file. All CSS inline in a <style> tag, all JS in a <script> tag at the bottom, no external dependencies except Google Fonts and image URLs.

Ready to convert?

Install the plugin, paste your HTML, and have your Elementor template in seconds.