html-to-generateblocks

Convert HTML/CSS layouts to GenerateBlocks V2 format with inline styles

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "html-to-generateblocks" with this command: npx skills add wpgaurav/generateblocks-skills/wpgaurav-generateblocks-skills-html-to-generateblocks

HTML to GenerateBlocks V2 Conversion

Convert HTML/CSS layouts to GenerateBlocks V2 format using inline styles in block attributes.

Output Requirements

ALWAYS output converted blocks to a file, never inline in the chat.

  • Output filename: {original-name}-converted.html (e.g., hero-converted.html)
  • For large 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 side-by-side comparison with original

Core Principle

Use both styles and css attributes:

  • styles: Basic properties (padding, margin, colors, display, flex, grid). Supports responsive keys like "@media (max-width:1024px)":{...}
  • css: Base styles only (alphabetically sorted). Exceptions that go in css: pseudo-elements (::before/::after), media queries, animations, parent hover targeting children

The css attribute must NOT contain hover states or transitions - the plugin generates those from the styles object.

Never use BEM or custom classes - all styling goes in block attributes.

When to Use Core Blocks

For HTML elements not available in GenerateBlocks, use WordPress Core Blocks:

HTML ElementConvert ToReason
<video>core/videoNative player controls, autoplay, loop
<audio>core/audioNative audio player
<iframe> (YouTube, Vimeo)core/embedoEmbed support, responsive sizing
<table>core/tableSemantic table structure
<figure> with <figcaption>core/imageBuilt-in caption support
<blockquote> with citecore/quoteSemantic quote with citation
<pre> / <code>core/codePreformatted code display
<ul> / <ol> (semantic lists)core/listUse with .list class
<hr>core/separatorHorizontal rule
Gallery layoutscore/galleryLightbox, columns, captions
Background image sectionscore/coverParallax, overlay, focal point
Text with emojiscore/paragraphGenerateBlocks doesn't render emojis properly

Conversion rule: Use GenerateBlocks for layout containers and styled text. Use Core Blocks for specialized content types that have built-in functionality (players, embeds, tables, etc.).

CRITICAL: htmlAttributes Format

htmlAttributes MUST be an array of objects, NOT a plain object:

// ✅ 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:

"linkHtmlAttributes": [
  {"attribute": "href", "value": "/product/"},
  {"attribute": "target", "value": "_blank"}
]

Block Structure

Standard Element Block

Element blocks add "className":"gb-element" to attributes. HTML class order: gb-element-{id} gb-element:

<!-- wp:generateblocks/element {"uniqueId":"elem001","tagName":"div","styles":{"display":"flex","gap":"1rem","padding":"2rem"},"css":".gb-element-elem001{display:flex;gap:1rem;padding:2rem}@media(max-width:768px){.gb-element-elem001{flex-direction:column}}","className":"gb-element"} -->
<div class="gb-element-elem001 gb-element">
    <!-- Inner content -->
</div>
<!-- /wp:generateblocks/element -->

Text Block (for headings, paragraphs, links)

<!-- wp:generateblocks/text {"uniqueId":"text001","tagName":"h2","styles":{"fontSize":"2rem","fontWeight":"900","color":"#0a0a0a"},"css":".gb-text-text001{font-size:2rem;font-weight:900;color:#0a0a0a}"} -->
<h2 class="gb-text gb-text-text001">Heading Text</h2>
<!-- /wp:generateblocks/text -->

Link as Card Wrapper

Cards with inner blocks use generateblocks/element (not text) with tagName: "a":

<!-- wp:generateblocks/element {"uniqueId":"card001","tagName":"a","htmlAttributes":[{"attribute":"href","value":"/services/"}],"styles":{"backgroundColor":"white","borderRadius":"1rem","display":"flex","flexDirection":"column","padding":"2rem","textDecoration":"none"},"css":".gb-element-card001{background-color:white;border-radius:1rem;display:flex;flex-direction:column;padding:2rem;text-decoration:none}","className":"gb-element"} -->
<a class="gb-element-card001 gb-element" href="/services/">
    <!-- Inner blocks (text, media, shape) -->
</a>
<!-- /wp:generateblocks/element -->

Plain text links (no inner blocks) use generateblocks/text with tagName: "a" — no htmlAttributes for href:

<!-- wp:generateblocks/text {"uniqueId":"link001","tagName":"a","styles":{"color":"#c0392b","fontSize":"0.9375rem","fontWeight":"600","textDecoration":"none"},"css":".gb-text-link001{color:#c0392b;font-size:0.9375rem;font-weight:600;text-decoration:none}"} -->
<a class="gb-text gb-text-link001">Learn more</a>
<!-- /wp:generateblocks/text -->

Media/Image Block

<!-- wp:generateblocks/media {"uniqueId":"img001","mediaType":"image","htmlAttributes":[{"attribute":"src","value":"https://example.com/image.jpg"},{"attribute":"alt","value":"Description"},{"attribute":"loading","value":"lazy"},{"attribute":"width","value":"600"},{"attribute":"height","value":"400"}],"styles":{"display":"block","width":"100%"},"css":".gb-media-img001{display:block;width:100%}"} -->
<img class="gb-media gb-media-img001" src="https://example.com/image.jpg" alt="Description" loading="lazy" width="600" height="400" />
<!-- /wp:generateblocks/media -->

Text <a> vs Element <a> Links

Block TypehtmlAttributes for hrefhref in HTMLUse Case
generateblocks/text with tagName: "a"No - plugin manages link internallyNoPlain text buttons/links (no inner blocks)
generateblocks/element with tagName: "a"Yes - [{"attribute":"href","value":"/url/"}]YesContainers wrapping inner blocks (cards, icon buttons)

Rule: Text <a> blocks are leaf blocks - the link URL is managed by the editor UI. Element <a> blocks are containers - they need explicit htmlAttributes for the href.

Buttons with icons use generateblocks/element (tagName a) wrapping generateblocks/text + generateblocks/shape blocks. Plain text buttons use generateblocks/text.

Styles vs CSS Decision Matrix

FeatureUse stylesUse css
Layout (display, flex, grid)Also in CSS (base styles)
Spacing (padding, margin, gap)Also in CSS (base styles)
Colors (background, text)Also in CSS (base styles)
Typography (font-size, weight)Also in CSS (base styles)
Basic borders, border-radiusAlso in CSS (base styles)
Responsive overrides"@media (max-width:1024px)":{...}Also in CSS
Hover states✅ via styles objectNever in css (plugin generates)
Transitions✅ via styles objectNever in css (plugin generates)
Pseudo-elements (::before/::after)✅ Only CSS
Media queries✅ (simple overrides)✅ (complex rules)
Animations (@keyframes)✅ Only CSS
Parent hover targeting children✅ Only CSS (in child's css)

Pattern: Put base properties in both styles and css (alphabetically sorted). The css attribute contains base styles plus exceptions (pseudo-elements, media queries, animations, parent-hover-child selectors). Never put hover states or transitions in css.

Common Patterns

Card with Animated Underline

Cards with inner blocks use generateblocks/element. Pseudo-elements (::after) and parent-hover-pseudo go in css. Hover states and transitions do NOT go in css.

<!-- wp:generateblocks/element {"uniqueId":"card001","tagName":"a","htmlAttributes":[{"attribute":"href","value":"/link/"}],"styles":{"backgroundColor":"white","border":"1px solid transparent","borderRadius":"1rem","display":"flex","flexDirection":"column","padding":"2rem","position":"relative","textDecoration":"none"},"css":".gb-element-card001{background-color:white;border:1px solid transparent;border-radius:1rem;display:flex;flex-direction:column;padding:2rem;position:relative;text-decoration:none}.gb-element-card001::after{background:#c0392b;bottom:0;content:'';height:3px;left:0;position:absolute;transform:scaleX(0);transform-origin:left;transition:transform 0.4s cubic-bezier(0.16, 1, 0.3, 1);width:100%}.gb-element-card001:hover::after{transform:scaleX(1)}","className":"gb-element"} -->
<a class="gb-element-card001 gb-element" href="/link/">
    <!-- Inner blocks -->
</a>
<!-- /wp:generateblocks/element -->

Grid Layout (Responsive)

<!-- wp:generateblocks/element {"uniqueId":"grid001","tagName":"div","styles":{"display":"grid","gridTemplateColumns":"repeat(4, minmax(0, 1fr))","gap":"1rem"},"css":".gb-element-grid001{display:grid;grid-template-columns:repeat(4, minmax(0, 1fr));gap:1rem}@media(max-width:1024px){.gb-element-grid001{grid-template-columns:repeat(2, minmax(0, 1fr))!important}}@media(max-width:768px){.gb-element-grid001{grid-template-columns:1fr!important}}"} -->
<div class="gb-element gb-element-grid001">
    <!-- Grid items -->
</div>
<!-- /wp:generateblocks/element -->

Icon (Shape Block with SVG)

SVG icons use generateblocks/shape. Two valid approaches:

Approach 1: styles.svg object (plugin generates .gb-shape-{id} svg{...} CSS):

<!-- wp:generateblocks/shape {"uniqueId":"icon001","styles":{"alignItems":"center","backgroundColor":"#f5f5f3","borderRadius":"1rem","color":"#c0392b","display":"flex","height":"3.5rem","justifyContent":"center","width":"3.5rem","svg":{"fill":"none","height":"1.5rem","stroke":"currentColor","width":"1.5rem"}},"css":".gb-shape-icon001{align-items:center;background-color:#f5f5f3;border-radius:1rem;color:#c0392b;display:flex;height:3.5rem;justify-content:center;width:3.5rem}.gb-shape-icon001 svg{fill:none;height:1.5rem;stroke:currentColor;width:1.5rem}.gb-element-card001:hover .gb-shape-icon001{background-color:#c0392b;color:white;transform:scale(1.05) rotate(-3deg)}"} -->
<span class="gb-shape gb-shape-icon001"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M13 2 3 14h9l-1 8 10-12h-9l1-8z"/></svg></span>
<!-- /wp:generateblocks/shape -->

Approach 2: Simple styles (for quick inline icons):

<!-- wp:generateblocks/shape {"uniqueId":"check001","styles":{"color":"#10b981","height":"20px","width":"20px"},"css":".gb-shape-check001{color:#10b981;height:20px;width:20px}"} -->
<span class="gb-shape gb-shape-check001"><svg stroke-linejoin="round" stroke-linecap="round" stroke-width="3" stroke="currentColor" fill="none" viewBox="0 0 24 24"><polyline points="20 6 9 17 4 12"></polyline></svg></span>
<!-- /wp:generateblocks/shape -->

Parent hover targeting icons is written in the shape block's css (as shown in Approach 1).

Featured Card (Dark, Span Multiple Columns)

<!-- wp:generateblocks/element {"uniqueId":"feat001","tagName":"div","styles":{"background":"linear-gradient(135deg, #0a0a0a 0%, #1a1a1a 100%)","borderRadius":"1rem","display":"flex","flexDirection":"column","gap":"1rem","gridColumn":"span 2","gridRow":"span 2","minHeight":"26rem","padding":"2rem","position":"relative"},"css":".gb-element-feat001{background:linear-gradient(135deg, #0a0a0a 0%, #1a1a1a 100%);border-radius:1rem;display:flex;flex-direction:column;gap:1rem;grid-column:span 2;grid-row:span 2;min-height:26rem;padding:2rem;position:relative}.gb-element-feat001::before{background:radial-gradient(circle at 100% 0%, rgba(192, 57, 43, 0.2) 0%, transparent 60%);content:'';height:100%;pointer-events:none;position:absolute;right:0;top:0;width:60%}.gb-element-feat001>*{position:relative;z-index:1}@media(max-width:1024px){.gb-element-feat001{grid-column:span 2;grid-row:span 1;min-height:auto}}@media(max-width:768px){.gb-element-feat001{grid-column:span 1}}","className":"gb-element"} -->
<div class="gb-element-feat001 gb-element">
    <!-- Featured card content -->
</div>
<!-- /wp:generateblocks/element -->

Badge (Absolute Position)

<!-- wp:generateblocks/text {"uniqueId":"badge001","tagName":"span","styles":{"backgroundColor":"#c0392b","borderRadius":"2rem","color":"white","fontSize":"0.75rem","fontWeight":"600","letterSpacing":"0.05em","padding":"0.25rem 0.625rem","position":"absolute","right":"1rem","textTransform":"uppercase","top":"1rem"},"css":".gb-text-badge001{background-color:#c0392b;border-radius:2rem;color:white;font-size:0.75rem;font-weight:600;letter-spacing:0.05em;padding:0.25rem 0.625rem;position:absolute;right:1rem;text-transform:uppercase;top:1rem}"} -->
<span class="gb-text gb-text-badge001">Recommended</span>
<!-- /wp:generateblocks/text -->

Dynamic Content with Query Blocks

For sections with dynamic WordPress posts, use native query blocks with GenerateBlocks for styling:

<!-- wp:query {"queryId":1,"query":{"perPage":12,"postType":"post","order":"desc","orderBy":"date","taxQuery":{"category":{"terms":[],"operator":"NOT IN"}}}} -->
<div class="wp-block-query">
    <!-- wp:post-template {"style":{"spacing":{"blockGap":"1rem"}}} -->

        <!-- wp:generateblocks/element {"uniqueId":"post001","tagName":"a","styles":{"backgroundColor":"white","border":"1px solid #e5e5e5","borderRadius":"1rem","display":"flex","flexDirection":"column","overflow":"hidden","textDecoration":"none"},"css":".gb-element-post001{background-color:white;border:1px solid #e5e5e5;border-radius:1rem;display:flex;flex-direction:column;overflow:hidden;text-decoration:none}","className":"gb-element"} -->
        <a class="gb-element-post001 gb-element">
            <!-- wp:post-featured-image {"isLink":false,"aspectRatio":"12/5"} /-->

            <!-- wp:generateblocks/element {"uniqueId":"post002","tagName":"div","styles":{"display":"flex","flex":"1","flexDirection":"column","padding":"1rem"},"css":".gb-element-post002{display:flex;flex:1;flex-direction:column;padding:1rem}","className":"gb-element"} -->
            <div class="gb-element-post002 gb-element">
                <!-- wp:post-title {"isLink":false,"style":{"typography":{"fontSize":"1.125rem","fontWeight":"700"}}} /-->
                <!-- wp:post-excerpt {"excerptLength":14} /-->
            </div>
            <!-- /wp:generateblocks/element -->
        </a>
        <!-- /wp:generateblocks/element -->

    <!-- /wp:post-template -->
</div>
<!-- /wp:query -->

Unique ID Convention

  • Format: {section}{number}{letter} (e.g., hero001a, serv023, tool014)
  • Section prefix: 3-4 characters (hero, serv, tool, blog, feat)
  • Number: Sequential 001-999
  • Optional letter: For nested elements (a, b, c)

Conversion Workflow

  1. Read original HTML/CSS - Understand structure and styles
  2. Identify sections - Break into logical components
  3. Map BEM classes to blocks - Each .block__element becomes a GenerateBlocks element
  4. Extract base styles - Put in styles attribute
  5. Extract complex styles - Put in css attribute (pseudo-elements, media queries, parent-hover-child). Never put hover states or transitions in css
  6. Create unique IDs - Follow convention
  7. Test responsive behavior - Ensure media queries work
  8. Handle dynamic content - Use WordPress query blocks

CSS Syntax Rules

In styles attribute (JavaScript object):

{
  "display": "flex",
  "flexDirection": "column",
  "backgroundColor": "#ffffff",
  "borderRadius": "1rem",
  "marginBottom": "2rem"
}

In css attribute (CSS string):

.gb-element-id{background-color:#ffffff;border-radius:1rem;display:flex;flex-direction:column;margin-bottom:2rem}@media(max-width:768px){.gb-element-id{flex-direction:row}}

Rules:

  • CSS must be minified (no line breaks, minimal spaces)
  • Properties must be alphabetically sorted
  • Contains base styles only — no hover states, no transitions
  • Exceptions: pseudo-elements (::before/::after), media queries, animations, parent hover targeting children

Responsive Patterns

Mobile-First Grid

.gb-element-grid{display:grid;grid-template-columns:1fr}@media(min-width:768px){.gb-element-grid{grid-template-columns:repeat(2, minmax(0, 1fr))}}@media(min-width:1024px){.gb-element-grid{grid-template-columns:repeat(4, minmax(0, 1fr))}}

Desktop-First Grid (Match Original)

.gb-element-grid{display:grid;grid-template-columns:repeat(4, minmax(0, 1fr));gap:1rem}@media(max-width:1024px){.gb-element-grid{grid-template-columns:repeat(2, minmax(0, 1fr))!important}}@media(max-width:768px){.gb-element-grid{grid-template-columns:1fr!important}}

Sticky Sidebar

.gb-element-sidebar{position:sticky;top:calc(var(--header-height, 80px) + 1rem)}@media(max-width:1024px){.gb-element-sidebar{position:static}}

CRITICAL: No Extra HTML Comments

⛔ NEVER add HTML comments other than WordPress block markers.

The ONLY allowed comments are WordPress block delimiters:

  • <!-- wp:generateblocks/element {...} --> and <!-- /wp:generateblocks/element -->
  • <!-- wp:generateblocks/text {...} --> and <!-- /wp:generateblocks/text -->
  • <!-- wp:generateblocks/media {...} --> and <!-- /wp:generateblocks/media -->
  • <!-- wp:generateblocks/shape {...} --> and <!-- /wp:generateblocks/shape -->
  • <!-- wp:image {...} --> and <!-- /wp:image -->
  • <!-- wp:video {...} --> and <!-- /wp:video -->
  • <!-- wp:embed {...} --> and <!-- /wp:embed -->
  • Any other <!-- wp:{namespace}/{block} --> format

WRONG - These will break the block editor:

<!-- This is a card -->
<!-- Section header -->
<!-- Hero content goes here -->
<!-- Button wrapper -->

CORRECT - Only block delimiters:

<!-- wp:generateblocks/element {"uniqueId":"card001",...} -->
<div class="gb-element gb-element-card001">
    <!-- wp:image {"id":123} -->
    <figure class="wp-block-image"><img src="image.jpg" alt=""/></figure>
    <!-- /wp:image -->
</div>
<!-- /wp:generateblocks/element -->

Any extra HTML comments will break the WordPress block editor and cause parsing errors. This is non-negotiable. Do NOT add descriptive comments, section labels, or any other HTML comments.

Design Inference (When CSS Not Provided)

When converting HTML without explicit CSS values, infer styles based on context:

GeneratePress Defaults:

  • Primary: #0073e6
  • Text: #222222, Muted: #757575
  • Body: 17px, line-height 1.7
  • H1: 42px, H2: 35px, H3: 29px
  • Section padding: 60px
  • Container max-width: var(--gb-container-width)

gauravtiwari.org Design System:

  • Primary: #c0392b
  • Text: #0a0a0a, Muted: #5c5c5c
  • Background: #ffffff, Light: #f5f5f3
  • Headings: font-weight 900, letter-spacing -0.03em
  • Section padding: 4rem
  • Card radius: 1rem, Button radius: 2rem
  • Hover lift: translateY(-6px)
  • Shadow: 0 20px 60px rgba(0,0,0,0.15)

Common Gotchas

  1. No HTML comments except block markers - Breaks WordPress block editor
  2. Always escape quotes in CSS strings - Use single quotes for content, attr values
  3. Duplicate properties - Put in both styles and css for consistency
  4. CSS alphabetically sorted - Properties in the css string must be sorted alphabetically
  5. No hover/transitions in css - The plugin generates hover states and transitions from the styles object. Never put these in the css attribute
  6. Cards with inner blocks = element block - Use generateblocks/element (not text) for cards containing other blocks. Text blocks are leaf blocks (no inner blocks)
  7. Text <a> = no htmlAttributes for href - Link URL managed by editor UI. Element <a> = use htmlAttributes for href
  8. SVG icons = shape blocks - Use generateblocks/shape for SVGs, not generateblocks/element with raw SVG inside
  9. Pseudo-elements need content - content:'' for ::before/::after (these go in css)
  10. Parent hover targeting children - Written in the child's css: .gb-element-card001:hover .gb-text-title001{color:#c0392b}
  11. Gradients only in CSS - Can't use in styles attribute
  12. CSS variables work - Use var(--custom-property) freely. Use \u002d\u002d for -- in JSON
  13. Element blocks need className - Add "className":"gb-element" to element block attributes
  14. Use !important sparingly - Only for overriding at breakpoints
  15. Lists use core/list with .list class - Convert <ul>/<ol> to native WordPress list block with className: "list"
  16. Use --gb-container-width for inner containers - Set inner container width using the CSS variable; add align: "full" to parent section
  17. Buttons with icons - Use generateblocks/element (tagName a) wrapping generateblocks/text + generateblocks/shape blocks. Plain text buttons use generateblocks/text

Performance Notes

  • Inline styles are fast (no external CSS file)
  • Each block's CSS is scoped to its unique ID
  • GenerateBlocks automatically deduplicates common styles
  • Media queries only load when needed
  • Use content-visibility: auto for off-screen sections

Example: Complete Hero Section

See to-convert/home-hero-v2.html for a complete real-world example with:

  • Complex grid layout
  • Multiple nested components
  • Responsive breakpoints
  • Hover effects
  • Icon fonts
  • Images with overlays

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

generateblocks-layouts

No summary provided by upstream source.

Repository SourceNeeds Review
General

figma-to-generateblocks

No summary provided by upstream source.

Repository SourceNeeds Review
General

Doc2slides

Convert documents to slides. PDF/Word/Markdown → PPT. Runs on your machine, no external APIs.

Registry SourceRecently Updated
380Profile unavailable
General

Blog Master — Universal SEO Blog Writing System

Write SEO-optimized blog posts for any niche and publish them to WordPress, Google Business Profile, and Google Blogger. Includes AEO triggers for AI search...

Registry SourceRecently Updated
9410Profile unavailable