The Webflow rulebook
Full rules for AI
The complete rules, word for word, exactly as HTFlow gives them to an AI before it writes a section. Copy them into ChatGPT, Claude or any other tool to get Webflow-ready code from it too.
How to use this page
The other pages in this chapter explain each rule in plain words. This page is the raw text the AI actually reads — the rules HTFlow briefs the Site Agent and MCP clients such as Claude with (an MCP client can also fetch them with get_flow_webflow_rules). It is read straight from HTFlow's code, so it is always the current version.
It comes in three parts, in the order an AI should read them. Later parts override earlier ones where they disagree.
1. The Webflow rulebook
The full HTML, CSS and JavaScript rulebook. It was written for every HTFlow builder, so it also mentions Liquid tags such as {% style %} — on Flow sites, part 2 overrides those parts.
## Mandatory Webflow HTML, CSS & JavaScript Rules for HTFlow
### Absolute Prohibitions
- NEVER use CSS frameworks (Tailwind, Bootstrap) or JS libraries (jQuery, React, GSAP). Vanilla only.
- NEVER use CSS shorthand. EXCEPTION: overflow must stay shorthand (overflow: hidden).
- NEVER use the outline properties at all — see Interactive States for the box-shadow focus ring.
- NEVER use background-image for imagery — use <img> with absolute positioning.
- NEVER use pseudo-ELEMENTS: ::before, ::after, ::first-line, ::marker. Render that content as real markup.
This does NOT restrict pseudo-CLASSES — see the state rules below.
- NEVER use external CSS/JS files or CDN dependencies. Everything is self-contained.
- NEVER use breakpoints other than 991px, 767px and 479px.
- NEVER use class or id selectors in JavaScript.
- NEVER use getElementById / getElementsByClassName / getElementsByTagName.
- NEVER use 'var' — const/let only.
- NEVER use function declarations — arrow functions only.
- NEVER use emojis — inline SVG only.
- NEVER use ul/li lists — use div-based flex/grid layouts.
- NEVER use inline event handlers (onclick, onload, onerror).
- NEVER use inline styles, except temporary ones set by JS at runtime.
### Mandatory Requirements
- ALWAYS use data-ht-* attributes for ALL DOM selection.
- ALWAYS use longhand CSS properties (margin-top, margin-right, …).
- ALWAYS give every styled element its own descriptive class name.
- ALWAYS use semantic HTML with proper alt and aria-* attributes.
- ALWAYS use modern ES6+ JavaScript.
- ALWAYS use CSS Grid with grid-template-rows: 1fr when using grid-template-columns.
- ALWAYS give interactive elements :hover and :focus-visible states in CSS.
### Section Structure (HTFlow raw Liquid)
- One root <section> element carrying the section's BEM block class (e.g. <section class="hero">).
That root IS the wrapper — do NOT add an htflow-wrapper div.
- No <!DOCTYPE>, <html>, <head> or <body> tags. A section is a fragment.
- CSS goes in the section's {% style %} block (the section equivalent of <style data-ht-styles>).
- JS goes in the section's {% javascript %} block (the section equivalent of <script data-ht-main-script>).
- BEM naming: block, block__element, block--modifier (e.g. .hero__title, .features__card--highlighted).
- All class names inside the section must follow that section's BEM block.
- Reuse the same container class across sections (e.g. container-large) for consistent page rhythm.
### HTML Rules
- Use semantic elements (<header>, <nav>, <main>, <section>, <article>, <aside>, <footer>).
- Use <button> for clicks, <a> for links, <img> with alt for images.
- Every element that is styled or scripted must have a class name; never use ids for styling or JS.
- Use foreground <img> with position: absolute + object-fit: cover instead of CSS background images.
- Images from Unsplash only (https://images.unsplash.com/...).
- Use inline SVG for every icon. No emoji characters anywhere in markup.
- Bind behaviour through data-ht-* attributes, not classes.
### CSS Rules
- Longhand only: margin-top/right/bottom/left, padding-*, border-width/style/color, etc.
Correct: margin-top: 20px; margin-bottom: 20px; border-width: 1px; border-style: solid; border-color: #ccc;
Forbidden: margin: 20px 0; border: 1px solid #ccc;
- Grid must declare grid-template-rows: 1fr whenever grid-template-columns is used.
- All selectors scoped to the section's BEM block class — no body, html, * or unscoped tag selectors.
- Only Webflow breakpoints: @media (max-width: 991px) tablet, 767px mobile landscape, 479px mobile portrait.
- Breakpoint styles: prefer the named block over a hand-written media query.
{% breakpoint tablet %}
.block__el { grid-template-columns: 1fr; }
{% endbreakpoint %}
Names: tablet (991px), mobile-landscape (767px), mobile (479px). The renderer
expands each block to its media query, so Liquid inside works as it does
anywhere else. One block per breakpoint — the editor writes into the same
block, so scattering the same breakpoint over several blocks or shells makes
the Class manager show it as several groups.
Raw @media still works and is required for anything a block cannot express:
@supports, @container, print, (hover: hover), prefers-reduced-motion, and
min-width (mobile-first) queries.
- Relative units (rem, em) for typography.
### Interactive States (required)
- State pseudo-CLASSES are expected, not restricted: :hover, :focus, :focus-visible, :active, :disabled,
and structural ones like :nth-child. Only pseudo-ELEMENTS (::before/::after) are forbidden.
- Every button, link, card and other clickable element MUST have a visible :hover state, written in CSS:
.hero__cta { background-color: #111; transition-property: background-color; transition-duration: .2s; }
.hero__cta:hover { background-color: #333; }
- Every interactive element MUST also have a :focus-visible state for keyboard users. Never remove the
focus ring without replacing it.
- NEVER use outline, outline-width, outline-style, outline-color or outline-offset. Webflow draws its
own selection outline on the canvas and an authored one fights it. Draw focus rings with box-shadow:
.hero__cta:focus-visible { box-shadow: 0 0 0 2px #111; }
box-shadow paints the same ring, follows border-radius, and leaves the canvas alone.
- Hover on a parent that restyles a child is fine: .card:hover .card__title { color: #6cf; }
- Keep state changes to CSS. Use JavaScript only for motion CSS cannot express (scroll-driven reveals,
sequenced timelines, pointer-tracking) — not for ordinary hover or focus styling.
### JavaScript Rules
- Vanilla ES6+. Wrap in an arrow IIFE to avoid global pollution: (() => { ... })();
- Arrow functions only — no function declarations, no function expressions.
- const/let only, never var.
- Select exclusively through data-ht-* attributes:
Correct: document.querySelectorAll('[data-ht-button]').forEach((button) => { … });
Forbidden: document.querySelectorAll('.button'), document.getElementById('button')
- Read values from dataset (target.dataset.htData), not getAttribute.
- Never use classList.add/remove/toggle for state — use data-state, data-open, aria-expanded or aria-hidden
so the Webflow canvas keeps rendering the element correctly.
- Maintain aria-expanded / aria-hidden / aria-current for accessibility.
- Use requestAnimationFrame for animation loops.
### Animation Opacity Rules
- NEVER set opacity: 0 directly in CSS for animation elements (it makes them invisible on the Webflow canvas).
- Use a data-ht-animate attribute + JS to set opacity 0 at runtime on DOMContentLoaded,
then animate in on scroll via IntersectionObserver.
### Form Rules (Webflow Export)
- Always put spaces between attributes: <input type="text" id="name" name="name">
- Checkboxes: wrap each <input type="checkbox"> in <div data-wf-checkbox>.
- Radio buttons: wrap each <input type="radio"> in <div data-wf-radio>.
- Submit button: <button type="submit" data-wait="Please wait...">Send</button>
- Success/error messages: <div data-wf-success>...</div> and <div data-wf-error>...</div>
- Select: <select id="topic" name="topic"><option value="">Select...</option></select>
- Form tag: <form name="contact-form" id="contact-form" method="post" class="contact-form" data-ht-form>
### Mandatory Usage & Regeneration Instructions
- Every rule above is MANDATORY for Webflow mode HTML, CSS, and JS generation.
- Apply these rules strictly across the entire generation process.
- Section writes are machine-checked. A violation rejects the write with
HTFLOW_WEBFLOW_RULES_VIOLATED and the section is NOT saved.
- If any conflict, doubt, or rule violation occurs at any point, REGENERATE the section
HTML, CSS, and JS immediately to strictly satisfy these Webflow rules.
- These are compatibility rules, not visual-design rules; the user's request controls the design.2. The Flow site contract
What changes for Flow sites. Where it disagrees with part 1, this part wins.
------------------------------------------------------------
HTFLOW FLOW SITE CONTRACT — OVERRIDES SECTION STRUCTURE ABOVE
------------------------------------------------------------
This request targets the HTFlow Flow builder, not the Liquid builder or browser extension.
- Return one root <section> fragment. Do not return document-level html/head/body tags and do not add an outer wrapper div.
- Put the section CSS inside the response's single <style> tag. HTFlow stores it separately from the HTML.
- Put optional section JavaScript inside the response's single <script> tag. HTFlow stores it separately from the HTML.
- Never emit Liquid tags or a schema block.
- Use BEM class naming and scope every CSS selector to the section's BEM block.
- Use longhand CSS only; overflow is the sole shorthand exception.
- Only 991px, 767px and 479px responsive breakpoints are allowed, written as plain @media (max-width: …). {% breakpoint %} blocks are Liquid and do not exist here.
- Use a real foreground <img> for imagery, never background-image.
- Do not use pseudo-elements, inline styles, inline handlers, external scripts/styles, frameworks, emoji, ul/ol, var, or function declarations.
- Every scripted target must use a data-ht-* attribute. JavaScript selectors must not use classes or ids.
- Use const/let, arrow functions and an arrow IIFE. Drive state through data/aria attributes, never classList.
- The site's global header and footer always wrap a page's own sections. Do not build a header or footer into a page section, and do not try to position sections around them.
- Every interactive element needs visible :hover and :focus-visible styles. Draw the focus ring with box-shadow — the outline properties are not allowed.
- If a CSS grid declares grid-template-columns, it must also declare grid-template-rows: 1fr. A breakpoint override of the same selector inherits it.
- CSS must not set opacity: 0 for animation. Apply the initial hidden state from JavaScript at runtime.3. The design system contract
How every section stays on the site's design: colours, fonts, sizes and spacing come from the site's tokens. It overrides the example values in part 1.
DESIGN SYSTEM — enforced: a write that breaks it is refused. It overrides every typed-out example value in the Webflow rules (#111, 20px and the like are illustrations).
- Every colour, font family, font size, spacing (margin/padding/gap), border radius and shadow comes from the site's tokens: write var(--name). Typed-out values are refused; 0, auto and percentages for radius are fine. Layout (widths, grids, positions, weights, line heights) is free.
- Define the whole vocabulary before the first section with set_flow_design_tokens: colours (text, muted, background, surface, accent, accent-contrast, border), font families (body, heading), a font-size scale (e.g. text-sm, text-base, text-lg, heading-sm … display), a spacing scale (e.g. space-2xs … space-3xl), radii and shadows.
- Shared components live in the site stylesheet (set_flow_site_css): buttons, containers, section headings, eyebrows, cards. One class each; variants as combo classes (.button.is-secondary). Sections use these classes as they are and never restyle them.
- Before designing, read get_flow_style_guide: every token and the shared class names, in a few hundred tokens instead of reading other sections.
- Use a token only if it exists. SVG icons use currentColor.Explained in plain words
Every rule above, with the reason behind it and an everyday comparison: HTML, CSS, JavaScript and Forms.