--- name: elementor-to-generateblocks version: 1.0.0 description: Convert Elementor layouts to clean GenerateBlocks V2 format, eliminating DIVception author: Gaurav Tiwari updated: 2026-01-22 trigger: - Elementor to GenerateBlocks - convert Elementor - Elementor migration - clean up Elementor - simplify Elementor tags: - wordpress - generateblocks - elementor - conversion - migration --- # Elementor to GenerateBlocks Converter Convert bloated Elementor layouts to clean, semantic GenerateBlocks V2 blocks. ## Output Requirements **ALWAYS output converted blocks to a file, never inline in the chat.** - Output filename: `{section-name}-converted.html` (e.g., `hero-converted.html`) - For full page conversions: Split into multiple files by section - Include a brief summary in chat describing what was converted **Why file output?** - Converted block code is often 100+ lines - Easier to copy/paste into WordPress - Prevents truncation and formatting issues - Allows comparison with original Elementor output ## The DIVception Problem Elementor wraps everything in excessive nested divs with utility classes: ```html

Hello World

``` **Result:** 7 nested divs for a simple heading. ## GenerateBlocks Solution Same content, cleaner structure: ```html

Hello World

``` **Result:** 3 semantic elements. Clean, maintainable, fast. ## Conversion Rules ### 1. Flatten the Structure | Elementor Pattern | GenerateBlocks Equivalent | |-------------------|---------------------------| | `elementor-section` > `elementor-container` | Single `section` + inner `div` | | `elementor-column` > `elementor-widget-wrap` | Single `div` with flex/grid | | `elementor-widget` > `elementor-widget-container` | Direct content block | | Multiple wrapper divs | Remove all unnecessary wrappers | ### 2. Map Elementor Classes to Inline Styles | Elementor Class | CSS Property | |-----------------|--------------| | `elementor-section-boxed` | `max-width: var(--gb-container-width); margin: auto` | | `elementor-section-full_width` | `max-width: 100%` | | `elementor-column-gap-default` | `gap: 1rem` | | `elementor-column-gap-extended` | `gap: 2rem` | | `elementor-col-50` | `flex: 0 0 50%` or grid column | | `elementor-col-33` | `flex: 0 0 33.333%` or grid column | | `elementor-hidden-desktop` | `@media(min-width:1025px){display:none}` | | `elementor-hidden-tablet` | `@media(max-width:1024px){display:none}` | | `elementor-hidden-mobile` | `@media(max-width:767px){display:none}` | ### 3. Widget to Block Mapping | Elementor Widget | GenerateBlocks Block | |------------------|---------------------| | `elementor-widget-heading` | `generateblocks/text` with h1-h6 | | `elementor-widget-text-editor` | `generateblocks/text` with p/div | | `elementor-widget-button` (text only) | `generateblocks/text` with tagName="a" (no `htmlAttributes` for href) | | `elementor-widget-button` (with icon) | `generateblocks/element` with tagName="a" wrapping `text` + `shape` blocks | | `elementor-widget-image` | `generateblocks/media` (or `core/image` if caption needed) | | `elementor-widget-icon` | `generateblocks/shape` with inline SVG | | `elementor-widget-icon-box` | `generateblocks/element` container with `shape` + `text` blocks | | `elementor-widget-image-box` | `generateblocks/element` container | | `elementor-widget-spacer` | Remove (use margins/padding instead) | | `elementor-widget-divider` | `generateblocks/element` with border (or `core/separator`) | | Clickable card (with inner blocks) | `generateblocks/element` with tagName="a" + `htmlAttributes` for href | ### 4. Widgets Requiring Core Blocks Some Elementor widgets should convert to Core Blocks instead of GenerateBlocks: | Elementor Widget | Use Core Block | Reason | |------------------|----------------|--------| | `elementor-widget-video` | `core/video` or `core/embed` | Native player, embed support | | `elementor-widget-image-gallery` | `core/gallery` | Lightbox, columns, captions | | `elementor-widget-image-carousel` | `core/gallery` + CSS or third-party | Slider functionality | | `elementor-widget-audio` | `core/audio` | Native audio player | | `elementor-widget-table` | `core/table` | Semantic table structure | | `elementor-widget-blockquote` | `core/quote` | Semantic quote with citation | | `elementor-widget-code-highlight` | `core/code` | Preformatted code display | | `elementor-widget-text-path` | Keep as SVG | No Core equivalent | | `elementor-widget-lottie` | Keep as custom | No Core equivalent | | `elementor-widget-image` (with caption) | `core/image` | Built-in caption support | | `elementor-widget-tabs` | `core/details` or custom | Accordion/tabs functionality | | `elementor-widget-accordion` | `core/details` | Native disclosure widget | | `elementor-widget-toggle` | `core/details` | Native disclosure widget | | **Text with emojis** | `core/paragraph` | GenerateBlocks doesn't render emojis properly | **Rule:** Use GenerateBlocks for layout and styling. Use Core Blocks for specialized functionality (media players, embeds, tables, interactive elements). ### 4. Column Layouts **Elementor 2-column:** ```html
...
...
``` **GenerateBlocks equivalent:** ```html
``` ### 5. Common Elementor Patterns **Hero with background:** ```html
``` **Card grid:** ```html
``` ## Design Inference (When CSS Not Provided) When converting Elementor without CSS values, infer styles based on context: ### Default GeneratePress Design System Use these defaults when no specific styles are provided: **Colors:** - Primary: `#0073e6` (GeneratePress default accent) - Text: `#222222` - Muted text: `#757575` - Background: `#ffffff` - Light background: `#f7f8f9` - Border: `#e0e0e0` **Typography:** - Body: `17px`, line-height `1.7` - H1: `42px`, font-weight `600` - H2: `35px`, font-weight `600` - H3: `29px`, font-weight `600` - H4: `24px`, font-weight `600` **Spacing:** - Section padding: `60px` top/bottom - Container max-width: `var(--gb-container-width)` - Content padding: `20px` - Gap between elements: `20px` **Buttons:** - Padding: `15px 30px` - Border-radius: `4px` - Background: primary color - Hover: darken 10% ### Site-Specific Inference When the target site is known, extract design tokens from: 1. **Theme's style.css** - Primary colors, fonts, base sizes 2. **theme.json** (block themes) - Color palette, typography presets 3. **Existing pages** - Match the established visual language **Example inference for gauravtiwari.org:** ```json { "colors": { "primary": "#c0392b", "text": "#0a0a0a", "muted": "#5c5c5c", "background": "#ffffff", "lightBg": "#f5f5f3", "border": "#e5e5e5" }, "typography": { "body": "1rem", "h1": "clamp(2rem, 5vw, 3.5rem)", "h2": "clamp(1.5rem, 3vw, 2.5rem)", "fontWeight": "900 for headings" }, "spacing": { "sectionPadding": "4rem", "containerMax": "var(--gb-container-width)", "gap": "1rem to 2rem" }, "effects": { "borderRadius": "1rem for cards, 2rem for buttons", "hoverLift": "translateY(-6px)", "shadow": "0 20px 60px rgba(0,0,0,0.15)" } } ``` ## CRITICAL: No Extra HTML Comments **⛔ NEVER add HTML comments other than WordPress block markers.** The ONLY allowed comments are WordPress block delimiters: - `` and `` - `` and `` - `` and `` - `` and `` - `` and `` - `` and `` - `` and `` - Any other `` format **WRONG - These will break the block editor:** ```html ``` **CORRECT - Only block delimiters:** ```html

Hello World

``` Any extra HTML comments will **break the WordPress block editor** and cause parsing errors. This is non-negotiable. ## Critical Rules ### 1. htmlAttributes MUST Use Array Format **htmlAttributes MUST be an array of objects, NOT a plain object:** ```json // ✅ CORRECT - Array of objects "htmlAttributes": [ {"attribute": "href", "value": "/contact/"}, {"attribute": "target", "value": "_blank"}, {"attribute": "id", "value": "section-id"} ] // ❌ WRONG - Plain object (causes block editor recovery errors) "htmlAttributes": {"href": "/contact/", "target": "_blank"} ``` **linkHtmlAttributes** (for media blocks) uses the same array format. ### 2. Always Include Both styles and css Every block needs: - `styles` object with camelCase properties (supports responsive keys like `"@media (max-width:1024px)":{...}`) - `css` string with minified CSS (kebab-case, **alphabetically sorted**, base styles only) - The `css` attribute must **NOT** contain hover states or transitions (the plugin generates those from the `styles` object) - Exceptions that go in `css`: pseudo-elements (::before/::after), media queries, animations, parent hover targeting children ### 3. Element Blocks Need className Add `"className":"gb-element"` to all element block attributes. HTML class order: `gb-element-{id} gb-element`: ```html
...
``` ### 4. Text `` vs Element `` Links | Block Type | `htmlAttributes` for href | Use Case | |-----------|--------------------------|----------| | `generateblocks/text` with `tagName: "a"` | **No** - plugin manages link internally | Plain text buttons/links (no inner blocks) | | `generateblocks/element` with `tagName: "a"` | **Yes** - `[{"attribute":"href","value":"/url/"}]` | Containers wrapping inner blocks (cards, icon buttons) | ### 5. SVG Icons Use Shape Blocks Convert Elementor icons to `generateblocks/shape` (not `generateblocks/element` with raw SVG): ```html ``` ### 6. Lists Use `core/list` with `.list` Class Convert Elementor list widgets to native WordPress list block: ```html ``` ### 7. Container Width with CSS Variable Use `--gb-container-width` for inner container width and `align: "full"` on parent section: ```json {"align": "full", "styles": {"maxWidth": "var(\u002d\u002dgb-container-width)"}} ``` ### 8. Use Semantic HTML Replace Elementor's generic divs with proper tags: | Content Type | Tag | |--------------|-----| | Page section | `section` | | Header area | `header` | | Footer area | `footer` | | Navigation | `nav` | | Main content | `article` | | Sidebar | `aside` | | Card wrapper | `div` or `a` (if clickable) | ### 9. Remove Spacers Never convert `elementor-widget-spacer` to a block. Use: - `marginBottom` on preceding element - `marginTop` on following element - `gap` on parent container ### 10. Flatten Icon Boxes **Elementor icon box (simplified):** ```html

Title

Description

``` **GenerateBlocks:** ```html

Title

Description

``` ## Conversion Workflow 1. **Analyze Elementor HTML** - Identify sections, columns, widgets 2. **Extract content** - Isolate actual text, images, links 3. **Determine layout** - Map column structure to grid/flex 4. **Apply design tokens** - Use provided CSS or infer from site 5. **Build blocks** - Create GenerateBlocks with inline styles 6. **Test responsive** - Add media queries for breakpoints 7. **Validate** - Ensure no HTML comments except block markers ## Performance Benefits | Metric | Elementor | GenerateBlocks | |--------|-----------|----------------| | DOM nodes | 50-100+ per section | 5-15 per section | | CSS file size | 200KB+ | 0 (inline) | | Render blocking | Multiple CSS files | None | | First paint | Delayed | Fast | | CLS issues | Common | Rare | ## Font Awesome to SVG Replace Elementor's Font Awesome icons with inline SVGs: ```html ``` See [SVG Icons Reference](../generateblocks-layouts/references/svg-icons.md) for common icons.