[{"data":1,"prerenderedAt":222},["ShallowReactive",2],{"blog-how-to-handle-paperwork-effeciently":3},{"blogData":4,"relatedArticles":29},{"id":5,"title":6,"author":7,"authorImage":8,"authorProfile":9,"coverImg":10,"coverImgAlt":11,"createdAt":12,"description":13,"featured":14,"jsonld":15,"keywords":16,"metaDescription":17,"metaImage":18,"metaTitle":19,"publishedAt":20,"slug":21,"updatedAt":22,"__hash__":23,"body":24,"coverImgWidth":25,"coverImgHeight":26,"readingStats":27},"blog\u002Fblog\u002Fhow-to-handle-paperwork-effeciently.md","What Growing Teams Need to Know About Handling Paperwork Efficiently","Harish Kumar",null,"https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fharish-kumar2424\u002F","https:\u002F\u002Fformester-strapi.s3.ap-south-1.amazonaws.com\u002FHow_to_Make_User_Research_Survey_6_4d34943d7c.png","a blog post cover about how to handle paperwork for better team management","2025-05-22T10:29:33.705Z","Learn smart ways for growing teams to handle paperwork faster, stay organized, and boost productivity without the usual hassle.",false,[],"paperwork,\nteam management,\nworkflow management,\nteam management tips,","Learn how to manage paperwork efficiently as your team grows. Save time, cut stress, and keep everything running smoothly with simple strategies.",[],"How to Handle Paperwork More Efficiently | Pro Tips ","2025-05-22T10:41:01.804Z","how-to-handle-paperwork-effeciently","2025-08-18T04:32:46.740Z","_4JC71EhsWuy5WJRiwI547AjpkCfNlaDYx6YXMyWqPU","![a blog post cover about how to handle paperwork for better team management](https:\u002F\u002Fformester-strapi.s3.ap-south-1.amazonaws.com\u002FHow_to_Make_User_Research_Survey_6_4d34943d7c.png)\n\n**Growing your team** is an exciting milestone in a company. It usually means that the work is flowing, the business is evolving, there’s finally some breathing space within the team. But it also means a lot more paperwork. \n\nSuddenly you’re handling a lot more employee files, sharing project templates, and transferring the responsibility of client documents. It can all start to feel cluttered and **disorganized**, quickly. \n\nBut if you have the right processes and tools, before you hire new team members, you can create a solid foundation for handling paperwork in a way that makes everyone less stressed. \n\nThis article offers some guidance on what to think about when planning out your **document management strategy**. \n\n## Paperwork challenges are seen in most teams\nRegardless of the size of your team, you’re likely to run into a handful of issues when it comes to paperwork and how you manage it. These are a few of the most common problems that managers find:\n\n- **Inconsistent processes.** If everyone has their own way of handling paperwork, there won’t be any consistency to share with newer team members.\n\n- **Lost and missing documents.** When files are shared in the wrong place, or there is no ‘right’ place to share them, it’s much harder to find them when you need them. \n\n- **Duplicated documents.** Having ‘final-contract.pdf’ and ‘final-contract2.pdf’ can be confusing and messy, and possibly lead to errors both internally and externally. \n\n- **Ownership and access issues.** There’s a document floating around but no one has access to it and it’s unclear who even owns it. Roles for documentation can avoid this. \n\n- **No version control.** Documents being updated should be tracked in case mistakes are made in the edits. Without controlling this, there’s a higher risk of things going wrong.\n\n- **Lack of security.** Handling sensitive information comes with the responsibility of making sure it’s not accessed by unauthorized people. Managing file protection is a crucial part of handling your team’s paperwork. \n\n### What to think about when managing your growing team’s paper trail\nAs your team expands, there’s a lot more to think about when it comes to paperwork, important files, and necessary documentation. \n\n\n### Unorganized paperwork can kill productivity when you’re growing\nYou have much less paperwork to create and store with a smaller team. And fewer hands in the document piles. \n\nBut as soon as you begin bringing on new hires, you find the **[onboarding checklists](\u002Fblog\u002Fhow-online-forms-simplify-employee-onboarding-for-hr\u002F)**, HR records, and versions of documents start to pile up. \n\nAnd there are typically more people handling the same client onboarding information across different stages.\n\nThe goal of hiring more and scaling your team is to increase the efficiency and productivity, so it seems counterproductive for a bigger crew to also be the reason you’re slowed down. \n\nWhen this happens, there’s bound to be some frustration within the team, which is going to affect overall morale as well. \n\nThere’s also the risk of missed deadlines because of a hiding file, or errors due to incorrect versions of a document being shared. So, should you try to avoid paperwork as much as possible? Not quite. You do, however, need to build early systems that are flexible enough to scale with your team. \n\n### Compliance should come first\nWhen you’re still small, worrying about the big legal complications of your documents seems like a far-off issue. But if you don’t address compliance from the very start, it becomes a lot harder to keep it all in check once your team starts to get larger. \n\nYou need to be thinking about how you collect information, as well as how it’s stored and tracked. One of the easiest ways to do a lot of that is to **[use forms](\u002Ftemplates\u002Fcategories\u002Femployee-management\u002F)**, but then there’s the risk of mishandling the data and opening up security gaps that will inevitably lead to a loss of trust within your organization. \n\nWhen you use forms to collect internal documents, like onboarding information or service requests, you end up with all of that form data in shared folders or automated pipelines. \n\nIf you’re tracking who, what, and where on your form submissions, you can use **\u003Ca href=\"https:\u002F\u002Fusercentrics.com\u002Fknowledge-hub\u002Fserver-side-tagging-and-how-it-will-impact-consent\u002F\">server-side tagging\u003C\u002Fa>** to keep that tracked data accurate and compliant. \n\nThis will help you ensure that any and all personal information is logged reliably, protected from manipulation, and stays in line with privacy regulations.\n\n### Sensitive documents must be protected\nImportant documents falling into unauthorized hands can end up being costly for your company. \n\nPassword-protected documents offer a layer of security that is needed for files possessing sensitive information. Only those with the code are able to access, view, and **\u003Ca href=\"https:\u002F\u002Fsmallpdf.com\u002Funlock-pdf\">unlock PDF\u003C\u002Fa>** documents. \n\nFor contracts, HR forms, and anything financial, this process means more control over who can see the information and increased accountability should anything go wrong. \n\nAlong with locked PDFs, there should also be access controls on your cloud storage and audit trails to trace back where sensitive information has been shared. Try to update your passwords regularly as well.\n\n### You need a standardized process for file naming\nPerhaps a basic thought, but naming files isn’t always at the top of mind within teams, especially when quantity is being prioritized over quality (sometimes necessary for growth spurts). \n\nBut without having a naming format that the whole team uses, you’re not going to be able to find files in the future. And there’s a higher risk of things going ‘missing’.\n\nHaving a uniform way to name your files will actually speed things up in the long run, as long as you manage to get everyone on board with the process. Try setting standards like always adding in the date and using the department or team names.\n\nFile names should also include the type of document it is (i.e. ‘employee contract’ or ‘client onboard doc’) and the format should have no spaces or special characters. \n\nSo you’re ending up with something that looks like this: **[Sample Devops Assessment Report](https:\u002F\u002Fwww.einfochips.com\u002Fwp-content\u002Fuploads\u002F2024\u002F12\u002Feic-sample-devops-assessment-report-december-2024.pdf)**. \n\nHowever you arrange it, make sure the team is aware and can follow the same format with all their documentation. For managing legal documents and agreements more efficiently, integrating **\u003Ca href=\"https:\u002F\u002Fpaperform.co\u002Fproducts\u002Fpapersign\u002F\">contract software\u003C\u002Fa>** can also support better organization and retrieval across teams.\n\n### Centralized storage is a must-have\nThe easiest way to lose control or feel overwhelmed by your team paperwork is to fail to provide a reliable place to store and access it. Having files in multiple different inboxes or personal drives is going to cause chaos in an expanding team.\n\nThe solution is to have one safe and reliable space where everyone can save and find documentation; with limited permissions, of course. \n\nThis can be an integrated system, a project management tool, or a shared **[cloud-based storage](https:\u002F\u002Fwww.pcmag.com\u002Fpicks\u002Fthe-best-cloud-storage-and-file-sharing-services)** drive, depending on your team’s needs and availability. \n\nEssentially you just need to create a space and ensure everyone knows that should they be creating a new document, or looking for a file to update or view, that’s where they should go. \n\nTo maintain proper usage and compliance, **\u003Ca href=\"https:\u002F\u002Fwww.insightful.io\u002Fcomputer-monitoring\">computer monitoring software\u003C\u002Fa>** can provide visibility into how documents are accessed and edited across the team.\n\nThis process also offers an easier way to onboard new team members. Everything they need will be in one place, and they won’t have to navigate through multiple platforms or ask different people for access to information. \n\nIt will also help to ensure secure backups are done. Duplicated and outdated files will be avoided (or can at least be spotted and handled faster). And you’ll see that collaboration across the team is smooth and efficient. \n\n### When in doubt, automate\nIf you’re still manually renaming file names, downloading form submissions, or sorting documents into folders, you’re wasting valuable time. There are tools to help you now, and using them will only strengthen your paperwork management. \n\n**Look for ways to automate tasks like:**\n\n- Trigger alerts or tasks when a document is moved, edited, or viewed\n\n- Save documents to the right folders as soon as they’re submitted\n\n- Generate templates for annual reviews, client pitches, etc. \n\n- Send reminders for unsigned agreements or missing documentation\n\nThis is especially straightforward for documents collected through form submissions, like leave requests or onboarding data. But you can easily add team checklists, reports, and scanned files to an **[automated workflow, with the right tools](\u002Fblog\u002F10-best-workflow-automation-tools-in-2024\u002F)**. \n\nManaging complex documents and requests efficiently is critical, especially when dealing with multiple vendors or partners. **\u003Ca href=\"https:\u002F\u002F1up.ai\u002Frfp-automation\u002F\">AI RFP\u003C\u002Fa>** solutions take this a step further by automating the entire Request for Proposal process, reducing manual errors and speeding up vendor selection.\n\n### Don’t forget the handoff plan\nStarting off, you may have one person in your team who manages client documents, another who handles the HR files, and a separate person handling other important information. \n\nBut growing often means sharing the load between more people, which also means sharing access to sensitive documentation. \n\nThe best way to avoid this becoming an issue down the line is to set out a plan for how files are going to be created and accessed in the team. \n\nHave clear roles and responsibilities for each document, with a structured process on how they should be handed off when the time comes. \n\nEach document should have an owner, so that someone is accountable for the status, location, and accuracy of it. And there should be strict tracking when these documents are being sent across departments and updated, so that there’s tight version control and access management throughout. \n\n### Files and documents shouldn’t stagnate your team\nPaperwork should help keep your team on track, organized, and efficient. It shouldn’t cause confusion, miscommunication, or aggravation. \n\nHaving clear processes for how you manage your documents, where you store them, and who has access to them, will bring clarity and keep productivity and morale levels high. \n\nDon’t wait until you’ve grown and need the systems, though. Implement them early so that by the time you really need them, they’re more like second nature than a foreign concept to the whole team. \n\nNeed help with some of that paperwork? Take a look at our **[client onboarding forms](\u002Fuse-case\u002Fclient-onboarding\u002F)** and **[new hire paperwork forms](\u002Ftemplates\u002Fnew-hire-paperwork-2778\u002F)** to help you start off on the right foot.\n",1214,630,{"text":28},"9 min read",[30,49,68,176],{"title":31,"author":7,"authorImage":8,"authorProfile":9,"coverImg":32,"coverImgAlt":33,"createdAt":34,"description":35,"featured":14,"jsonld":36,"keywords":37,"metaDescription":38,"metaImage":39,"metaTitle":40,"publishedAt":41,"slug":42,"updatedAt":43,"__hash__":44,"body":45,"id":46,"coverImgWidth":25,"coverImgHeight":26,"readingStats":47},"How to create an intake process without Airtable & Zapier?","https:\u002F\u002Fformester-strapi.s3.ap-south-1.amazonaws.com\u002FHow_to_Make_User_Research_Survey_20_12ded1f2b7.png","a blog post cover about how to create an intake process","2025-08-22T05:06:27.842Z","Learn how to build a smooth intake process without expensive tools. Capture leads, qualify them, and automate nurturing affordably with ease.",[],"intake form,\nintake process,\nclient intake,\nwork intake,\nworkflow automation,\nintake process automation,\n","Learn how to create a complete intake process without Airtable or Zapier. Capture, qualify, and nurture leads easily in a cost effective way.",[],"How to create an intake process without Airtable & Zapier","2025-08-22T05:13:21.915Z","how-to-create-an-intake-process","2025-08-25T04:26:53.455Z","yfpDICvIEeBGZfb_HS6Gk2uQz4sXGNxTofJkDz8-GDw","\u003Ciframe width=\"100%\" height=\"400\" src=\"https:\u002F\u002Fwww.youtube.com\u002Fembed\u002FSDkZJso4nv8?si=2zMa2k-mvk0WS62Z\" title=\"YouTube video player\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen>\u003C\u002Fiframe>\n\n**Most intake processes** today depend on expensive tools like Airtable and Zapier, which can quickly add up in cost. But the truth is, you don’t need them to build a complete, automated workflow for capturing and qualifying leads.\n\nIn this guide, I’ll show you **how to create an end-to-end intake process** without relying on those tools. By the end, you’ll know how to:\n\n- Capture leads with a smart intake form\n\n- Qualify them into categories like cold, warm, and hot\n\n- Automate lead nurturing with personalized emails\n\nAnd the best part? You’ll do it all in the simplest and most cost-effective way using Formester.\n\n## How to Create an Intake Process in Formester?\n\n### Step 1: Build an Intake Form\n![a screenshot of formester ai form builder](https:\u002F\u002Fformester-strapi.s3.ap-south-1.amazonaws.com\u002Fa_screenshot_of_formester_ai_form_builder_79554ac18b.png)\n\nYour intake form is the very first touchpoint with potential clients. A well-designed form helps you collect all the important details upfront, so you don’t waste hours chasing information later.\n\nWith Formester, creating an intake form takes just seconds thanks to its **[AI-powered form builder](\u002Fai-form-generator\u002F)**. Here’s how:\n\n- Click New Form.\n\n- Select Create with AI.\n\n- Describe the intake form you need. For example: “Create an intake form for my software development company.”\n\n- If you want specific questions, include them, then click Generate.\n\n- The AI will instantly create a ready-to-use intake form.\n\n**A sample form might include:**\n\n- Page 1: Project type and required features\n\n- Page 2: Contact details (email, company name, website)\n\n- Page 3: Budget and timeline estimates\n\nWant more? Add extra questions from the Add Elements tab, or even include a **[Scheduling field](\u002Ffeatures\u002Fappointment-scheduler)** so prospects can book appointments directly.\n\nOnce your fields are set, head to the Design tab to add your logo, customize fonts, and match your brand style. Publish the form and embed it on your website—it’s that easy.\n\n### Step 2: Qualify Your Leads\n![a screenshot of formester's results tab](https:\u002F\u002Fformester-strapi.s3.ap-south-1.amazonaws.com\u002Fa_screenshot_of_formester_s_results_tab_86cc7af2d5.png)\n\nThe next step is lead qualification. Normally, people use Airtable or other tools to do this manually. But with Formester, you can handle it all in one place.\n\nGo to the Results tab, and you’ll see all submissions neatly organized in a table. Open any submission to view it in detail.\n\n**From there:**\n\n- Click the three dots above and add a new column, e.g., Lead Type.\n\n- For each submission, click the three dots → Edit Columns.\n\n- Assign a type based on the answers.\n\n**For example:**\n\n- Cold Lead: Low budget, vague project details.\n\n- Warm Lead: Mid-range budget, clear interest.\n\n- Hot Lead: High budget and specific project type.\n\nThis way, you can prioritize who to contact first. You can also filter by lead type, export the list as CSV, or push leads to a database like Notion.\n\n**Notion** works as a free, flexible CRM. Plus, you can invite unlimited team members with different levels of access—similar to Google Sheets.\n\n### Step 3: Automate Follow-Up Emails\n\n![a screenshot of formester's ai email autoresponder](https:\u002F\u002Fformester-strapi.s3.ap-south-1.amazonaws.com\u002Fa_screenshot_of_formester_s_ai_email_autoresponder_f6f3c8ee6e.png)\n\nIf you don’t want to review and qualify leads manually, you can automate the follow-up process with Formester’s **[Conditional Autoresponder](\u002Ffeatures\u002Fautoresponder-email\u002F)**.\n\nHere’s how:\n\n- Go to Automate → New Autoresponder.\n\n- Name it (for example, Hot Lead).\n\n- Use AI to generate a personalized email subject and body tailored to the lead type.\n\nExample prompt:\n“Write a professional yet friendly email for a hot lead who filled out our intake form. Highlight their interest, mention the budget, and invite them to book a call.”\n\nMake sure you set the email field as the recipient address. Then, connect your **SMTP integration** so emails are sent from your own account.\n\n- Finally, head to Advanced → Rules to set up conditions. For example:\n\n- Project type = Web Application\n\n- Budget > $50,000\n\nWhen these conditions are met, the autoresponder will send your personalized follow-up automatically.\n\n### Step 4: Test the Workflow\n![a screenshot of formester intake form](https:\u002F\u002Fformester-strapi.s3.ap-south-1.amazonaws.com\u002Fa_screenshot_of_formester_intake_form_9f09a839bb.png)\n\nBefore you go live, test everything. Submit the form as if you were a prospect. \n\nOnce submitted, check your inbox. You should see a personalized follow-up email that matches the details you entered.\n\nThis test ensures your conditions, autoresponder, and SMTP setup are working correctly.\n\n### Why Use Formester for Your Intake Process?\n\nWith **[Formester](\u002F)**, you can manage your entire intake process in one place:\n\n- Capture details with AI-powered forms\n\n- Qualify leads directly in the dashboard\n\n- Automate follow-ups with personalized emails\n\nAll of this happens without relying on multiple expensive tools like Airtable or Zapier. You save money, keep your workflow simple, and scale your intake process with ease.\n\nIf you want to try Formester, check out our **[pricing page](\u002Fpricing\u002F)** and see how much you can save.\n","blog\u002Fblog\u002Fhow-to-create-an-intake-process.md",{"text":48},"4 min read",{"title":50,"author":7,"authorImage":8,"authorProfile":9,"coverImg":51,"coverImgAlt":52,"createdAt":53,"description":54,"featured":14,"jsonld":55,"keywords":56,"metaDescription":57,"metaImage":58,"metaTitle":59,"publishedAt":60,"slug":61,"updatedAt":62,"__hash__":63,"body":64,"id":65,"coverImgWidth":25,"coverImgHeight":26,"readingStats":66},"How to Make a Feedback Form in HTML (with Code, CSS, and a Backend)","https:\u002F\u002Fformester-strapi.s3.ap-south-1.amazonaws.com\u002Fan_illustration_of_how_to_make_feedback_form_in_html_c6203dc935.png","an illustration of how to make feedback form in html","2024-06-27T06:19:40.031Z","Learn how to create a feedback form in HTML with easy steps. Set up an HTML document, add form fields, style with CSS, and add JavaScript for validation. Test your form and start collecting feedback.",[],"feedback forms, fillable freedback form, how to make feedback form in html, style feedback form with css, feedback form html code","Build a working feedback form in HTML with copy-paste code, CSS styling, JavaScript validation, accessibility, and a backend that stores submissions without a server.",[],"How to Make a Feedback Form in HTML (Code, CSS, Validation, Backend)","2026-05-17T04:46:01.940Z","how-to-make-feedback-form-in-html","2026-05-17T04:46:01.948Z","wyyctYTKwdEs6QGo1-xhuZdxYoLFow0lRYEcN7glo1g","![an illustration of how to make feedback form in html](https:\u002F\u002Fformester-strapi.s3.ap-south-1.amazonaws.com\u002Fan_illustration_of_how_to_make_feedback_form_in_html_c6203dc935.png)\n\n\u003Cstyle>\n\u002F* host-link-override *\u002F\n.fmstr-cmp-ffh-body a { text-decoration: none !important; }\n.fmstr-cmp-ffh-body {\n--c-bg-card: #ffffff;\n--c-bg-soft: #f9fafb;\n--c-fg-1: #101828; --c-fg-2: #475467; --c-fg-3: #697586;\n--c-violet-500: #7f56d9; --c-violet-600: #6941c6;\n--c-tint: #f7f3ff; --c-edge: #e4d7ff; --c-border: #eaecf0;\n--c-code-bg: #0f172a; --c-code-fg: #e2e8f0;\n--c-code-keyword: #a78bfa; --c-code-attr: #67e8f9; --c-code-string: #fcd34d; --c-code-comment: #64748b;\n--c-warn-bg: #fef3c7; --c-warn-fg: #92400e; --c-warn-edge: #fde68a;\n\nbackground: transparent; padding: 24px;\nfont-family: inherit;\ncolor: var(--c-fg-1);\n}\n.fmstr-cmp-ffh-body *, .fmstr-cmp-ffh-body *::before, .fmstr-cmp-ffh-body *::after { box-sizing: border-box; }\n.fmstr-cmp-ffh-body__container { max-width: 820px; margin: 0 auto; }\n\n.fmstr-cmp-ffh-body__intro p { font-size: 17px; line-height: 1.7; color: var(--c-fg-2); margin: 0 0 16px; }\n.fmstr-cmp-ffh-body__intro a { color: var(--c-violet-600) !important; text-decoration: none !important; font-weight: 500; }\n.fmstr-cmp-ffh-body__intro a:hover { text-decoration: underline !important; }\n.fmstr-cmp-ffh-body__intro code { background: var(--c-tint); color: var(--c-violet-600); padding: 2px 6px; border-radius: 4px; font-family: ui-monospace, Menlo, Consolas, monospace; font-size: 14.5px; border: 1px solid var(--c-edge); }\n\n.fmstr-cmp-ffh-body__h2 {\nfont-size: 28px; font-weight: 700; line-height: 1.25; letter-spacing: -.02em;\nmargin: 40px 0 16px; color: var(--c-fg-1);\n}\n.fmstr-cmp-ffh-body__h3 {\nfont-size: 20px; font-weight: 700; line-height: 1.35; letter-spacing: -.01em;\nmargin: 28px 0 12px; color: var(--c-fg-1);\n}\n.fmstr-cmp-ffh-body p { font-size: 16px; line-height: 1.7; color: var(--c-fg-2); margin: 0 0 14px; }\n.fmstr-cmp-ffh-body p strong { color: var(--c-fg-1); }\n.fmstr-cmp-ffh-body a { color: var(--c-violet-600) !important; text-decoration: none !important; font-weight: 500; }\n.fmstr-cmp-ffh-body a:hover { text-decoration: underline !important; }\n.fmstr-cmp-ffh-body ul, .fmstr-cmp-ffh-body ol { margin: 0 0 16px; padding-left: 22px; }\n.fmstr-cmp-ffh-body li { font-size: 16px; line-height: 1.7; color: var(--c-fg-2); margin: 6px 0; }\n.fmstr-cmp-ffh-body li strong { color: var(--c-fg-1); }\n.fmstr-cmp-ffh-body code { background: var(--c-tint); color: var(--c-violet-600); padding: 2px 6px; border-radius: 4px; font-family: ui-monospace, Menlo, Consolas, monospace; font-size: 14.5px; border: 1px solid var(--c-edge); }\n\n.fmstr-cmp-ffh-body__code {\nbackground: var(--c-code-bg); color: var(--c-code-fg);\nborder-radius: 12px; padding: 18px 20px; margin: 8px 0 18px;\noverflow-x: auto;\nfont-family: ui-monospace, Menlo, Consolas, monospace; font-size: 13.5px; line-height: 1.6;\n}\n.fmstr-cmp-ffh-body__code pre { margin: 0; }\n.fmstr-cmp-ffh-body__code code {\nbackground: transparent !important; color: inherit !important; padding: 0; border: 0;\nfont-family: inherit !important; font-size: inherit;\n}\n.fmstr-cmp-ffh-body__code .kw { color: var(--c-code-keyword); }\n.fmstr-cmp-ffh-body__code .at { color: var(--c-code-attr); }\n.fmstr-cmp-ffh-body__code .st { color: var(--c-code-string); }\n.fmstr-cmp-ffh-body__code .cm { color: var(--c-code-comment); font-style: italic; }\n.fmstr-cmp-ffh-body__code .lang { display: inline-block; font-size: 11px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; padding: 3px 10px; border-radius: 6px; background: rgba(255,255,255,.1); color: rgba(255,255,255,.7); margin: 0 0 12px; }\n\n.fmstr-cmp-ffh-body__note {\nmargin: 14px 0 18px; padding: 14px 18px;\nbackground: var(--c-bg-soft); border-left: 3px solid var(--c-violet-500);\nborder-radius: 8px; font-size: 15.5px; color: var(--c-fg-2); line-height: 1.6;\n}\n.fmstr-cmp-ffh-body__note strong { color: var(--c-fg-1); }\n.fmstr-cmp-ffh-body__note--warn { background: var(--c-warn-bg); border-left-color: var(--c-warn-fg); }\n.fmstr-cmp-ffh-body__note--warn strong { color: var(--c-warn-fg); }\n\n.fmstr-cmp-ffh-body__variants {\ndisplay: grid; grid-template-columns: 1fr; gap: 14px; margin: 12px 0 24px;\n}\n.fmstr-cmp-ffh-body__variant {\nbackground: var(--c-bg-card); border: 1px solid var(--c-border); border-radius: 14px;\npadding: 18px 22px;\n}\n.fmstr-cmp-ffh-body__variant h4 {\nfont-size: 16px; font-weight: 700; color: var(--c-fg-1);\nmargin: 0 0 8px; line-height: 1.35;\n}\n.fmstr-cmp-ffh-body__variant p { font-size: 15px; line-height: 1.65; color: var(--c-fg-2); margin: 0; }\n\n@media (max-width: 760px) {\n.fmstr-cmp-ffh-body { padding: 16px; }\n.fmstr-cmp-ffh-body__intro p, .fmstr-cmp-ffh-body p, .fmstr-cmp-ffh-body li { font-size: 15.5px; }\n.fmstr-cmp-ffh-body__h2 { font-size: 24px; margin-top: 32px; }\n.fmstr-cmp-ffh-body__h3 { font-size: 18.5px; }\n.fmstr-cmp-ffh-body__code { padding: 14px 16px; font-size: 12.5px; border-radius: 10px; }\n.fmstr-cmp-ffh-body__variant { padding: 16px 18px; }\n}\n\u003C\u002Fstyle>\n\n\u003Csection class=\"fmstr-cmp-ffh-body\" aria-label=\"How to make a feedback form in HTML\">\n\u003Cdiv class=\"fmstr-cmp-ffh-body__container\">\n\n\u003Cdiv class=\"fmstr-cmp-ffh-body__intro\">\n\u003Cp>A feedback form in HTML is twenty lines of markup, a bit of CSS, and one decision that trips up almost everyone: what happens after the user clicks Submit?\u003C\u002Fp>\n\u003Cp>This guide ships the full pattern. You'll get a working \u003Ccode>&lt;form&gt;\u003C\u002Fcode> with name, email, and message fields, CSS that styles it without a framework, JavaScript validation that doesn't break keyboard users, and three honest options for the backend, including one that needs zero server code. Paste the snippets in order, swap the action URL, and you have a live feedback form on your site in about ten minutes.\u003C\u002Fp>\n\u003Cp>If you want to skip the code entirely, \u003Ca href=\"https:\u002F\u002Fformester.com\u002Ffeatures\u002Fdrag-and-drop-form-builder\u002F\">Formester's drag-and-drop builder\u003C\u002Fa> ships a feedback form you can \u003Ca href=\"https:\u002F\u002Fformester.com\u002Ffeatures\u002Fembed-forms\u002F\">embed in any HTML page\u003C\u002Fa> with one snippet. Keep reading for the hand-coded path.\u003C\u002Fp>\n\u003C\u002Fdiv>\n\n\u003Ch2 class=\"fmstr-cmp-ffh-body__h2\">What a feedback form in HTML actually needs\u003C\u002Fh2>\n\u003Cp>Four pieces, in order:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\u003Cstrong>A \u003Ccode>&lt;form&gt;\u003C\u002Fcode> element\u003C\u002Fstrong> with the right \u003Ccode>action\u003C\u002Fcode> and \u003Ccode>method\u003C\u002Fcode> so the browser knows where to send data.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Labeled inputs\u003C\u002Fstrong> for the fields you care about (name, email, rating, message), with \u003Ccode>name\u003C\u002Fcode> attributes so the server can read them.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Validation\u003C\u002Fstrong> on the client (for user experience) and on the server (for trust).\u003C\u002Fli>\n\u003Cli>\u003Cstrong>A backend\u003C\u002Fstrong> that receives the submission, stores it, and ideally notifies you. This is the part most tutorials skip; it's the part you need most.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>Below, each piece is a separate step with a copy-paste block. The last step is a single complete file you can save as \u003Ccode>feedback.html\u003C\u002Fcode> and open in a browser.\u003C\u002Fp>\n\n\u003Ch2 class=\"fmstr-cmp-ffh-body__h2\">Step 1: Set up the HTML document\u003C\u002Fh2>\n\u003Cp>Save this as \u003Ccode>feedback.html\u003C\u002Fcode>. It's the shell every form goes inside.\u003C\u002Fp>\n\u003Cdiv class=\"fmstr-cmp-ffh-body__code\">\u003Cspan class=\"lang\">HTML\u003C\u002Fspan>\n\u003Cpre>\u003Ccode>&lt;!DOCTYPE html&gt;\n&lt;html lang=\"en\"&gt;\n&lt;head&gt;\n&#160;&#160;&lt;meta charset=\"UTF-8\"&gt;\n&#160;&#160;&lt;meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"&gt;\n&#160;&#160;&lt;title&gt;Feedback Form&lt;\u002Ftitle&gt;\n&lt;\u002Fhead&gt;\n&lt;body&gt;\n&#160;&#160;&lt;h1&gt;Tell us what you think&lt;\u002Fh1&gt;\n&#160;&#160;&lt;!-- form goes here --&gt;\n&lt;\u002Fbody&gt;\n&lt;\u002Fhtml&gt;\u003C\u002Fcode>\u003C\u002Fpre>\n\u003C\u002Fdiv>\n\u003Cp>Two small things that matter later: \u003Ccode>lang=\"en\"\u003C\u002Fcode> helps screen readers pick the right voice, and the viewport meta tag makes the form usable on phones.\u003C\u002Fp>\n\n\u003Ch2 class=\"fmstr-cmp-ffh-body__h2\">Step 2: Add the form fields\u003C\u002Fh2>\n\u003Cp>Paste this inside \u003Ccode>&lt;body&gt;\u003C\u002Fcode>, where the comment says \"form goes here\":\u003C\u002Fp>\n\u003Cdiv class=\"fmstr-cmp-ffh-body__code\">\u003Cspan class=\"lang\">HTML\u003C\u002Fspan>\n\u003Cpre>\u003Ccode>&lt;form id=\"feedback-form\" action=\"\u002Fsubmit-feedback\" method=\"post\" novalidate&gt;\n&#160;&#160;&lt;div class=\"field\"&gt;\n&#160;&#160;&#160;&#160;&lt;label for=\"name\"&gt;Name&lt;\u002Flabel&gt;\n&#160;&#160;&#160;&#160;&lt;input type=\"text\" id=\"name\" name=\"name\" autocomplete=\"name\" required&gt;\n&#160;&#160;&lt;\u002Fdiv&gt;\n\n&#160;&#160;&lt;div class=\"field\"&gt;\n&#160;&#160;&#160;&#160;&lt;label for=\"email\"&gt;Email&lt;\u002Flabel&gt;\n&#160;&#160;&#160;&#160;&lt;input type=\"email\" id=\"email\" name=\"email\" autocomplete=\"email\" required&gt;\n&#160;&#160;&lt;\u002Fdiv&gt;\n\n&#160;&#160;&lt;div class=\"field\"&gt;\n&#160;&#160;&#160;&#160;&lt;label for=\"rating\"&gt;How was your experience?&lt;\u002Flabel&gt;\n&#160;&#160;&#160;&#160;&lt;select id=\"rating\" name=\"rating\" required&gt;\n&#160;&#160;&#160;&#160;&#160;&#160;&lt;option value=\"\"&gt;Pick one&lt;\u002Foption&gt;\n&#160;&#160;&#160;&#160;&#160;&#160;&lt;option value=\"5\"&gt;Loved it&lt;\u002Foption&gt;\n&#160;&#160;&#160;&#160;&#160;&#160;&lt;option value=\"4\"&gt;Good&lt;\u002Foption&gt;\n&#160;&#160;&#160;&#160;&#160;&#160;&lt;option value=\"3\"&gt;Okay&lt;\u002Foption&gt;\n&#160;&#160;&#160;&#160;&#160;&#160;&lt;option value=\"2\"&gt;Not great&lt;\u002Foption&gt;\n&#160;&#160;&#160;&#160;&#160;&#160;&lt;option value=\"1\"&gt;Bad&lt;\u002Foption&gt;\n&#160;&#160;&#160;&#160;&lt;\u002Fselect&gt;\n&#160;&#160;&lt;\u002Fdiv&gt;\n\n&#160;&#160;&lt;div class=\"field\"&gt;\n&#160;&#160;&#160;&#160;&lt;label for=\"message\"&gt;Your feedback&lt;\u002Flabel&gt;\n&#160;&#160;&#160;&#160;&lt;textarea id=\"message\" name=\"message\" rows=\"5\" required&gt;&lt;\u002Ftextarea&gt;\n&#160;&#160;&lt;\u002Fdiv&gt;\n\n&#160;&#160;&lt;button type=\"submit\"&gt;Send feedback&lt;\u002Fbutton&gt;\n&lt;\u002Fform&gt;\u003C\u002Fcode>\u003C\u002Fpre>\n\u003C\u002Fdiv>\n\u003Cp>Three details that beginners miss:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\u003Cstrong>Every input has a matching \u003Ccode>&lt;label for&gt;\u003C\u002Fcode>.\u003C\u002Fstrong> Click the label, the input focuses. Screen readers read the label out loud. Skip this and the form fails accessibility and loses keyboard users.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>\u003Ccode>name\u003C\u002Fcode> attributes are not cosmetic.\u003C\u002Fstrong> The server reads submissions by \u003Ccode>name\u003C\u002Fcode>, so \u003Ccode>name=\"email\"\u003C\u002Fcode> is what makes the email value reach your inbox. Missing \u003Ccode>name\u003C\u002Fcode> = silent data loss.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>\u003Ccode>autocomplete=\"name\"\u003C\u002Fcode> and \u003Ccode>autocomplete=\"email\"\u003C\u002Fcode>\u003C\u002Fstrong> let browsers pre-fill from saved info. One line, measurable bump in completion.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cdiv class=\"fmstr-cmp-ffh-body__note\">\u003Cstrong>Note:\u003C\u002Fstrong> \u003Ccode>novalidate\u003C\u002Fcode> on the form tag turns off the browser's default error bubbles so you can show your own (covered in Step 4). Drop it if you want native validation only.\u003C\u002Fdiv>\n\n\u003Ch2 class=\"fmstr-cmp-ffh-body__h2\">Step 3: Style it with CSS\u003C\u002Fh2>\n\u003Cp>Paste this inside \u003Ccode>&lt;head&gt;\u003C\u002Fcode> between \u003Ccode>&lt;title&gt;\u003C\u002Fcode> and the closing \u003Ccode>&lt;\u002Fhead&gt;\u003C\u002Fcode>:\u003C\u002Fp>\n\u003Cdiv class=\"fmstr-cmp-ffh-body__code\">\u003Cspan class=\"lang\">CSS\u003C\u002Fspan>\n\u003Cpre>\u003Ccode>&lt;style&gt;\n&#160;&#160;body {\n&#160;&#160;&#160;&#160;font-family: system-ui, -apple-system, \"Segoe UI\", Roboto, sans-serif;\n&#160;&#160;&#160;&#160;background: #f7f7f9;\n&#160;&#160;&#160;&#160;margin: 0;\n&#160;&#160;&#160;&#160;padding: 40px 16px;\n&#160;&#160;&#160;&#160;color: #1a1a1a;\n&#160;&#160;}\n&#160;&#160;h1 { font-size: 1.5rem; margin: 0 0 24px; text-align: center; }\n&#160;&#160;form {\n&#160;&#160;&#160;&#160;max-width: 480px;\n&#160;&#160;&#160;&#160;margin: 0 auto;\n&#160;&#160;&#160;&#160;background: #fff;\n&#160;&#160;&#160;&#160;padding: 24px;\n&#160;&#160;&#160;&#160;border-radius: 12px;\n&#160;&#160;&#160;&#160;box-shadow: 0 2px 12px rgba(0,0,0,0.06);\n&#160;&#160;}\n&#160;&#160;.field { margin-bottom: 16px; }\n&#160;&#160;label {\n&#160;&#160;&#160;&#160;display: block;\n&#160;&#160;&#160;&#160;font-weight: 600;\n&#160;&#160;&#160;&#160;font-size: 0.9rem;\n&#160;&#160;&#160;&#160;margin-bottom: 6px;\n&#160;&#160;}\n&#160;&#160;input, select, textarea {\n&#160;&#160;&#160;&#160;width: 100%;\n&#160;&#160;&#160;&#160;box-sizing: border-box;\n&#160;&#160;&#160;&#160;padding: 10px 12px;\n&#160;&#160;&#160;&#160;font: inherit;\n&#160;&#160;&#160;&#160;border: 1px solid #d0d0d6;\n&#160;&#160;&#160;&#160;border-radius: 8px;\n&#160;&#160;&#160;&#160;background: #fff;\n&#160;&#160;}\n&#160;&#160;input:focus, select:focus, textarea:focus {\n&#160;&#160;&#160;&#160;outline: 2px solid #5b6cff;\n&#160;&#160;&#160;&#160;outline-offset: 1px;\n&#160;&#160;&#160;&#160;border-color: #5b6cff;\n&#160;&#160;}\n&#160;&#160;input[aria-invalid=\"true\"],\n&#160;&#160;select[aria-invalid=\"true\"],\n&#160;&#160;textarea[aria-invalid=\"true\"] {\n&#160;&#160;&#160;&#160;border-color: #d33;\n&#160;&#160;}\n&#160;&#160;.error {\n&#160;&#160;&#160;&#160;display: block;\n&#160;&#160;&#160;&#160;color: #d33;\n&#160;&#160;&#160;&#160;font-size: 0.8rem;\n&#160;&#160;&#160;&#160;margin-top: 4px;\n&#160;&#160;&#160;&#160;min-height: 1em;\n&#160;&#160;}\n&#160;&#160;button {\n&#160;&#160;&#160;&#160;width: 100%;\n&#160;&#160;&#160;&#160;padding: 12px;\n&#160;&#160;&#160;&#160;background: #5b6cff;\n&#160;&#160;&#160;&#160;color: #fff;\n&#160;&#160;&#160;&#160;font-weight: 600;\n&#160;&#160;&#160;&#160;border: none;\n&#160;&#160;&#160;&#160;border-radius: 8px;\n&#160;&#160;&#160;&#160;cursor: pointer;\n&#160;&#160;}\n&#160;&#160;button:hover { background: #4a59e0; }\n&lt;\u002Fstyle&gt;\u003C\u002Fcode>\u003C\u002Fpre>\n\u003C\u002Fdiv>\n\u003Cp>Two things this stylesheet does that the typical tutorial skips:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>Keeps the focus outline visible. Default focus styles are ugly, so most tutorials remove them. Removing them breaks keyboard users. Replace, don't remove.\u003C\u002Fli>\n\u003Cli>Uses \u003Ccode>system-ui\u003C\u002Fcode> for fonts, so the form inherits the host site's native typography on macOS, Windows, iOS, and Android without shipping a font file.\u003C\u002Fli>\n\u003C\u002Ful>\n\n\u003Ch2 class=\"fmstr-cmp-ffh-body__h2\">Step 4: Add accessible JavaScript validation\u003C\u002Fh2>\n\u003Cp>The alert-on-submit pattern works but it's the worst possible UX. This version shows inline errors, marks invalid fields for screen readers with \u003Ccode>aria-invalid\u003C\u002Fcode>, and keeps focus where the user can fix the problem.\u003C\u002Fp>\n\u003Cp>Paste this right before \u003Ccode>&lt;\u002Fbody&gt;\u003C\u002Fcode>:\u003C\u002Fp>\n\u003Cdiv class=\"fmstr-cmp-ffh-body__code\">\u003Cspan class=\"lang\">JavaScript\u003C\u002Fspan>\n\u003Cpre>\u003Ccode>&lt;script&gt;\n&#160;&#160;const form = document.getElementById('feedback-form');\n\n&#160;&#160;function setError(input, message) {\n&#160;&#160;&#160;&#160;input.setAttribute('aria-invalid', 'true');\n&#160;&#160;&#160;&#160;let errorEl = input.parentElement.querySelector('.error');\n&#160;&#160;&#160;&#160;if (!errorEl) {\n&#160;&#160;&#160;&#160;&#160;&#160;errorEl = document.createElement('span');\n&#160;&#160;&#160;&#160;&#160;&#160;errorEl.className = 'error';\n&#160;&#160;&#160;&#160;&#160;&#160;errorEl.id = input.id + '-error';\n&#160;&#160;&#160;&#160;&#160;&#160;input.parentElement.appendChild(errorEl);\n&#160;&#160;&#160;&#160;}\n&#160;&#160;&#160;&#160;errorEl.textContent = message;\n&#160;&#160;&#160;&#160;input.setAttribute('aria-describedby', errorEl.id);\n&#160;&#160;}\n\n&#160;&#160;function clearError(input) {\n&#160;&#160;&#160;&#160;input.setAttribute('aria-invalid', 'false');\n&#160;&#160;&#160;&#160;const errorEl = input.parentElement.querySelector('.error');\n&#160;&#160;&#160;&#160;if (errorEl) errorEl.textContent = '';\n&#160;&#160;}\n\n&#160;&#160;form.addEventListener('submit', function (event) {\n&#160;&#160;&#160;&#160;let firstInvalid = null;\n\n&#160;&#160;&#160;&#160;[...form.querySelectorAll('input, select, textarea')].forEach((input) =&gt; {\n&#160;&#160;&#160;&#160;&#160;&#160;clearError(input);\n&#160;&#160;&#160;&#160;&#160;&#160;if (!input.value.trim()) {\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;setError(input, 'This field is required.');\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;firstInvalid = firstInvalid || input;\n&#160;&#160;&#160;&#160;&#160;&#160;} else if (input.type === 'email' &amp;&amp; !\u002F^\\S+@\\S+\\.\\S+$\u002F.test(input.value)) {\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;setError(input, 'Enter a valid email address.');\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;firstInvalid = firstInvalid || input;\n&#160;&#160;&#160;&#160;&#160;&#160;}\n&#160;&#160;&#160;&#160;});\n\n&#160;&#160;&#160;&#160;if (firstInvalid) {\n&#160;&#160;&#160;&#160;&#160;&#160;event.preventDefault();\n&#160;&#160;&#160;&#160;&#160;&#160;firstInvalid.focus();\n&#160;&#160;&#160;&#160;}\n&#160;&#160;});\n&lt;\u002Fscript&gt;\u003C\u002Fcode>\u003C\u002Fpre>\n\u003C\u002Fdiv>\n\u003Cp>What this does that the original snippet missed:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>Sets \u003Ccode>aria-invalid=\"true\"\u003C\u002Fcode> and \u003Ccode>aria-describedby\u003C\u002Fcode> so screen readers announce the error.\u003C\u002Fli>\n\u003Cli>Inserts the error message next to the field, not in a modal.\u003C\u002Fli>\n\u003Cli>Focuses the first invalid field on failed submit, so a keyboard user lands exactly where they need to fix.\u003C\u002Fli>\n\u003Cli>Doesn't trust the email regex to be perfect (it isn't); always re-validate on the server.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cdiv class=\"fmstr-cmp-ffh-body__note\">\u003Cstrong>Rule of thumb:\u003C\u002Fstrong> client-side validation is for UX. Server-side validation is for trust. Do both.\u003C\u002Fdiv>\n\n\u003Ch2 class=\"fmstr-cmp-ffh-body__h2\">Step 5: Test the form locally\u003C\u002Fh2>\n\u003Cp>Open \u003Ccode>feedback.html\u003C\u002Fcode> in a browser. Run this checklist:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>Tab through every field with the keyboard. Focus should be visible at every stop.\u003C\u002Fli>\n\u003Cli>Try to submit empty. You should see inline error messages, focus should jump to the first empty field.\u003C\u002Fli>\n\u003Cli>Type a malformed email. You should see \"Enter a valid email address.\"\u003C\u002Fli>\n\u003Cli>Open the browser's network tab, submit a valid form. You should see a POST to \u003Ccode>\u002Fsubmit-feedback\u003C\u002Fcode>. That request will currently 404 because you don't have a backend yet. Step 6 fixes that.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>If you want to skip the backend setup entirely, the next step shows the \u003Ca href=\"https:\u002F\u002Fformester.com\u002Ffeatures\u002Fhtml-form-backend\u002F\">Formester HTML form backend\u003C\u002Fa> path: change one \u003Ccode>action\u003C\u002Fcode> attribute and your form starts collecting submissions.\u003C\u002Fp>\n\n\u003Ch2 class=\"fmstr-cmp-ffh-body__h2\" id=\"step-6-backend\">Step 6: Wire up a backend that stores submissions\u003C\u002Fh2>\n\u003Cp>A feedback form without a backend is a dead form. The browser POSTs the data, the server returns 404, the user sees an error page, the feedback is gone. You have three real options, compared side-by-side below.\u003C\u002Fp>\n\n\u003C\u002Fdiv>\n\u003C\u002Fsection>\n\n\u003Cstyle>\n\u002F* host-link-override *\u002F\n.fmstr-cmp-ffh-back a { text-decoration: none !important; }\n.fmstr-cmp-ffh-back {\n--fmstr-cmp-ffh-back-bg-card: #ffffff;\n--fmstr-cmp-ffh-back-bg-code: #0f172a;\n--fmstr-cmp-ffh-back-fg-1: #101828;\n--fmstr-cmp-ffh-back-fg-2: #475467;\n--fmstr-cmp-ffh-back-fg-3: #697586;\n--fmstr-cmp-ffh-back-violet-500: #7f56d9;\n--fmstr-cmp-ffh-back-violet-600: #6941c6;\n--fmstr-cmp-ffh-back-tint: #f7f3ff;\n--fmstr-cmp-ffh-back-edge: #e4d7ff;\n--fmstr-cmp-ffh-back-border: #eaecf0;\n--fmstr-cmp-ffh-back-red: #dc2626;\n--fmstr-cmp-ffh-back-red-bg: #fef2f2;\n--fmstr-cmp-ffh-back-red-edge: #fecaca;\n--fmstr-cmp-ffh-back-amber: #d97706;\n--fmstr-cmp-ffh-back-amber-bg: #fffbeb;\n--fmstr-cmp-ffh-back-amber-edge: #fde68a;\n--fmstr-cmp-ffh-back-green: #15803d;\n--fmstr-cmp-ffh-back-green-bg: #f0fdf4;\n--fmstr-cmp-ffh-back-green-edge: #bbf7d0;\n--fmstr-cmp-ffh-back-code-fg: #e2e8f0;\n--fmstr-cmp-ffh-back-shadow: 0 4px 20px rgba(16,24,40,.06), 0 2px 6px rgba(16,24,40,.04);\n\nbackground: transparent; padding: 56px 24px;\nfont-family: inherit; color: var(--fmstr-cmp-ffh-back-fg-1);\n}\n.fmstr-cmp-ffh-back *, .fmstr-cmp-ffh-back *::before, .fmstr-cmp-ffh-back *::after { box-sizing: border-box; }\n.fmstr-cmp-ffh-back__container { max-width: 820px; margin: 0 auto; }\n.fmstr-cmp-ffh-back__head { margin: 0 0 28px; }\n.fmstr-cmp-ffh-back__eyebrow {\ndisplay: inline-block; padding: 5px 12px; border-radius: 9999px;\nbackground: var(--fmstr-cmp-ffh-back-tint); color: var(--fmstr-cmp-ffh-back-violet-600);\nfont-size: 12px; font-weight: 600; letter-spacing: .04em;\ntext-transform: uppercase; border: 1px solid var(--fmstr-cmp-ffh-back-edge); margin: 0 0 14px;\n}\n.fmstr-cmp-ffh-back__h2 { font-size: clamp(26px, 3vw, 36px); font-weight: 700; line-height: 1.15; letter-spacing: -.02em; margin: 0; }\n.fmstr-cmp-ffh-back__intro { color: var(--fmstr-cmp-ffh-back-fg-3); font-size: 17px; line-height: 1.6; margin: 14px 0 0; }\n\n.fmstr-cmp-ffh-back__grid { display: grid; grid-template-columns: 1fr; gap: 16px; }\n.fmstr-cmp-ffh-back__card {\nbackground: var(--fmstr-cmp-ffh-back-bg-card);\nborder: 1px solid var(--fmstr-cmp-ffh-back-border);\nborder-radius: 18px; padding: 24px 26px; display: flex; flex-direction: column; gap: 16px;\nbox-shadow: var(--fmstr-cmp-ffh-back-shadow); position: relative;\n}\n.fmstr-cmp-ffh-back__card--red { border-top: 4px solid var(--fmstr-cmp-ffh-back-red); }\n.fmstr-cmp-ffh-back__card--amber { border-top: 4px solid var(--fmstr-cmp-ffh-back-amber); }\n.fmstr-cmp-ffh-back__card--green { border-top: 4px solid var(--fmstr-cmp-ffh-back-violet-500); background: linear-gradient(180deg, #fdfbff 0%, #fff 60%); }\n\n.fmstr-cmp-ffh-back__verdict {\ndisplay: inline-flex; align-items: center; gap: 8px; align-self: flex-start;\npadding: 5px 12px; border-radius: 9999px; font-size: 11.5px; font-weight: 700;\nletter-spacing: .04em; text-transform: uppercase;\n}\n.fmstr-cmp-ffh-back__verdict--red { background: var(--fmstr-cmp-ffh-back-red-bg); color: var(--fmstr-cmp-ffh-back-red); border: 1px solid var(--fmstr-cmp-ffh-back-red-edge); }\n.fmstr-cmp-ffh-back__verdict--amber { background: var(--fmstr-cmp-ffh-back-amber-bg); color: var(--fmstr-cmp-ffh-back-amber); border: 1px solid var(--fmstr-cmp-ffh-back-amber-edge); }\n.fmstr-cmp-ffh-back__verdict--green { background: var(--fmstr-cmp-ffh-back-tint); color: var(--fmstr-cmp-ffh-back-violet-600); border: 1px solid var(--fmstr-cmp-ffh-back-edge); }\n\n.fmstr-cmp-ffh-back__name { font-size: 19px; font-weight: 700; margin: 0; letter-spacing: -.01em; color: var(--fmstr-cmp-ffh-back-fg-1); }\n.fmstr-cmp-ffh-back__sub { font-size: 13.5px; color: var(--fmstr-cmp-ffh-back-fg-3); margin: -8px 0 0; line-height: 1.5; }\n\n.fmstr-cmp-ffh-back__code {\nbackground: var(--fmstr-cmp-ffh-back-bg-code);\nborder-radius: 10px; padding: 14px 16px;\nfont-family: ui-monospace, Menlo, Monaco, monospace;\nfont-size: 12px; line-height: 1.55;\ncolor: var(--fmstr-cmp-ffh-back-code-fg);\noverflow-x: auto; margin: 0; white-space: pre;\n}\n.fmstr-cmp-ffh-back__code code { font-family: inherit; }\n.fmstr-cmp-ffh-back__code .t { color: #f472b6; }\n.fmstr-cmp-ffh-back__code .a { color: #a5b4fc; }\n.fmstr-cmp-ffh-back__code .s { color: #86efac; }\n.fmstr-cmp-ffh-back__code .c { color: #64748b; font-style: italic; }\n\n.fmstr-cmp-ffh-back__list { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 8px; }\n.fmstr-cmp-ffh-back__row { display: flex; gap: 10px; font-size: 14px; line-height: 1.5; color: var(--fmstr-cmp-ffh-back-fg-2); }\n.fmstr-cmp-ffh-back__row::before {\ncontent: \"\"; width: 16px; height: 16px; border-radius: 50%; flex-shrink: 0; margin-top: 3px;\nbackground-repeat: no-repeat; background-position: center;\n}\n.fmstr-cmp-ffh-back__row--bad::before { background-color: var(--fmstr-cmp-ffh-back-red-bg); background-image: url(\"data:image\u002Fsvg+xml,%3Csvg xmlns='http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg' width='10' height='10' viewBox='0 0 10 10' fill='none' stroke='%23dc2626' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='M2 2 L8 8 M8 2 L2 8'\u002F%3E%3C\u002Fsvg%3E\"); }\n.fmstr-cmp-ffh-back__row--meh::before { background-color: var(--fmstr-cmp-ffh-back-amber-bg); background-image: url(\"data:image\u002Fsvg+xml,%3Csvg xmlns='http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg' width='10' height='10' viewBox='0 0 10 10' fill='none' stroke='%23d97706' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='M2 5 L8 5'\u002F%3E%3C\u002Fsvg%3E\"); }\n.fmstr-cmp-ffh-back__row--good::before { background-color: var(--fmstr-cmp-ffh-back-green-bg); background-image: url(\"data:image\u002Fsvg+xml,%3Csvg xmlns='http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg' width='10' height='10' viewBox='0 0 10 10' fill='none' stroke='%2315803d' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2 5 L4 7 L8 3'\u002F%3E%3C\u002Fsvg%3E\"); }\n.fmstr-cmp-ffh-back__row strong { color: var(--fmstr-cmp-ffh-back-fg-1); font-weight: 600; }\n\n.fmstr-cmp-ffh-back__cta {\nmargin-top: auto; padding-top: 4px;\ndisplay: inline-flex; align-items: center; gap: 8px;\ncolor: var(--fmstr-cmp-ffh-back-violet-600) !important;\nfont-weight: 600; font-size: 14.5px;\ntext-decoration: none !important;\n}\n.fmstr-cmp-ffh-back__cta:hover { text-decoration: underline !important; }\n\n@media (max-width: 760px) {\n.fmstr-cmp-ffh-back { padding: 40px 16px; }\n.fmstr-cmp-ffh-back__card { padding: 22px; }\n.fmstr-cmp-ffh-back__intro { font-size: 15.5px; }\n.fmstr-cmp-ffh-back__code { font-size: 11.5px; padding: 12px 14px; }\n}\n\u003C\u002Fstyle>\n\n\u003Csection class=\"fmstr-cmp-ffh-back\" aria-labelledby=\"fmstr-cmp-ffh-back-h2\">\n\u003Cdiv class=\"fmstr-cmp-ffh-back__container\">\n\u003Cdiv class=\"fmstr-cmp-ffh-back__head\">\n\u003Cspan class=\"fmstr-cmp-ffh-back__eyebrow\">Three honest paths\u003C\u002Fspan>\n\u003Ch2 class=\"fmstr-cmp-ffh-back__h2\" id=\"fmstr-cmp-ffh-back-h2\">What happens after the user clicks Submit\u003C\u002Fh2>\n\u003Cp class=\"fmstr-cmp-ffh-back__intro\">Without a backend, a feedback form is a dead form. The browser POSTs the data, the server returns 404, the user sees an error page. Here are the three real options, ranked by how much pain each one ships with.\u003C\u002Fp>\n\u003C\u002Fdiv>\n\n\u003Cdiv class=\"fmstr-cmp-ffh-back__grid\">\n\n\u003Carticle class=\"fmstr-cmp-ffh-back__card fmstr-cmp-ffh-back__card--red\">\n\u003Cspan class=\"fmstr-cmp-ffh-back__verdict fmstr-cmp-ffh-back__verdict--red\">Don&rsquo;t ship this\u003C\u002Fspan>\n\u003Ch3 class=\"fmstr-cmp-ffh-back__name\">Path 1: \u003Ccode>mailto:\u003C\u002Fcode>\u003C\u002Fh3>\n\u003Cp class=\"fmstr-cmp-ffh-back__sub\">The \"no server\" hack that loses about half your submissions.\u003C\u002Fp>\n\u003Cpre class=\"fmstr-cmp-ffh-back__code\">\u003Ccode>\u003Cspan class=\"c\">&lt;!-- Opens the user's mail client --&gt;\u003C\u002Fspan>\n\u003Cspan class=\"t\">&lt;form\u003C\u002Fspan>\n\u003Cspan class=\"a\">action\u003C\u002Fspan>=\u003Cspan class=\"s\">\"mailto:you@example.com\"\u003C\u002Fspan>\n\u003Cspan class=\"a\">method\u003C\u002Fspan>=\u003Cspan class=\"s\">\"post\"\u003C\u002Fspan>\n\u003Cspan class=\"a\">enctype\u003C\u002Fspan>=\u003Cspan class=\"s\">\"text\u002Fplain\"\u003C\u002Fspan>\u003Cspan class=\"t\">&gt;\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cul class=\"fmstr-cmp-ffh-back__list\">\n\u003Cli class=\"fmstr-cmp-ffh-back__row fmstr-cmp-ffh-back__row--bad\">\u003Cspan>\u003Cstrong>User-action required.\u003C\u002Fstrong> Browser opens a draft email. They have to click Send manually. Half won&rsquo;t.\u003C\u002Fspan>\u003C\u002Fli>\n\u003Cli class=\"fmstr-cmp-ffh-back__row fmstr-cmp-ffh-back__row--bad\">\u003Cspan>\u003Cstrong>Breaks on mobile.\u003C\u002Fstrong> Many phones have no configured mail client.\u003C\u002Fspan>\u003C\u002Fli>\n\u003Cli class=\"fmstr-cmp-ffh-back__row fmstr-cmp-ffh-back__row--bad\">\u003Cspan>\u003Cstrong>Spam-filter bait.\u003C\u002Fstrong> Resulting messages are unsigned and easy to flag.\u003C\u002Fspan>\u003C\u002Fli>\n\u003C\u002Ful>\n\u003C\u002Farticle>\n\n\u003Carticle class=\"fmstr-cmp-ffh-back__card fmstr-cmp-ffh-back__card--amber\">\n\u003Cspan class=\"fmstr-cmp-ffh-back__verdict fmstr-cmp-ffh-back__verdict--amber\">You&rsquo;ll maintain it\u003C\u002Fspan>\n\u003Ch3 class=\"fmstr-cmp-ffh-back__name\">Path 2: Your own server\u003C\u002Fh3>\n\u003Cp class=\"fmstr-cmp-ffh-back__sub\">PHP, Node, or whatever you already run. Full control, full ownership.\u003C\u002Fp>\n\u003Cpre class=\"fmstr-cmp-ffh-back__code\">\u003Ccode>\u003Cspan class=\"c\">\u002F\u002F minimal Node\u002FExpress receiver\u003C\u002Fspan>\napp.\u003Cspan class=\"t\">post\u003C\u002Fspan>(\u003Cspan class=\"s\">'\u002Fsubmit-feedback'\u003C\u002Fspan>, (req, res) =&gt; {\n\u003Cspan class=\"t\">const\u003C\u002Fspan> { name, email, message } = req.body;\n\u003Cspan class=\"t\">if\u003C\u002Fspan> (!validate(email)) \u003Cspan class=\"t\">return\u003C\u002Fspan> res.\u003Cspan class=\"t\">status\u003C\u002Fspan>(400);\ndb.\u003Cspan class=\"t\">insert\u003C\u002Fspan>({ name, email, message });\nres.\u003Cspan class=\"t\">redirect\u003C\u002Fspan>(\u003Cspan class=\"s\">'\u002Fthank-you'\u003C\u002Fspan>);\n});\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cul class=\"fmstr-cmp-ffh-back__list\">\n\u003Cli class=\"fmstr-cmp-ffh-back__row fmstr-cmp-ffh-back__row--meh\">\u003Cspan>\u003Cstrong>You own the server.\u003C\u002Fstrong> Hosting, TLS, scaling, uptime monitoring are yours.\u003C\u002Fspan>\u003C\u002Fli>\n\u003Cli class=\"fmstr-cmp-ffh-back__row fmstr-cmp-ffh-back__row--meh\">\u003Cspan>\u003Cstrong>Spam protection is on you.\u003C\u002Fstrong> Honeypot, rate limiting, CAPTCHA, all DIY.\u003C\u002Fspan>\u003C\u002Fli>\n\u003Cli class=\"fmstr-cmp-ffh-back__row fmstr-cmp-ffh-back__row--good\">\u003Cspan>\u003Cstrong>Maximum control.\u003C\u002Fstrong> Custom logic, database, queues, webhooks however you want.\u003C\u002Fspan>\u003C\u002Fli>\n\u003C\u002Ful>\n\u003C\u002Farticle>\n\n\u003Carticle class=\"fmstr-cmp-ffh-back__card fmstr-cmp-ffh-back__card--green\">\n\u003Cspan class=\"fmstr-cmp-ffh-back__verdict fmstr-cmp-ffh-back__verdict--green\">Skip the server\u003C\u002Fspan>\n\u003Ch3 class=\"fmstr-cmp-ffh-back__name\">Path 3: Formester HTML form backend\u003C\u002Fh3>\n\u003Cp class=\"fmstr-cmp-ffh-back__sub\">One \u003Ccode>action\u003C\u002Fcode> attribute swap. No server code, no infra.\u003C\u002Fp>\n\u003Cpre class=\"fmstr-cmp-ffh-back__code\">\u003Ccode>\u003Cspan class=\"c\">&lt;!-- The only change vs. Path 2 --&gt;\u003C\u002Fspan>\n\u003Cspan class=\"t\">&lt;form\u003C\u002Fspan>\n\u003Cspan class=\"a\">action\u003C\u002Fspan>=\u003Cspan class=\"s\">\"https:\u002F\u002Fapp.formester.com\u002F\u003C\u002Fspan>\n\u003Cspan class=\"s\">    api\u002Fv1\u002Fforms\u002FYOUR_ID\u002Fsubmissions\"\u003C\u002Fspan>\n\u003Cspan class=\"a\">method\u003C\u002Fspan>=\u003Cspan class=\"s\">\"post\"\u003C\u002Fspan>\u003Cspan class=\"t\">&gt;\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cul class=\"fmstr-cmp-ffh-back__list\">\n\u003Cli class=\"fmstr-cmp-ffh-back__row fmstr-cmp-ffh-back__row--good\">\u003Cspan>\u003Cstrong>Submissions land in the dashboard.\u003C\u002Fstrong> View, filter, \u003Ca href=\"https:\u002F\u002Fformester.com\u002Ffeatures\u002Fexport-form-submission-pdf\u002F\">export to PDF\u003C\u002Fa>, push to Sheets\u002FSlack\u002FHubSpot.\u003C\u002Fspan>\u003C\u002Fli>\n\u003Cli class=\"fmstr-cmp-ffh-back__row fmstr-cmp-ffh-back__row--good\">\u003Cspan>\u003Cstrong>Spam protection built in.\u003C\u002Fstrong> Honeypot plus \u003Ca href=\"https:\u002F\u002Fformester.com\u002Ffeatures\u002Fspam-protection\u002F\">reCAPTCHA-style checks\u003C\u002Fa> on every submission.\u003C\u002Fspan>\u003C\u002Fli>\n\u003Cli class=\"fmstr-cmp-ffh-back__row fmstr-cmp-ffh-back__row--good\">\u003Cspan>\u003Cstrong>Free with unlimited submissions.\u003C\u002Fstrong> Email notifications, dashboard, integrations included. Used by 56,000+ teams.\u003C\u002Fspan>\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ca class=\"fmstr-cmp-ffh-back__cta\" href=\"https:\u002F\u002Fformester.com\u002Ffeatures\u002Fhtml-form-backend\u002F\">See the HTML form backend &rarr;\u003C\u002Fa>\n\u003C\u002Farticle>\n\n\u003C\u002Fdiv>\n\u003C\u002Fdiv>\n\u003C\u002Fsection>\n\n\u003Cstyle>\n\u002F* host-link-override *\u002F\n.fmstr-cmp-ffh-code a { text-decoration: none !important; }\n.fmstr-cmp-ffh-code {\n--fmstr-cmp-ffh-code-bg-card: #ffffff;\n--fmstr-cmp-ffh-code-bg-code: #0f172a;\n--fmstr-cmp-ffh-code-bg-preview: #f7f7f9;\n--fmstr-cmp-ffh-code-fg-1: #101828;\n--fmstr-cmp-ffh-code-fg-2: #475467;\n--fmstr-cmp-ffh-code-fg-3: #697586;\n--fmstr-cmp-ffh-code-violet-500: #7f56d9;\n--fmstr-cmp-ffh-code-violet-600: #6941c6;\n--fmstr-cmp-ffh-code-tint: #f7f3ff;\n--fmstr-cmp-ffh-code-edge: #e4d7ff;\n--fmstr-cmp-ffh-code-border: #eaecf0;\n--fmstr-cmp-ffh-code-code-fg: #e2e8f0;\n--fmstr-cmp-ffh-code-code-tag: #f472b6;\n--fmstr-cmp-ffh-code-code-attr: #a5b4fc;\n--fmstr-cmp-ffh-code-code-str: #86efac;\n--fmstr-cmp-ffh-code-code-comment: #64748b;\n--fmstr-cmp-ffh-code-shadow: 0 4px 20px rgba(16,24,40,.06), 0 2px 6px rgba(16,24,40,.04);\n\nbackground: transparent; padding: 56px 24px;\nfont-family: inherit; color: var(--fmstr-cmp-ffh-code-fg-1);\n}\n.fmstr-cmp-ffh-code *, .fmstr-cmp-ffh-code *::before, .fmstr-cmp-ffh-code *::after { box-sizing: border-box; }\n.fmstr-cmp-ffh-code__container { max-width: 820px; margin: 0 auto; }\n.fmstr-cmp-ffh-code__head { max-width: 780px; margin: 0 0 32px; }\n.fmstr-cmp-ffh-code__eyebrow {\ndisplay: inline-block; padding: 5px 12px; border-radius: 9999px;\nbackground: var(--fmstr-cmp-ffh-code-tint); color: var(--fmstr-cmp-ffh-code-violet-600);\nfont-size: 12px; font-weight: 600; letter-spacing: .04em;\ntext-transform: uppercase; border: 1px solid var(--fmstr-cmp-ffh-code-edge); margin: 0 0 14px;\n}\n.fmstr-cmp-ffh-code__h2 { font-size: clamp(26px, 3vw, 36px); font-weight: 700; line-height: 1.15; letter-spacing: -.02em; margin: 0; }\n.fmstr-cmp-ffh-code__intro { color: var(--fmstr-cmp-ffh-code-fg-3); font-size: 17px; line-height: 1.6; margin: 14px 0 0; }\n\n.fmstr-cmp-ffh-code__grid {\ndisplay: grid; grid-template-columns: 1fr; gap: 0;\nbackground: var(--fmstr-cmp-ffh-code-bg-card);\nborder: 1px solid var(--fmstr-cmp-ffh-code-border);\nborder-radius: 20px; overflow: hidden;\nbox-shadow: var(--fmstr-cmp-ffh-code-shadow);\n}\n\n.fmstr-cmp-ffh-code__preview-pane {\nbackground: var(--fmstr-cmp-ffh-code-bg-preview);\npadding: 28px 24px;\ndisplay: flex; flex-direction: column; gap: 14px;\nborder-bottom: 1px solid var(--fmstr-cmp-ffh-code-border);\n}\n.fmstr-cmp-ffh-code__preview-label {\nfont-size: 11px; font-weight: 700; letter-spacing: .08em;\ntext-transform: uppercase; color: var(--fmstr-cmp-ffh-code-fg-3);\ndisplay: flex; align-items: center; gap: 8px;\n}\n.fmstr-cmp-ffh-code__preview-label::before {\ncontent: \"\"; width: 8px; height: 8px; border-radius: 50%;\nbackground: #22c55e; flex-shrink: 0;\n}\n.fmstr-cmp-ffh-code__preview-form {\nbackground: #fff; padding: 22px 20px; border-radius: 12px;\nbox-shadow: 0 2px 12px rgba(0,0,0,0.06);\ndisplay: flex; flex-direction: column; gap: 14px;\n}\n.fmstr-cmp-ffh-code__preview-h { font-size: 16px; font-weight: 700; text-align: center; margin: 0 0 4px; color: var(--fmstr-cmp-ffh-code-fg-1); }\n.fmstr-cmp-ffh-code__preview-field { display: flex; flex-direction: column; gap: 6px; }\n.fmstr-cmp-ffh-code__preview-label-row { font-size: 12.5px; font-weight: 600; color: var(--fmstr-cmp-ffh-code-fg-1); }\n.fmstr-cmp-ffh-code__preview-input {\nbackground: #fff; border: 1px solid #d0d0d6; border-radius: 8px;\npadding: 9px 11px; font-size: 12.5px; color: var(--fmstr-cmp-ffh-code-fg-3);\n}\n.fmstr-cmp-ffh-code__preview-input--focus { outline: 2px solid var(--fmstr-cmp-ffh-code-violet-500); outline-offset: 1px; border-color: var(--fmstr-cmp-ffh-code-violet-500); color: var(--fmstr-cmp-ffh-code-fg-1); }\n.fmstr-cmp-ffh-code__preview-select {\nbackground: #fff; border: 1px solid #d0d0d6; border-radius: 8px;\npadding: 9px 11px; font-size: 12.5px; color: var(--fmstr-cmp-ffh-code-fg-3);\ndisplay: flex; justify-content: space-between; align-items: center;\n}\n.fmstr-cmp-ffh-code__preview-textarea {\nbackground: #fff; border: 1px solid #d0d0d6; border-radius: 8px;\npadding: 9px 11px; font-size: 12.5px; color: var(--fmstr-cmp-ffh-code-fg-3);\nmin-height: 54px;\n}\n.fmstr-cmp-ffh-code__preview-btn {\nbackground: var(--fmstr-cmp-ffh-code-violet-500); color: #fff;\npadding: 10px; border-radius: 8px; text-align: center;\nfont-weight: 600; font-size: 13px; margin-top: 4px;\n}\n.fmstr-cmp-ffh-code__preview-caption {\nfont-size: 12px; color: var(--fmstr-cmp-ffh-code-fg-3); line-height: 1.5; margin: 4px 0 0;\n}\n\n.fmstr-cmp-ffh-code__code-pane {\nbackground: var(--fmstr-cmp-ffh-code-bg-code);\nposition: relative; max-height: 560px;\ndisplay: flex; flex-direction: column;\n}\n.fmstr-cmp-ffh-code__code-header {\ndisplay: flex; align-items: center; justify-content: space-between;\npadding: 14px 18px; border-bottom: 1px solid rgba(255,255,255,0.08);\ncolor: var(--fmstr-cmp-ffh-code-code-comment);\nfont-family: ui-monospace, Menlo, Monaco, monospace; font-size: 12px;\n}\n.fmstr-cmp-ffh-code__code-filename { display: flex; align-items: center; gap: 8px; }\n.fmstr-cmp-ffh-code__code-filename::before {\ncontent: \"\"; width: 10px; height: 10px; border-radius: 50%; background: #f87171;\nbox-shadow: 16px 0 0 #fbbf24, 32px 0 0 #34d399;\nmargin-right: 12px;\n}\n.fmstr-cmp-ffh-code__code-copy {\nbackground: rgba(127, 86, 217, 0.18) !important;\ncolor: #c4b5fd !important; border: 1px solid rgba(127, 86, 217, 0.4);\npadding: 6px 14px; border-radius: 6px; font-size: 12px; font-weight: 600;\ncursor: pointer; font-family: ui-monospace, Menlo, Monaco, monospace;\ndisplay: inline-flex; align-items: center; gap: 6px;\n}\n.fmstr-cmp-ffh-code__code-copy:hover { background: rgba(127, 86, 217, 0.28) !important; }\n.fmstr-cmp-ffh-code__code-body {\nmargin: 0; padding: 18px 20px;\nfont-family: ui-monospace, Menlo, Monaco, monospace;\nfont-size: 12.5px; line-height: 1.65;\ncolor: var(--fmstr-cmp-ffh-code-code-fg);\noverflow: auto; flex-grow: 1;\nwhite-space: pre;\nscrollbar-width: thin; scrollbar-color: rgba(167,139,250,.35) transparent;\n}\n.fmstr-cmp-ffh-code__code-body::-webkit-scrollbar { width: 10px; height: 10px; }\n.fmstr-cmp-ffh-code__code-body::-webkit-scrollbar-track { background: transparent; }\n.fmstr-cmp-ffh-code__code-body::-webkit-scrollbar-thumb { background: rgba(167,139,250,.3); border-radius: 5px; }\n.fmstr-cmp-ffh-code__code-body::-webkit-scrollbar-thumb:hover { background: rgba(167,139,250,.5); }\n.fmstr-cmp-ffh-code__code-body code { font-family: inherit; }\n.fmstr-cmp-ffh-code__tag { color: var(--fmstr-cmp-ffh-code-code-tag); }\n.fmstr-cmp-ffh-code__attr { color: var(--fmstr-cmp-ffh-code-code-attr); }\n.fmstr-cmp-ffh-code__str { color: var(--fmstr-cmp-ffh-code-code-str); }\n.fmstr-cmp-ffh-code__cmt { color: var(--fmstr-cmp-ffh-code-code-comment); font-style: italic; }\n\n.fmstr-cmp-ffh-code__foot {\nmargin: 20px auto 0; max-width: 780px; text-align: center;\ncolor: var(--fmstr-cmp-ffh-code-fg-3); font-size: 14.5px; line-height: 1.6;\n}\n.fmstr-cmp-ffh-code__foot a { color: var(--fmstr-cmp-ffh-code-violet-600) !important; font-weight: 600; }\n.fmstr-cmp-ffh-code__foot a:hover { text-decoration: underline !important; }\n\n@media (max-width: 760px) {\n.fmstr-cmp-ffh-code { padding: 40px 16px; }\n.fmstr-cmp-ffh-code__grid { border-radius: 16px; }\n.fmstr-cmp-ffh-code__preview-pane { padding: 22px 18px; }\n.fmstr-cmp-ffh-code__code-pane { max-height: 420px; }\n.fmstr-cmp-ffh-code__code-body { font-size: 11.5px; padding: 14px 16px; }\n.fmstr-cmp-ffh-code__intro { font-size: 15.5px; }\n}\n\u003C\u002Fstyle>\n\n\u003Csection class=\"fmstr-cmp-ffh-code\" aria-labelledby=\"fmstr-cmp-ffh-code-h2\">\n\u003Cdiv class=\"fmstr-cmp-ffh-code__container\">\n\u003Cdiv class=\"fmstr-cmp-ffh-code__head\">\n\u003Cspan class=\"fmstr-cmp-ffh-code__eyebrow\">Copy, paste, ship\u003C\u002Fspan>\n\u003Ch2 class=\"fmstr-cmp-ffh-code__h2\" id=\"fmstr-cmp-ffh-code-h2\">The complete feedback form, in one file\u003C\u002Fh2>\n\u003Cp class=\"fmstr-cmp-ffh-code__intro\">Structure, styling, and accessible JavaScript validation in a single working file. Save as \u003Ccode>feedback.html\u003C\u002Fcode>, swap the \u003Ccode>action\u003C\u002Fcode> URL, and the form is live.\u003C\u002Fp>\n\u003C\u002Fdiv>\n\n\u003Cdiv class=\"fmstr-cmp-ffh-code__grid\">\n\u003Cdiv class=\"fmstr-cmp-ffh-code__preview-pane\">\n\u003Cdiv class=\"fmstr-cmp-ffh-code__preview-label\">Live preview\u003C\u002Fdiv>\n\u003Cdiv class=\"fmstr-cmp-ffh-code__preview-form\">\n\u003Ch3 class=\"fmstr-cmp-ffh-code__preview-h\">Tell us what you think\u003C\u002Fh3>\n\u003Cdiv class=\"fmstr-cmp-ffh-code__preview-field\">\n\u003Cspan class=\"fmstr-cmp-ffh-code__preview-label-row\">Name\u003C\u002Fspan>\n\u003Cdiv class=\"fmstr-cmp-ffh-code__preview-input\">Jane Doe\u003C\u002Fdiv>\n\u003C\u002Fdiv>\n\u003Cdiv class=\"fmstr-cmp-ffh-code__preview-field\">\n\u003Cspan class=\"fmstr-cmp-ffh-code__preview-label-row\">Email\u003C\u002Fspan>\n\u003Cdiv class=\"fmstr-cmp-ffh-code__preview-input fmstr-cmp-ffh-code__preview-input--focus\">jane@example.com\u003C\u002Fdiv>\n\u003C\u002Fdiv>\n\u003Cdiv class=\"fmstr-cmp-ffh-code__preview-field\">\n\u003Cspan class=\"fmstr-cmp-ffh-code__preview-label-row\">How was your experience?\u003C\u002Fspan>\n\u003Cdiv class=\"fmstr-cmp-ffh-code__preview-select\">\u003Cspan>Loved it\u003C\u002Fspan>\u003Cspan>&#9662;\u003C\u002Fspan>\u003C\u002Fdiv>\n\u003C\u002Fdiv>\n\u003Cdiv class=\"fmstr-cmp-ffh-code__preview-field\">\n\u003Cspan class=\"fmstr-cmp-ffh-code__preview-label-row\">Your feedback\u003C\u002Fspan>\n\u003Cdiv class=\"fmstr-cmp-ffh-code__preview-textarea\">The dashboard is fast and the export to PDF saved my week.\u003C\u002Fdiv>\n\u003C\u002Fdiv>\n\u003Cdiv class=\"fmstr-cmp-ffh-code__preview-btn\">Send feedback\u003C\u002Fdiv>\n\u003C\u002Fdiv>\n\u003Cp class=\"fmstr-cmp-ffh-code__preview-caption\">Rendered output. Keyboard-accessible focus ring on the active field, inline error slot ready, mobile-friendly layout.\u003C\u002Fp>\n\u003C\u002Fdiv>\n\n\u003Cdiv class=\"fmstr-cmp-ffh-code__code-pane\">\n\u003Cdiv class=\"fmstr-cmp-ffh-code__code-header\">\n\u003Cspan class=\"fmstr-cmp-ffh-code__code-filename\">feedback.html\u003C\u002Fspan>\n\u003Cbutton type=\"button\" class=\"fmstr-cmp-ffh-code__code-copy\" aria-label=\"Copy code\">Copy\u003C\u002Fbutton>\n\u003C\u002Fdiv>\n\u003Cpre class=\"fmstr-cmp-ffh-code__code-body\">\u003Ccode>\u003Cspan class=\"fmstr-cmp-ffh-code__cmt\">&lt;!DOCTYPE html&gt;\u003C\u002Fspan>\n\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&lt;html\u003C\u002Fspan> \u003Cspan class=\"fmstr-cmp-ffh-code__attr\">lang\u003C\u002Fspan>=\u003Cspan class=\"fmstr-cmp-ffh-code__str\">\"en\"\u003C\u002Fspan>\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&gt;\u003C\u002Fspan>\n\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&lt;head&gt;\u003C\u002Fspan>\n\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&lt;meta\u003C\u002Fspan> \u003Cspan class=\"fmstr-cmp-ffh-code__attr\">charset\u003C\u002Fspan>=\u003Cspan class=\"fmstr-cmp-ffh-code__str\">\"UTF-8\"\u003C\u002Fspan>\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&gt;\u003C\u002Fspan>\n\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&lt;meta\u003C\u002Fspan> \u003Cspan class=\"fmstr-cmp-ffh-code__attr\">name\u003C\u002Fspan>=\u003Cspan class=\"fmstr-cmp-ffh-code__str\">\"viewport\"\u003C\u002Fspan> \u003Cspan class=\"fmstr-cmp-ffh-code__attr\">content\u003C\u002Fspan>=\u003Cspan class=\"fmstr-cmp-ffh-code__str\">\"width=device-width, initial-scale=1.0\"\u003C\u002Fspan>\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&gt;\u003C\u002Fspan>\n\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&lt;title&gt;\u003C\u002Fspan>Feedback Form\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&lt;\u002Ftitle&gt;\u003C\u002Fspan>\n\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&lt;style&gt;\u003C\u002Fspan>\nbody { font-family: system-ui, sans-serif; background: #f7f7f9; padding: 40px 16px; }\nform { max-width: 480px; margin: 0 auto; background: #fff; padding: 24px; border-radius: 12px; }\n.field { margin-bottom: 16px; }\nlabel { display: block; font-weight: 600; margin-bottom: 6px; }\ninput, select, textarea { width: 100%; padding: 10px 12px; border: 1px solid #d0d0d6; border-radius: 8px; box-sizing: border-box; }\ninput:focus, select:focus, textarea:focus { outline: 2px solid #5b6cff; border-color: #5b6cff; }\n[aria-invalid=\"true\"] { border-color: #d33; }\n.error { display: block; color: #d33; font-size: 0.8rem; margin-top: 4px; }\nbutton { width: 100%; padding: 12px; background: #5b6cff; color: #fff; font-weight: 600; border: none; border-radius: 8px; cursor: pointer; }\n\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&lt;\u002Fstyle&gt;\u003C\u002Fspan>\n\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&lt;\u002Fhead&gt;\u003C\u002Fspan>\n\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&lt;body&gt;\u003C\u002Fspan>\n\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&lt;h1&gt;\u003C\u002Fspan>Tell us what you think\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&lt;\u002Fh1&gt;\u003C\u002Fspan>\n\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&lt;form\u003C\u002Fspan> \u003Cspan class=\"fmstr-cmp-ffh-code__attr\">id\u003C\u002Fspan>=\u003Cspan class=\"fmstr-cmp-ffh-code__str\">\"feedback-form\"\u003C\u002Fspan> \u003Cspan class=\"fmstr-cmp-ffh-code__attr\">action\u003C\u002Fspan>=\u003Cspan class=\"fmstr-cmp-ffh-code__str\">\"https:\u002F\u002Fapp.formester.com\u002Fapi\u002Fv1\u002Fforms\u002FYOUR_FORM_ID\u002Fsubmissions\"\u003C\u002Fspan> \u003Cspan class=\"fmstr-cmp-ffh-code__attr\">method\u003C\u002Fspan>=\u003Cspan class=\"fmstr-cmp-ffh-code__str\">\"post\"\u003C\u002Fspan> \u003Cspan class=\"fmstr-cmp-ffh-code__attr\">novalidate\u003C\u002Fspan>\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&gt;\u003C\u002Fspan>\n\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&lt;div\u003C\u002Fspan> \u003Cspan class=\"fmstr-cmp-ffh-code__attr\">class\u003C\u002Fspan>=\u003Cspan class=\"fmstr-cmp-ffh-code__str\">\"field\"\u003C\u002Fspan>\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&gt;\u003C\u002Fspan>\n\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&lt;label\u003C\u002Fspan> \u003Cspan class=\"fmstr-cmp-ffh-code__attr\">for\u003C\u002Fspan>=\u003Cspan class=\"fmstr-cmp-ffh-code__str\">\"name\"\u003C\u002Fspan>\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&gt;\u003C\u002Fspan>Name\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&lt;\u002Flabel&gt;\u003C\u002Fspan>\n\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&lt;input\u003C\u002Fspan> \u003Cspan class=\"fmstr-cmp-ffh-code__attr\">type\u003C\u002Fspan>=\u003Cspan class=\"fmstr-cmp-ffh-code__str\">\"text\"\u003C\u002Fspan> \u003Cspan class=\"fmstr-cmp-ffh-code__attr\">id\u003C\u002Fspan>=\u003Cspan class=\"fmstr-cmp-ffh-code__str\">\"name\"\u003C\u002Fspan> \u003Cspan class=\"fmstr-cmp-ffh-code__attr\">name\u003C\u002Fspan>=\u003Cspan class=\"fmstr-cmp-ffh-code__str\">\"name\"\u003C\u002Fspan> \u003Cspan class=\"fmstr-cmp-ffh-code__attr\">autocomplete\u003C\u002Fspan>=\u003Cspan class=\"fmstr-cmp-ffh-code__str\">\"name\"\u003C\u002Fspan> \u003Cspan class=\"fmstr-cmp-ffh-code__attr\">required\u003C\u002Fspan>\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&gt;\u003C\u002Fspan>\n\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&lt;\u002Fdiv&gt;\u003C\u002Fspan>\n\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&lt;div\u003C\u002Fspan> \u003Cspan class=\"fmstr-cmp-ffh-code__attr\">class\u003C\u002Fspan>=\u003Cspan class=\"fmstr-cmp-ffh-code__str\">\"field\"\u003C\u002Fspan>\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&gt;\u003C\u002Fspan>\n\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&lt;label\u003C\u002Fspan> \u003Cspan class=\"fmstr-cmp-ffh-code__attr\">for\u003C\u002Fspan>=\u003Cspan class=\"fmstr-cmp-ffh-code__str\">\"email\"\u003C\u002Fspan>\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&gt;\u003C\u002Fspan>Email\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&lt;\u002Flabel&gt;\u003C\u002Fspan>\n\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&lt;input\u003C\u002Fspan> \u003Cspan class=\"fmstr-cmp-ffh-code__attr\">type\u003C\u002Fspan>=\u003Cspan class=\"fmstr-cmp-ffh-code__str\">\"email\"\u003C\u002Fspan> \u003Cspan class=\"fmstr-cmp-ffh-code__attr\">id\u003C\u002Fspan>=\u003Cspan class=\"fmstr-cmp-ffh-code__str\">\"email\"\u003C\u002Fspan> \u003Cspan class=\"fmstr-cmp-ffh-code__attr\">name\u003C\u002Fspan>=\u003Cspan class=\"fmstr-cmp-ffh-code__str\">\"email\"\u003C\u002Fspan> \u003Cspan class=\"fmstr-cmp-ffh-code__attr\">autocomplete\u003C\u002Fspan>=\u003Cspan class=\"fmstr-cmp-ffh-code__str\">\"email\"\u003C\u002Fspan> \u003Cspan class=\"fmstr-cmp-ffh-code__attr\">required\u003C\u002Fspan>\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&gt;\u003C\u002Fspan>\n\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&lt;\u002Fdiv&gt;\u003C\u002Fspan>\n\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&lt;div\u003C\u002Fspan> \u003Cspan class=\"fmstr-cmp-ffh-code__attr\">class\u003C\u002Fspan>=\u003Cspan class=\"fmstr-cmp-ffh-code__str\">\"field\"\u003C\u002Fspan>\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&gt;\u003C\u002Fspan>\n\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&lt;label\u003C\u002Fspan> \u003Cspan class=\"fmstr-cmp-ffh-code__attr\">for\u003C\u002Fspan>=\u003Cspan class=\"fmstr-cmp-ffh-code__str\">\"rating\"\u003C\u002Fspan>\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&gt;\u003C\u002Fspan>How was your experience?\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&lt;\u002Flabel&gt;\u003C\u002Fspan>\n\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&lt;select\u003C\u002Fspan> \u003Cspan class=\"fmstr-cmp-ffh-code__attr\">id\u003C\u002Fspan>=\u003Cspan class=\"fmstr-cmp-ffh-code__str\">\"rating\"\u003C\u002Fspan> \u003Cspan class=\"fmstr-cmp-ffh-code__attr\">name\u003C\u002Fspan>=\u003Cspan class=\"fmstr-cmp-ffh-code__str\">\"rating\"\u003C\u002Fspan> \u003Cspan class=\"fmstr-cmp-ffh-code__attr\">required\u003C\u002Fspan>\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&gt;\u003C\u002Fspan>\n\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&lt;option\u003C\u002Fspan> \u003Cspan class=\"fmstr-cmp-ffh-code__attr\">value\u003C\u002Fspan>=\u003Cspan class=\"fmstr-cmp-ffh-code__str\">\"\"\u003C\u002Fspan>\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&gt;\u003C\u002Fspan>Pick one\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&lt;\u002Foption&gt;\u003C\u002Fspan>\n\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&lt;option\u003C\u002Fspan> \u003Cspan class=\"fmstr-cmp-ffh-code__attr\">value\u003C\u002Fspan>=\u003Cspan class=\"fmstr-cmp-ffh-code__str\">\"5\"\u003C\u002Fspan>\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&gt;\u003C\u002Fspan>Loved it\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&lt;\u002Foption&gt;\u003C\u002Fspan>\n\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&lt;option\u003C\u002Fspan> \u003Cspan class=\"fmstr-cmp-ffh-code__attr\">value\u003C\u002Fspan>=\u003Cspan class=\"fmstr-cmp-ffh-code__str\">\"3\"\u003C\u002Fspan>\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&gt;\u003C\u002Fspan>Okay\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&lt;\u002Foption&gt;\u003C\u002Fspan>\n\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&lt;option\u003C\u002Fspan> \u003Cspan class=\"fmstr-cmp-ffh-code__attr\">value\u003C\u002Fspan>=\u003Cspan class=\"fmstr-cmp-ffh-code__str\">\"1\"\u003C\u002Fspan>\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&gt;\u003C\u002Fspan>Bad\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&lt;\u002Foption&gt;\u003C\u002Fspan>\n\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&lt;\u002Fselect&gt;\u003C\u002Fspan>\n\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&lt;\u002Fdiv&gt;\u003C\u002Fspan>\n\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&lt;div\u003C\u002Fspan> \u003Cspan class=\"fmstr-cmp-ffh-code__attr\">class\u003C\u002Fspan>=\u003Cspan class=\"fmstr-cmp-ffh-code__str\">\"field\"\u003C\u002Fspan>\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&gt;\u003C\u002Fspan>\n\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&lt;label\u003C\u002Fspan> \u003Cspan class=\"fmstr-cmp-ffh-code__attr\">for\u003C\u002Fspan>=\u003Cspan class=\"fmstr-cmp-ffh-code__str\">\"message\"\u003C\u002Fspan>\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&gt;\u003C\u002Fspan>Your feedback\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&lt;\u002Flabel&gt;\u003C\u002Fspan>\n\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&lt;textarea\u003C\u002Fspan> \u003Cspan class=\"fmstr-cmp-ffh-code__attr\">id\u003C\u002Fspan>=\u003Cspan class=\"fmstr-cmp-ffh-code__str\">\"message\"\u003C\u002Fspan> \u003Cspan class=\"fmstr-cmp-ffh-code__attr\">name\u003C\u002Fspan>=\u003Cspan class=\"fmstr-cmp-ffh-code__str\">\"message\"\u003C\u002Fspan> \u003Cspan class=\"fmstr-cmp-ffh-code__attr\">rows\u003C\u002Fspan>=\u003Cspan class=\"fmstr-cmp-ffh-code__str\">\"5\"\u003C\u002Fspan> \u003Cspan class=\"fmstr-cmp-ffh-code__attr\">required\u003C\u002Fspan>\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&gt;&lt;\u002Ftextarea&gt;\u003C\u002Fspan>\n\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&lt;\u002Fdiv&gt;\u003C\u002Fspan>\n\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&lt;button\u003C\u002Fspan> \u003Cspan class=\"fmstr-cmp-ffh-code__attr\">type\u003C\u002Fspan>=\u003Cspan class=\"fmstr-cmp-ffh-code__str\">\"submit\"\u003C\u002Fspan>\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&gt;\u003C\u002Fspan>Send feedback\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&lt;\u002Fbutton&gt;\u003C\u002Fspan>\n\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&lt;\u002Fform&gt;\u003C\u002Fspan>\n\n\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&lt;script&gt;\u003C\u002Fspan>\n\u003Cspan class=\"fmstr-cmp-ffh-code__cmt\">\u002F\u002F Accessible inline validation: aria-invalid, aria-describedby, focus management\u003C\u002Fspan>\nconst form = document.getElementById(\u003Cspan class=\"fmstr-cmp-ffh-code__str\">'feedback-form'\u003C\u002Fspan>);\nform.addEventListener(\u003Cspan class=\"fmstr-cmp-ffh-code__str\">'submit'\u003C\u002Fspan>, (e) =&gt; {\nlet firstInvalid = null;\n[...form.querySelectorAll(\u003Cspan class=\"fmstr-cmp-ffh-code__str\">'input, select, textarea'\u003C\u002Fspan>)].forEach((input) =&gt; {\nconst valid = input.value.trim() &amp;&amp; (input.type !== \u003Cspan class=\"fmstr-cmp-ffh-code__str\">'email'\u003C\u002Fspan> || \u002F^\\S+@\\S+\\.\\S+$\u002F.test(input.value));\ninput.setAttribute(\u003Cspan class=\"fmstr-cmp-ffh-code__str\">'aria-invalid'\u003C\u002Fspan>, valid ? \u003Cspan class=\"fmstr-cmp-ffh-code__str\">'false'\u003C\u002Fspan> : \u003Cspan class=\"fmstr-cmp-ffh-code__str\">'true'\u003C\u002Fspan>);\nif (!valid &amp;&amp; !firstInvalid) firstInvalid = input;\n});\nif (firstInvalid) { e.preventDefault(); firstInvalid.focus(); }\n});\n\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&lt;\u002Fscript&gt;\u003C\u002Fspan>\n\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&lt;\u002Fbody&gt;\u003C\u002Fspan>\n\u003Cspan class=\"fmstr-cmp-ffh-code__tag\">&lt;\u002Fhtml&gt;\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\n\u003C\u002Fdiv>\n\u003C\u002Fdiv>\n\n\u003Cp class=\"fmstr-cmp-ffh-code__foot\">The \u003Ccode>action\u003C\u002Fcode> URL above points to \u003Ca href=\"https:\u002F\u002Fformester.com\u002Ffeatures\u002Fhtml-form-backend\u002F\">Formester&rsquo;s HTML form backend\u003C\u002Fa>. Replace \u003Ccode>YOUR_FORM_ID\u003C\u002Fcode> with your form&rsquo;s ID, or point it at your own server. Everything else stays the same.\u003C\u002Fp>\n\u003C\u002Fdiv>\n\u003C\u002Fsection>\n\n\u003Csection class=\"fmstr-cmp-ffh-body\" aria-label=\"Common mistakes and variants\">\n\u003Cdiv class=\"fmstr-cmp-ffh-body__container\">\n\n\u003Ch2 class=\"fmstr-cmp-ffh-body__h2\">Common mistakes that break feedback forms\u003C\u002Fh2>\n\u003Cul>\n\u003Cli>\u003Cstrong>\u003Ccode>mailto:\u003C\u002Fcode> as the action.\u003C\u002Fstrong> Looks like the easy answer. Drops half your submissions because the user has to manually send the draft. Use a real backend.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Missing \u003Ccode>name\u003C\u002Fcode> attributes.\u003C\u002Fstrong> The form POSTs successfully but the server gets empty fields. \u003Ccode>id\u003C\u002Fcode> is for CSS and labels; \u003Ccode>name\u003C\u002Fcode> is what the server reads.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Removed focus outlines.\u003C\u002Fstrong> \u003Ccode>outline: none\u003C\u002Fcode> is the most copy-pasted CSS mistake on the web. It breaks keyboard navigation. Replace the outline; don't delete it.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Client-side validation only.\u003C\u002Fstrong> A user with DevTools open can submit anything. Validate on the server too.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>No spam protection.\u003C\u002Fstrong> Public forms attract bots within hours. Add a honeypot field (a hidden input that bots fill and humans don't) or a CAPTCHA. \u003Ca href=\"https:\u002F\u002Fformester.com\u002Ffeatures\u002Fspam-protection\u002F\">Formester's backend\u003C\u002Fa> does this automatically.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>No confirmation page or message.\u003C\u002Fstrong> The user submits, the page reloads, nothing visibly changes. They submit again. Add a \u003Ccode>&lt;p role=\"status\"&gt;Thanks, we got it&lt;\u002Fp&gt;\u003C\u002Fcode> or redirect to a thank-you page.\u003C\u002Fli>\n\u003C\u002Ful>\n\n\u003Ch2 class=\"fmstr-cmp-ffh-body__h2\">Variants of the feedback form\u003C\u002Fh2>\n\u003Cp>The base form covers most cases. Three common variants:\u003C\u002Fp>\n\u003Cdiv class=\"fmstr-cmp-ffh-body__variants\">\n\u003Cdiv class=\"fmstr-cmp-ffh-body__variant\">\n\u003Ch4>Customer feedback (with rating)\u003C\u002Fh4>\n\u003Cp>Add a 1-5 star scale instead of the dropdown. The \u003Ccode>&lt;input type=\"range\"&gt;\u003C\u002Fcode> works, but a row of radio buttons styled as stars is clearer for screen readers. The \u003Ca href=\"https:\u002F\u002Fformester.com\u002Ftemplates\u002Fcustomer-feedback-form-31840\u002F\">customer feedback form template\u003C\u002Fa> ships this layout pre-built.\u003C\u002Fp>\n\u003C\u002Fdiv>\n\u003Cdiv class=\"fmstr-cmp-ffh-body__variant\">\n\u003Ch4>Product feedback (with feature picker)\u003C\u002Fh4>\n\u003Cp>Add a checkbox group: \"Which features did you use?\" with options like Onboarding, Search, Reporting. Use \u003Ccode>&lt;fieldset&gt;&lt;legend&gt;\u003C\u002Fcode> around the group so screen readers announce it as one question. The \u003Ca href=\"https:\u002F\u002Fformester.com\u002Ftemplates\u002Fcategories\u002Ffeedback-forms\u002F\">feedback form templates library\u003C\u002Fa> has a fuller version.\u003C\u002Fp>\n\u003C\u002Fdiv>\n\u003Cdiv class=\"fmstr-cmp-ffh-body__variant\">\n\u003Ch4>Employee feedback (anonymous)\u003C\u002Fh4>\n\u003Cp>Drop the name and email fields entirely. Add a \"Department\" dropdown and a longer text area. If you collect this through Formester, turn off IP tracking in the form settings to keep submissions genuinely anonymous. The \u003Ca href=\"https:\u002F\u002Fformester.com\u002Ftemplates\u002Fcategories\u002Ffeedback-forms\u002F\">employee feedback templates\u003C\u002Fa> are preconfigured for this.\u003C\u002Fp>\n\u003C\u002Fdiv>\n\u003C\u002Fdiv>\n\n\u003C\u002Fdiv>\n\u003C\u002Fsection>\n\n\u003Cstyle>\n\u002F* host-link-override *\u002F\n.fmstr-cmp-ffh-a11y a { text-decoration: none !important; }\n.fmstr-cmp-ffh-a11y {\n--fmstr-cmp-ffh-a11y-bg-card: #ffffff;\n--fmstr-cmp-ffh-a11y-bg-code: #0f172a;\n--fmstr-cmp-ffh-a11y-fg-1: #101828;\n--fmstr-cmp-ffh-a11y-fg-2: #475467;\n--fmstr-cmp-ffh-a11y-fg-3: #697586;\n--fmstr-cmp-ffh-a11y-violet-500: #7f56d9;\n--fmstr-cmp-ffh-a11y-violet-600: #6941c6;\n--fmstr-cmp-ffh-a11y-tint: #f7f3ff;\n--fmstr-cmp-ffh-a11y-edge: #e4d7ff;\n--fmstr-cmp-ffh-a11y-border: #eaecf0;\n--fmstr-cmp-ffh-a11y-red-bg: #fef2f2;\n--fmstr-cmp-ffh-a11y-red-edge: #fecaca;\n--fmstr-cmp-ffh-a11y-red: #b91c1c;\n--fmstr-cmp-ffh-a11y-green-bg: #f0fdf4;\n--fmstr-cmp-ffh-a11y-green-edge: #bbf7d0;\n--fmstr-cmp-ffh-a11y-green: #15803d;\n--fmstr-cmp-ffh-a11y-shadow: 0 4px 20px rgba(16,24,40,.06), 0 2px 6px rgba(16,24,40,.04);\n\nbackground: transparent; padding: 56px 24px;\nfont-family: inherit; color: var(--fmstr-cmp-ffh-a11y-fg-1);\n}\n.fmstr-cmp-ffh-a11y *, .fmstr-cmp-ffh-a11y *::before, .fmstr-cmp-ffh-a11y *::after { box-sizing: border-box; }\n.fmstr-cmp-ffh-a11y__container { max-width: 820px; margin: 0 auto; }\n.fmstr-cmp-ffh-a11y__head { margin: 0 0 28px; }\n.fmstr-cmp-ffh-a11y__eyebrow {\ndisplay: inline-block; padding: 5px 12px; border-radius: 9999px;\nbackground: var(--fmstr-cmp-ffh-a11y-tint); color: var(--fmstr-cmp-ffh-a11y-violet-600);\nfont-size: 12px; font-weight: 600; letter-spacing: .04em;\ntext-transform: uppercase; border: 1px solid var(--fmstr-cmp-ffh-a11y-edge); margin: 0 0 14px;\n}\n.fmstr-cmp-ffh-a11y__h2 { font-size: clamp(26px, 3vw, 36px); font-weight: 700; line-height: 1.15; letter-spacing: -.02em; margin: 0; }\n.fmstr-cmp-ffh-a11y__intro { color: var(--fmstr-cmp-ffh-a11y-fg-3); font-size: 17px; line-height: 1.6; margin: 14px 0 0; }\n\n.fmstr-cmp-ffh-a11y__list { display: flex; flex-direction: column; gap: 16px; }\n.fmstr-cmp-ffh-a11y__item {\nbackground: var(--fmstr-cmp-ffh-a11y-bg-card);\nborder: 1px solid var(--fmstr-cmp-ffh-a11y-border);\nborder-radius: 16px; padding: 22px 24px;\ndisplay: grid; grid-template-columns: 44px 1fr 1fr; gap: 20px; align-items: start;\nbox-shadow: var(--fmstr-cmp-ffh-a11y-shadow);\n}\n.fmstr-cmp-ffh-a11y__num {\nwidth: 36px; height: 36px; border-radius: 10px;\nbackground: var(--fmstr-cmp-ffh-a11y-tint);\ncolor: var(--fmstr-cmp-ffh-a11y-violet-600);\ndisplay: grid; place-items: center;\nfont-weight: 700; font-size: 15px;\nborder: 1px solid var(--fmstr-cmp-ffh-a11y-edge);\n}\n\n.fmstr-cmp-ffh-a11y__copy h3 {\nfont-size: 17px; font-weight: 600; letter-spacing: -.01em;\ncolor: var(--fmstr-cmp-ffh-a11y-fg-1); margin: 0 0 6px;\n}\n.fmstr-cmp-ffh-a11y__copy p { color: var(--fmstr-cmp-ffh-a11y-fg-2); font-size: 14.5px; line-height: 1.6; margin: 0; }\n.fmstr-cmp-ffh-a11y__copy strong { color: var(--fmstr-cmp-ffh-a11y-fg-1); font-weight: 600; }\n\n.fmstr-cmp-ffh-a11y__pair { display: flex; flex-direction: column; gap: 10px; }\n.fmstr-cmp-ffh-a11y__codebox {\nbackground: var(--fmstr-cmp-ffh-a11y-bg-code);\nborder-radius: 8px; padding: 10px 12px;\nfont-family: ui-monospace, Menlo, Monaco, monospace;\nfont-size: 11.5px; line-height: 1.55;\ncolor: #e2e8f0; overflow-x: auto; margin: 0;\nwhite-space: pre; position: relative; padding-left: 50px;\n}\n.fmstr-cmp-ffh-a11y__codebox code { font-family: inherit; }\n.fmstr-cmp-ffh-a11y__codebox::before {\ncontent: \"\"; position: absolute; left: 10px; top: 11px;\nwidth: 14px; height: 14px; border-radius: 50%;\nbackground-repeat: no-repeat; background-position: center;\n}\n.fmstr-cmp-ffh-a11y__codebox--bad::before { background-color: var(--fmstr-cmp-ffh-a11y-red-bg); background-image: url(\"data:image\u002Fsvg+xml,%3Csvg xmlns='http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg' width='8' height='8' viewBox='0 0 8 8' fill='none' stroke='%23b91c1c' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='M1.5 1.5 L6.5 6.5 M6.5 1.5 L1.5 6.5'\u002F%3E%3C\u002Fsvg%3E\"); }\n.fmstr-cmp-ffh-a11y__codebox--good::before { background-color: var(--fmstr-cmp-ffh-a11y-green-bg); background-image: url(\"data:image\u002Fsvg+xml,%3Csvg xmlns='http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg' width='9' height='9' viewBox='0 0 9 9' fill='none' stroke='%2315803d' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1.5 4.5 L3.5 6.5 L7 3'\u002F%3E%3C\u002Fsvg%3E\"); }\n.fmstr-cmp-ffh-a11y__codebox-label {\nposition: absolute; top: 11px; left: 28px;\nfont-size: 9px; font-weight: 700; letter-spacing: .08em;\ntext-transform: uppercase;\n}\n.fmstr-cmp-ffh-a11y__codebox--bad .fmstr-cmp-ffh-a11y__codebox-label { color: var(--fmstr-cmp-ffh-a11y-red); }\n.fmstr-cmp-ffh-a11y__codebox--good .fmstr-cmp-ffh-a11y__codebox-label { color: var(--fmstr-cmp-ffh-a11y-green); }\n\n.fmstr-cmp-ffh-a11y__codebox .t { color: #f472b6; }\n.fmstr-cmp-ffh-a11y__codebox .a { color: #a5b4fc; }\n.fmstr-cmp-ffh-a11y__codebox .s { color: #86efac; }\n\n.fmstr-cmp-ffh-a11y__foot {\nmargin: 28px auto 0; max-width: 760px; text-align: center;\ncolor: var(--fmstr-cmp-ffh-a11y-fg-3); font-size: 14.5px; line-height: 1.6;\n}\n.fmstr-cmp-ffh-a11y__foot a { color: var(--fmstr-cmp-ffh-a11y-violet-600) !important; font-weight: 600; }\n.fmstr-cmp-ffh-a11y__foot a:hover { text-decoration: underline !important; }\n\n@media (max-width: 880px) {\n.fmstr-cmp-ffh-a11y__item { grid-template-columns: 36px 1fr; gap: 16px; }\n.fmstr-cmp-ffh-a11y__pair { grid-column: 1 \u002F -1; }\n}\n@media (max-width: 760px) {\n.fmstr-cmp-ffh-a11y { padding: 40px 16px; }\n.fmstr-cmp-ffh-a11y__item { padding: 18px; border-radius: 14px; }\n.fmstr-cmp-ffh-a11y__intro { font-size: 15.5px; }\n.fmstr-cmp-ffh-a11y__codebox { font-size: 11px; }\n}\n\u003C\u002Fstyle>\n\n\u003Csection class=\"fmstr-cmp-ffh-a11y\" aria-labelledby=\"fmstr-cmp-ffh-a11y-h2\">\n\u003Cdiv class=\"fmstr-cmp-ffh-a11y__container\">\n\u003Cdiv class=\"fmstr-cmp-ffh-a11y__head\">\n\u003Cspan class=\"fmstr-cmp-ffh-a11y__eyebrow\">Five flags worth catching\u003C\u002Fspan>\n\u003Ch2 class=\"fmstr-cmp-ffh-a11y__h2\" id=\"fmstr-cmp-ffh-a11y-h2\">Accessibility checklist for an HTML feedback form\u003C\u002Fh2>\n\u003Cp class=\"fmstr-cmp-ffh-a11y__intro\">Every item below is something keyboard and screen-reader users actually hit. Skip these and a measurable chunk of your audience can&rsquo;t complete the form.\u003C\u002Fp>\n\u003C\u002Fdiv>\n\n\u003Cdiv class=\"fmstr-cmp-ffh-a11y__list\">\n\n\u003Carticle class=\"fmstr-cmp-ffh-a11y__item\">\n\u003Cdiv class=\"fmstr-cmp-ffh-a11y__num\">1\u003C\u002Fdiv>\n\u003Cdiv class=\"fmstr-cmp-ffh-a11y__copy\">\n\u003Ch3>Pair every label with its input\u003C\u002Fh3>\n\u003Cp>The label&rsquo;s \u003Ccode>for\u003C\u002Fcode> must match the input&rsquo;s \u003Ccode>id\u003C\u002Fcode>. Click the label, focus the input. Screen readers announce the label out loud. Skip this and the form fails WCAG 2.1 and loses keyboard users.\u003C\u002Fp>\n\u003C\u002Fdiv>\n\u003Cdiv class=\"fmstr-cmp-ffh-a11y__pair\">\n\u003Cpre class=\"fmstr-cmp-ffh-a11y__codebox fmstr-cmp-ffh-a11y__codebox--bad\">\u003Cspan class=\"fmstr-cmp-ffh-a11y__codebox-label\">No\u003C\u002Fspan>\u003Ccode>\u003Cspan class=\"t\">&lt;label&gt;\u003C\u002Fspan>Email\u003Cspan class=\"t\">&lt;\u002Flabel&gt;\u003C\u002Fspan>\n\u003Cspan class=\"t\">&lt;input\u003C\u002Fspan> \u003Cspan class=\"a\">type\u003C\u002Fspan>=\u003Cspan class=\"s\">\"email\"\u003C\u002Fspan>\u003Cspan class=\"t\">&gt;\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cpre class=\"fmstr-cmp-ffh-a11y__codebox fmstr-cmp-ffh-a11y__codebox--good\">\u003Cspan class=\"fmstr-cmp-ffh-a11y__codebox-label\">Yes\u003C\u002Fspan>\u003Ccode>\u003Cspan class=\"t\">&lt;label\u003C\u002Fspan> \u003Cspan class=\"a\">for\u003C\u002Fspan>=\u003Cspan class=\"s\">\"email\"\u003C\u002Fspan>\u003Cspan class=\"t\">&gt;\u003C\u002Fspan>Email\u003Cspan class=\"t\">&lt;\u002Flabel&gt;\u003C\u002Fspan>\n\u003Cspan class=\"t\">&lt;input\u003C\u002Fspan> \u003Cspan class=\"a\">id\u003C\u002Fspan>=\u003Cspan class=\"s\">\"email\"\u003C\u002Fspan> \u003Cspan class=\"a\">type\u003C\u002Fspan>=\u003Cspan class=\"s\">\"email\"\u003C\u002Fspan>\u003Cspan class=\"t\">&gt;\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\n\u003C\u002Fdiv>\n\u003C\u002Farticle>\n\n\u003Carticle class=\"fmstr-cmp-ffh-a11y__item\">\n\u003Cdiv class=\"fmstr-cmp-ffh-a11y__num\">2\u003C\u002Fdiv>\n\u003Cdiv class=\"fmstr-cmp-ffh-a11y__copy\">\n\u003Ch3>Connect errors with \u003Ccode>aria-describedby\u003C\u002Fcode>\u003C\u002Fh3>\n\u003Cp>An invalid field needs \u003Ccode>aria-invalid=\"true\"\u003C\u002Fcode> plus an \u003Ccode>aria-describedby\u003C\u002Fcode> that points at the visible error message. Screen readers then announce the error along with the field name on focus.\u003C\u002Fp>\n\u003C\u002Fdiv>\n\u003Cdiv class=\"fmstr-cmp-ffh-a11y__pair\">\n\u003Cpre class=\"fmstr-cmp-ffh-a11y__codebox fmstr-cmp-ffh-a11y__codebox--bad\">\u003Cspan class=\"fmstr-cmp-ffh-a11y__codebox-label\">No\u003C\u002Fspan>\u003Ccode>\u003Cspan class=\"t\">&lt;input\u003C\u002Fspan> \u003Cspan class=\"a\">id\u003C\u002Fspan>=\u003Cspan class=\"s\">\"email\"\u003C\u002Fspan>\u003Cspan class=\"t\">&gt;\u003C\u002Fspan>\n\u003Cspan class=\"t\">&lt;span&gt;\u003C\u002Fspan>Invalid email\u003Cspan class=\"t\">&lt;\u002Fspan&gt;\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cpre class=\"fmstr-cmp-ffh-a11y__codebox fmstr-cmp-ffh-a11y__codebox--good\">\u003Cspan class=\"fmstr-cmp-ffh-a11y__codebox-label\">Yes\u003C\u002Fspan>\u003Ccode>\u003Cspan class=\"t\">&lt;input\u003C\u002Fspan> \u003Cspan class=\"a\">id\u003C\u002Fspan>=\u003Cspan class=\"s\">\"email\"\u003C\u002Fspan>\n\u003Cspan class=\"a\">aria-invalid\u003C\u002Fspan>=\u003Cspan class=\"s\">\"true\"\u003C\u002Fspan>\n\u003Cspan class=\"a\">aria-describedby\u003C\u002Fspan>=\u003Cspan class=\"s\">\"email-error\"\u003C\u002Fspan>\u003Cspan class=\"t\">&gt;\u003C\u002Fspan>\n\u003Cspan class=\"t\">&lt;span\u003C\u002Fspan> \u003Cspan class=\"a\">id\u003C\u002Fspan>=\u003Cspan class=\"s\">\"email-error\"\u003C\u002Fspan>\u003Cspan class=\"t\">&gt;\u003C\u002Fspan>Invalid email\u003Cspan class=\"t\">&lt;\u002Fspan&gt;\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\n\u003C\u002Fdiv>\n\u003C\u002Farticle>\n\n\u003Carticle class=\"fmstr-cmp-ffh-a11y__item\">\n\u003Cdiv class=\"fmstr-cmp-ffh-a11y__num\">3\u003C\u002Fdiv>\n\u003Cdiv class=\"fmstr-cmp-ffh-a11y__copy\">\n\u003Ch3>Use \u003Ccode>autocomplete\u003C\u002Fcode> tokens\u003C\u002Fh3>\n\u003Cp>One line per field. Browsers prefill from saved info, password managers behave, and assistive tech recognizes the field&rsquo;s purpose. Measurable lift in completion rate on mobile.\u003C\u002Fp>\n\u003C\u002Fdiv>\n\u003Cdiv class=\"fmstr-cmp-ffh-a11y__pair\">\n\u003Cpre class=\"fmstr-cmp-ffh-a11y__codebox fmstr-cmp-ffh-a11y__codebox--bad\">\u003Cspan class=\"fmstr-cmp-ffh-a11y__codebox-label\">No\u003C\u002Fspan>\u003Ccode>\u003Cspan class=\"t\">&lt;input\u003C\u002Fspan> \u003Cspan class=\"a\">type\u003C\u002Fspan>=\u003Cspan class=\"s\">\"text\"\u003C\u002Fspan> \u003Cspan class=\"a\">name\u003C\u002Fspan>=\u003Cspan class=\"s\">\"name\"\u003C\u002Fspan>\u003Cspan class=\"t\">&gt;\u003C\u002Fspan>\n\u003Cspan class=\"t\">&lt;input\u003C\u002Fspan> \u003Cspan class=\"a\">type\u003C\u002Fspan>=\u003Cspan class=\"s\">\"email\"\u003C\u002Fspan> \u003Cspan class=\"a\">name\u003C\u002Fspan>=\u003Cspan class=\"s\">\"email\"\u003C\u002Fspan>\u003Cspan class=\"t\">&gt;\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cpre class=\"fmstr-cmp-ffh-a11y__codebox fmstr-cmp-ffh-a11y__codebox--good\">\u003Cspan class=\"fmstr-cmp-ffh-a11y__codebox-label\">Yes\u003C\u002Fspan>\u003Ccode>\u003Cspan class=\"t\">&lt;input\u003C\u002Fspan> \u003Cspan class=\"a\">type\u003C\u002Fspan>=\u003Cspan class=\"s\">\"text\"\u003C\u002Fspan> \u003Cspan class=\"a\">name\u003C\u002Fspan>=\u003Cspan class=\"s\">\"name\"\u003C\u002Fspan>\n\u003Cspan class=\"a\">autocomplete\u003C\u002Fspan>=\u003Cspan class=\"s\">\"name\"\u003C\u002Fspan>\u003Cspan class=\"t\">&gt;\u003C\u002Fspan>\n\u003Cspan class=\"t\">&lt;input\u003C\u002Fspan> \u003Cspan class=\"a\">type\u003C\u002Fspan>=\u003Cspan class=\"s\">\"email\"\u003C\u002Fspan> \u003Cspan class=\"a\">name\u003C\u002Fspan>=\u003Cspan class=\"s\">\"email\"\u003C\u002Fspan>\n\u003Cspan class=\"a\">autocomplete\u003C\u002Fspan>=\u003Cspan class=\"s\">\"email\"\u003C\u002Fspan>\u003Cspan class=\"t\">&gt;\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\n\u003C\u002Fdiv>\n\u003C\u002Farticle>\n\n\u003Carticle class=\"fmstr-cmp-ffh-a11y__item\">\n\u003Cdiv class=\"fmstr-cmp-ffh-a11y__num\">4\u003C\u002Fdiv>\n\u003Cdiv class=\"fmstr-cmp-ffh-a11y__copy\">\n\u003Ch3>Keep focus outlines visible\u003C\u002Fh3>\n\u003Cp>\u003Ccode>outline: none\u003C\u002Fcode> is the single most-copied CSS mistake on the web. It breaks keyboard navigation. Replace the default outline, never delete it. The visible ring is how a sighted keyboard user knows where they are.\u003C\u002Fp>\n\u003C\u002Fdiv>\n\u003Cdiv class=\"fmstr-cmp-ffh-a11y__pair\">\n\u003Cpre class=\"fmstr-cmp-ffh-a11y__codebox fmstr-cmp-ffh-a11y__codebox--bad\">\u003Cspan class=\"fmstr-cmp-ffh-a11y__codebox-label\">No\u003C\u002Fspan>\u003Ccode>input:focus { outline: none; }\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cpre class=\"fmstr-cmp-ffh-a11y__codebox fmstr-cmp-ffh-a11y__codebox--good\">\u003Cspan class=\"fmstr-cmp-ffh-a11y__codebox-label\">Yes\u003C\u002Fspan>\u003Ccode>input:focus {\noutline: 2px solid #5b6cff;\noutline-offset: 1px;\n}\u003C\u002Fcode>\u003C\u002Fpre>\n\u003C\u002Fdiv>\n\u003C\u002Farticle>\n\n\u003Carticle class=\"fmstr-cmp-ffh-a11y__item\">\n\u003Cdiv class=\"fmstr-cmp-ffh-a11y__num\">5\u003C\u002Fdiv>\n\u003Cdiv class=\"fmstr-cmp-ffh-a11y__copy\">\n\u003Ch3>Mark required fields semantically\u003C\u002Fh3>\n\u003Cp>The native \u003Ccode>required\u003C\u002Fcode> attribute does two jobs at once: it tells the browser to block submission and tells screen readers the field is required. Don&rsquo;t fake it with just a red asterisk in the label.\u003C\u002Fp>\n\u003C\u002Fdiv>\n\u003Cdiv class=\"fmstr-cmp-ffh-a11y__pair\">\n\u003Cpre class=\"fmstr-cmp-ffh-a11y__codebox fmstr-cmp-ffh-a11y__codebox--bad\">\u003Cspan class=\"fmstr-cmp-ffh-a11y__codebox-label\">No\u003C\u002Fspan>\u003Ccode>\u003Cspan class=\"t\">&lt;label&gt;\u003C\u002Fspan>Email \u003Cspan class=\"t\">&lt;span&gt;\u003C\u002Fspan>*\u003Cspan class=\"t\">&lt;\u002Fspan&gt;&lt;\u002Flabel&gt;\u003C\u002Fspan>\n\u003Cspan class=\"t\">&lt;input\u003C\u002Fspan> \u003Cspan class=\"a\">type\u003C\u002Fspan>=\u003Cspan class=\"s\">\"email\"\u003C\u002Fspan>\u003Cspan class=\"t\">&gt;\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cpre class=\"fmstr-cmp-ffh-a11y__codebox fmstr-cmp-ffh-a11y__codebox--good\">\u003Cspan class=\"fmstr-cmp-ffh-a11y__codebox-label\">Yes\u003C\u002Fspan>\u003Ccode>\u003Cspan class=\"t\">&lt;label\u003C\u002Fspan> \u003Cspan class=\"a\">for\u003C\u002Fspan>=\u003Cspan class=\"s\">\"email\"\u003C\u002Fspan>\u003Cspan class=\"t\">&gt;\u003C\u002Fspan>Email (required)\u003Cspan class=\"t\">&lt;\u002Flabel&gt;\u003C\u002Fspan>\n\u003Cspan class=\"t\">&lt;input\u003C\u002Fspan> \u003Cspan class=\"a\">id\u003C\u002Fspan>=\u003Cspan class=\"s\">\"email\"\u003C\u002Fspan> \u003Cspan class=\"a\">type\u003C\u002Fspan>=\u003Cspan class=\"s\">\"email\"\u003C\u002Fspan> \u003Cspan class=\"a\">required\u003C\u002Fspan>\u003Cspan class=\"t\">&gt;\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\n\u003C\u002Fdiv>\n\u003C\u002Farticle>\n\n\u003C\u002Fdiv>\n\n\u003Cp class=\"fmstr-cmp-ffh-a11y__foot\">For edge cases (fieldsets, error summaries, custom controls), the \u003Ca href=\"https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FHTML\u002FReference\u002FElements\u002Fform\">MDN \u003Ccode>&lt;form&gt;\u003C\u002Fcode> reference\u003C\u002Fa> is the canonical source.\u003C\u002Fp>\n\u003C\u002Fdiv>\n\u003C\u002Fsection>\n\n\u003Cstyle>\n\u002F* host-link-override *\u002F\n.fmstr-cmp-ffh-faq a { text-decoration: none !important; }\n.fmstr-cmp-ffh-faq {\n--c-bg: #fafafb; --c-card: #ffffff;\n--c-fg-1: #101828; --c-fg-2: #475467;\n--c-violet-600: #6941c6; --c-tint: #f7f3ff; --c-edge: #e4d7ff;\n--c-border: #eaecf0; --c-chip-bg: #f4f4f7;\n--c-shadow: 0 1px 3px rgba(16,24,40,.05);\n\nbackground: transparent; padding: 56px 24px;\nfont-family: inherit;\ncolor: var(--c-fg-1);\n}\n.fmstr-cmp-ffh-faq *, .fmstr-cmp-ffh-faq *::before, .fmstr-cmp-ffh-faq *::after { box-sizing: border-box; }\n.fmstr-cmp-ffh-faq__container { max-width: 820px; margin: 0 auto; }\n.fmstr-cmp-ffh-faq__h2 { font-size: clamp(26px, 3vw, 36px); font-weight: 700; line-height: 1.15; letter-spacing: -.02em; margin: 0; color: var(--c-fg-1); }\n.fmstr-cmp-ffh-faq__intro { color: #697586; font-size: 17px; line-height: 1.6; margin: 14px 0 28px; max-width: 760px; }\n.fmstr-cmp-ffh-faq__list { display: flex; flex-direction: column; gap: 12px; }\n.fmstr-cmp-ffh-faq__item {\nbackground: var(--c-card); border: 1px solid var(--c-border);\nborder-radius: 14px; box-shadow: var(--c-shadow); overflow: hidden;\n}\n.fmstr-cmp-ffh-faq__item > summary {\npadding: 18px 22px; cursor: pointer; font-weight: 600; font-size: 16.5px;\ncolor: var(--c-fg-1); display: flex; align-items: center; gap: 14px;\nlist-style: none;\n}\n.fmstr-cmp-ffh-faq__item > summary::-webkit-details-marker { display: none; }\n.fmstr-cmp-ffh-faq__item > summary::before {\ncontent: \"\"; width: 28px; height: 28px; border-radius: 8px; flex-shrink: 0;\nbackground-color: var(--c-chip-bg);\nbackground-image: url(\"data:image\u002Fsvg+xml,%3Csvg xmlns='http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg' width='14' height='14' viewBox='0 0 14 14' fill='none' stroke='%2375747f' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 5l4 4 4-4'\u002F%3E%3C\u002Fsvg%3E\");\nbackground-repeat: no-repeat; background-position: center;\ntransition: transform .15s ease, background-color .15s ease;\n}\n.fmstr-cmp-ffh-faq__item[open] > summary::before { transform: rotate(180deg); background-color: var(--c-tint); }\n.fmstr-cmp-ffh-faq__item[open] > summary { color: var(--c-violet-600); }\n.fmstr-cmp-ffh-faq__answer { padding: 0 22px 22px 64px; color: var(--c-fg-2); font-size: 15.5px; line-height: 1.7; }\n.fmstr-cmp-ffh-faq__answer a { color: var(--c-violet-600) !important; text-decoration: none !important; }\n.fmstr-cmp-ffh-faq__answer a:hover { text-decoration: underline !important; }\n.fmstr-cmp-ffh-faq__answer code {\nbackground: var(--c-chip-bg); padding: 1px 6px; border-radius: 4px;\nfont-family: ui-monospace, Menlo, Monaco, monospace; font-size: 13.5px;\ncolor: var(--c-violet-600);\n}\n\n@media (max-width: 760px) {\n.fmstr-cmp-ffh-faq { padding: 40px 16px; }\n.fmstr-cmp-ffh-faq__intro { font-size: 15.5px; }\n.fmstr-cmp-ffh-faq__item > summary { padding: 16px 16px; font-size: 15.5px; gap: 12px; }\n.fmstr-cmp-ffh-faq__item > summary::before { width: 26px; height: 26px; }\n.fmstr-cmp-ffh-faq__answer { padding: 0 16px 18px 16px; font-size: 15px; line-height: 1.65; }\n}\n\u003C\u002Fstyle>\n\n\u003Csection class=\"fmstr-cmp-ffh-faq\" aria-labelledby=\"fmstr-cmp-ffh-faq-h2\">\n\u003Cdiv class=\"fmstr-cmp-ffh-faq__container\">\n\u003Ch2 class=\"fmstr-cmp-ffh-faq__h2\" id=\"fmstr-cmp-ffh-faq-h2\">HTML feedback form FAQ\u003C\u002Fh2>\n\u003Cp class=\"fmstr-cmp-ffh-faq__intro\">Answers that mirror the FAQPage JSON-LD on the live page.\u003C\u002Fp>\n\u003Cdiv class=\"fmstr-cmp-ffh-faq__list\">\n\n\u003Cdetails class=\"fmstr-cmp-ffh-faq__item\">\n\u003Csummary>How do you add a feedback form in HTML?\u003C\u002Fsummary>\n\u003Cdiv class=\"fmstr-cmp-ffh-faq__answer\">Use a \u003Ccode>&lt;form&gt;\u003C\u002Fcode> element with \u003Ccode>action\u003C\u002Fcode> set to your submission endpoint and \u003Ccode>method=\"post\"\u003C\u002Fcode>. Inside the form, add labeled \u003Ccode>&lt;input&gt;\u003C\u002Fcode> and \u003Ccode>&lt;textarea&gt;\u003C\u002Fcode> elements with \u003Ccode>name\u003C\u002Fcode> attributes. Style with CSS, validate with JavaScript, and point the \u003Ccode>action\u003C\u002Fcode> at a backend (your server, or a service like \u003Ca href=\"https:\u002F\u002Fformester.com\u002Ffeatures\u002Fhtml-form-backend\u002F\">Formester&rsquo;s HTML form backend\u003C\u002Fa>). The complete copy-paste example above is the shortest working version.\u003C\u002Fdiv>\n\u003C\u002Fdetails>\n\n\u003Cdetails class=\"fmstr-cmp-ffh-faq__item\">\n\u003Csummary>How do I create a feedback form?\u003C\u002Fsummary>\n\u003Cdiv class=\"fmstr-cmp-ffh-faq__answer\">Decide what to ask (name, email, rating, open-ended feedback are the standard four). Write the HTML using a \u003Ccode>&lt;form&gt;\u003C\u002Fcode> with one labeled input per question. Style it with CSS so it matches your site. Hook the \u003Ccode>action\u003C\u002Fcode> to a backend that stores submissions. The full process is the six steps above, or skip ahead to \u003Ca href=\"https:\u002F\u002Fformester.com\u002Ffeatures\u002Fdrag-and-drop-form-builder\u002F\">Formester&rsquo;s drag-and-drop builder\u003C\u002Fa> if you&rsquo;d rather not write code.\u003C\u002Fdiv>\n\u003C\u002Fdetails>\n\n\u003Cdetails class=\"fmstr-cmp-ffh-faq__item\">\n\u003Csummary>How do I create an inquiry form in HTML?\u003C\u002Fsummary>\n\u003Cdiv class=\"fmstr-cmp-ffh-faq__answer\">Same pattern as a feedback form, with different field labels. Swap \"How was your experience?\" for \"What are you interested in?\" and \"Your feedback\" for \"Your message.\" Keep the name, email, and submit-button structure identical. For a longer inquiry form with subject lines and contact preferences, the \u003Ca href=\"https:\u002F\u002Fformester.com\u002Fblog\u002Fcontact-form-design-tips-best-practices-and-examples\u002F\">contact form design best practices guide\u003C\u002Fa> covers the patterns.\u003C\u002Fdiv>\n\u003C\u002Fdetails>\n\n\u003Cdetails class=\"fmstr-cmp-ffh-faq__item\">\n\u003Csummary>How do you add a comment to a form in HTML?\u003C\u002Fsummary>\n\u003Cdiv class=\"fmstr-cmp-ffh-faq__answer\">Two meanings. (1) An HTML comment for developers: \u003Ccode>&lt;!-- this is the feedback section --&gt;\u003C\u002Fcode> between elements. (2) A user-facing comment field: a \u003Ccode>&lt;textarea&gt;\u003C\u002Fcode> with a label like \"Your comments.\" If you want comments to be optional, leave off the \u003Ccode>required\u003C\u002Fcode> attribute. Use \u003Ccode>rows\u003C\u002Fcode> and \u003Ccode>cols\u003C\u002Fcode> (or CSS height) to size the box.\u003C\u002Fdiv>\n\u003C\u002Fdetails>\n\n\u003Cdetails class=\"fmstr-cmp-ffh-faq__item\">\n\u003Csummary>How do I add CSS to a feedback form?\u003C\u002Fsummary>\n\u003Cdiv class=\"fmstr-cmp-ffh-faq__answer\">Two options. Inline \u003Ccode>&lt;style&gt;\u003C\u002Fcode> tags inside \u003Ccode>&lt;head&gt;\u003C\u002Fcode> work fine for one-off pages. For any real site, link an external stylesheet with \u003Ccode>&lt;link rel=\"stylesheet\" href=\"styles.css\"&gt;\u003C\u002Fcode>. Style the \u003Ccode>form\u003C\u002Fcode>, \u003Ccode>label\u003C\u002Fcode>, \u003Ccode>input\u003C\u002Fcode>, \u003Ccode>textarea\u003C\u002Fcode>, and \u003Ccode>button\u003C\u002Fcode> selectors directly. Step 3 above ships a complete starter stylesheet you can paste, including focus rings and inline error styles.\u003C\u002Fdiv>\n\u003C\u002Fdetails>\n\n\u003Cdetails class=\"fmstr-cmp-ffh-faq__item\">\n\u003Csummary>How do I add JavaScript validation without breaking accessibility?\u003C\u002Fsummary>\n\u003Cdiv class=\"fmstr-cmp-ffh-faq__answer\">Use \u003Ccode>aria-invalid=\"true\"\u003C\u002Fcode> on invalid fields, \u003Ccode>aria-describedby\u003C\u002Fcode> to point at the inline error message, and move focus to the first invalid field on submit failure. Avoid \u003Ccode>alert()\u003C\u002Fcode> boxes, they break screen-reader flow. The Step 4 JavaScript and the complete example above are accessibility-tested versions you can paste directly. Always re-validate on the server too, since a user with DevTools open can bypass client-side checks.\u003C\u002Fdiv>\n\u003C\u002Fdetails>\n\n\u003C\u002Fdiv>\n\u003C\u002Fdiv>\n\u003C\u002Fsection>\n\n\u003Cstyle>\n\u002F* host-link-override *\u002F\n.fmstr-cmp-ffh-vid a { text-decoration: none !important; }\n.fmstr-cmp-ffh-vid {\n--c-bg-card: #ffffff;\n--c-fg-1: #101828; --c-fg-2: #475467; --c-fg-3: #697586;\n--c-violet-500: #7f56d9; --c-violet-600: #6941c6;\n--c-tint: #f7f3ff; --c-edge: #e4d7ff; --c-border: #eaecf0;\n--c-shadow: 0 4px 20px rgba(16,24,40,.06), 0 2px 6px rgba(16,24,40,.04);\n\nbackground: transparent; padding: 56px 24px;\nfont-family: inherit;\ncolor: var(--c-fg-1);\n}\n.fmstr-cmp-ffh-vid *, .fmstr-cmp-ffh-vid *::before, .fmstr-cmp-ffh-vid *::after { box-sizing: border-box; }\n.fmstr-cmp-ffh-vid__container { max-width: 820px; margin: 0 auto; }\n.fmstr-cmp-ffh-vid__head { margin: 0 0 24px; }\n.fmstr-cmp-ffh-vid__eyebrow {\ndisplay: inline-block; padding: 5px 12px; border-radius: 9999px;\nbackground: var(--c-tint); color: var(--c-violet-600);\nfont-size: 12px; font-weight: 600; letter-spacing: .04em;\ntext-transform: uppercase; border: 1px solid var(--c-edge); margin: 0 0 14px;\n}\n.fmstr-cmp-ffh-vid__h2 { font-size: clamp(24px, 2.8vw, 32px); font-weight: 700; line-height: 1.15; letter-spacing: -.02em; margin: 0; color: var(--c-fg-1); }\n.fmstr-cmp-ffh-vid__sub { color: var(--c-fg-3); font-size: 16px; line-height: 1.6; margin: 12px 0 0; }\n.fmstr-cmp-ffh-vid__frame {\nposition: relative; aspect-ratio: 16 \u002F 9; border-radius: 20px; overflow: hidden;\nbackground: var(--c-tint); border: 1px solid var(--c-border); box-shadow: var(--c-shadow);\n}\n.fmstr-cmp-ffh-vid__frame iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }\n.fmstr-cmp-ffh-vid__caption { color: var(--c-fg-3); font-size: 14px; line-height: 1.6; text-align: center; margin: 16px 0 0; }\n.fmstr-cmp-ffh-vid__caption a { color: var(--c-violet-600) !important; text-decoration: none !important; }\n.fmstr-cmp-ffh-vid__caption a:hover { text-decoration: underline !important; }\n.fmstr-cmp-ffh-vid__caption code {\nbackground: var(--c-tint); padding: 1px 6px; border-radius: 4px;\nfont-family: ui-monospace, Menlo, Monaco, monospace; font-size: 13px;\ncolor: var(--c-violet-600);\n}\n\n@media (max-width: 760px) {\n.fmstr-cmp-ffh-vid { padding: 40px 16px; }\n.fmstr-cmp-ffh-vid__sub { font-size: 15px; }\n.fmstr-cmp-ffh-vid__frame { border-radius: 16px; }\n.fmstr-cmp-ffh-vid__caption { font-size: 13.5px; }\n}\n\u003C\u002Fstyle>\n\n\u003Csection class=\"fmstr-cmp-ffh-vid\" aria-labelledby=\"fmstr-cmp-ffh-vid-h2\">\n\u003Cdiv class=\"fmstr-cmp-ffh-vid__container\">\n\u003Cdiv class=\"fmstr-cmp-ffh-vid__head\">\n\u003Cspan class=\"fmstr-cmp-ffh-vid__eyebrow\">Three-minute walkthrough\u003C\u002Fspan>\n\u003Ch2 class=\"fmstr-cmp-ffh-vid__h2\" id=\"fmstr-cmp-ffh-vid-h2\">Watch the full HTML feedback form built from scratch\u003C\u002Fh2>\n\u003Cp class=\"fmstr-cmp-ffh-vid__sub\">Structure, CSS, accessible validation, backend swap. All six steps in one short video.\u003C\u002Fp>\n\u003C\u002Fdiv>\n\u003Cdiv class=\"fmstr-cmp-ffh-vid__frame\">\n\u003Ciframe src=\"https:\u002F\u002Fwww.youtube.com\u002Fembed\u002F8FC3c5Cv5ew\" title=\"How to make a feedback form in HTML\" loading=\"lazy\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen>\u003C\u002Fiframe>\n\u003C\u002Fdiv>\n\u003Cp class=\"fmstr-cmp-ffh-vid__caption\">Prefer reading? The full tutorial is below with copy-paste blocks. To skip the backend setup entirely, point the form&rsquo;s \u003Ccode>action\u003C\u002Fcode> at \u003Ca href=\"https:\u002F\u002Fformester.com\u002Ffeatures\u002Fhtml-form-backend\u002F\">Formester&rsquo;s HTML form backend\u003C\u002Fa>.\u003C\u002Fp>\n\u003C\u002Fdiv>\n\u003C\u002Fsection>\n\n\u003Cstyle>\n\u002F* host-link-override *\u002F\n.fmstr-cmp-ffh-rel a { text-decoration: none !important; }\n.fmstr-cmp-ffh-rel {\n--c-bg: #f4f4f7; --c-card: #ffffff;\n--c-fg-1: #101828; --c-fg-2: #475467; --c-fg-3: #697586;\n--c-violet-500: #7f56d9; --c-violet-600: #6941c6;\n--c-tint: #f7f3ff; --c-edge: #e4d7ff; --c-border: #eaecf0;\n--c-shadow: 0 4px 20px rgba(16,24,40,.06);\n\nbackground: transparent; padding: 56px 24px;\nfont-family: inherit;\ncolor: var(--c-fg-1);\n}\n.fmstr-cmp-ffh-rel *, .fmstr-cmp-ffh-rel *::before, .fmstr-cmp-ffh-rel *::after { box-sizing: border-box; }\n.fmstr-cmp-ffh-rel__container { max-width: 820px; margin: 0 auto; }\n.fmstr-cmp-ffh-rel__head { margin: 0 0 28px; }\n.fmstr-cmp-ffh-rel__h2 { font-size: clamp(26px, 3vw, 36px); font-weight: 700; line-height: 1.15; letter-spacing: -.02em; margin: 0; }\n.fmstr-cmp-ffh-rel__intro { color: var(--c-fg-3); font-size: 17px; line-height: 1.6; margin: 14px 0 0; }\n.fmstr-cmp-ffh-rel__grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }\n.fmstr-cmp-ffh-rel__card {\nbackground: var(--c-card); border: 1px solid var(--c-border);\nborder-radius: 14px; padding: 18px 20px; display: flex; align-items: center; gap: 14px;\ntext-decoration: none !important; color: inherit !important; transition: all .15s ease;\n}\n.fmstr-cmp-ffh-rel__card:hover { border-color: var(--c-edge); box-shadow: var(--c-shadow); transform: translateY(-1px); }\n.fmstr-cmp-ffh-rel__icon { width: 40px; height: 40px; border-radius: 10px; background: var(--c-tint); display: grid; place-items: center; flex-shrink: 0; font-size: 18px; border: 1px solid var(--c-edge); }\n.fmstr-cmp-ffh-rel__text { flex-grow: 1; }\n.fmstr-cmp-ffh-rel__text h4 { font-size: 14.5px; font-weight: 600; color: var(--c-fg-1); margin: 0; }\n.fmstr-cmp-ffh-rel__text small { font-size: 12.5px; color: var(--c-fg-3); display: block; margin-top: 2px; }\n.fmstr-cmp-ffh-rel__arrow { color: var(--c-violet-500); font-size: 18px; }\n\n@media (max-width: 880px) { .fmstr-cmp-ffh-rel__grid { grid-template-columns: 1fr 1fr; gap: 12px; } }\n@media (max-width: 760px) {\n.fmstr-cmp-ffh-rel { padding: 40px 16px; }\n.fmstr-cmp-ffh-rel__intro { font-size: 15.5px; }\n.fmstr-cmp-ffh-rel__card { padding: 16px; gap: 12px; }\n}\n@media (max-width: 540px) { .fmstr-cmp-ffh-rel__grid { grid-template-columns: 1fr; gap: 12px; } }\n\u003C\u002Fstyle>\n\n\u003Csection class=\"fmstr-cmp-ffh-rel\" aria-labelledby=\"fmstr-cmp-ffh-rel-h2\">\n\u003Cdiv class=\"fmstr-cmp-ffh-rel__container\">\n\u003Cdiv class=\"fmstr-cmp-ffh-rel__head\">\n\u003Ch2 class=\"fmstr-cmp-ffh-rel__h2\" id=\"fmstr-cmp-ffh-rel-h2\">More from Formester on HTML forms and feedback\u003C\u002Fh2>\n\u003Cp class=\"fmstr-cmp-ffh-rel__intro\">Pair this tutorial with the backend features, ready-made templates, and adjacent how-tos.\u003C\u002Fp>\n\u003C\u002Fdiv>\n\u003Cdiv class=\"fmstr-cmp-ffh-rel__grid\">\n\n\u003Ca class=\"fmstr-cmp-ffh-rel__card\" href=\"https:\u002F\u002Fformester.com\u002Ffeatures\u002Fhtml-form-backend\u002F\">\n\u003Cdiv class=\"fmstr-cmp-ffh-rel__icon\" aria-hidden=\"true\">&#128229;\u003C\u002Fdiv>\n\u003Cdiv class=\"fmstr-cmp-ffh-rel__text\">\u003Ch4>HTML Form Backend\u003C\u002Fh4>\u003Csmall>One \u003Ccode>action\u003C\u002Fcode> swap, no server\u003C\u002Fsmall>\u003C\u002Fdiv>\n\u003Cspan class=\"fmstr-cmp-ffh-rel__arrow\" aria-hidden=\"true\">&rarr;\u003C\u002Fspan>\n\u003C\u002Fa>\n\n\u003Ca class=\"fmstr-cmp-ffh-rel__card\" href=\"https:\u002F\u002Fformester.com\u002Ffeatures\u002Fembed-forms\u002F\">\n\u003Cdiv class=\"fmstr-cmp-ffh-rel__icon\" aria-hidden=\"true\">&#128279;\u003C\u002Fdiv>\n\u003Cdiv class=\"fmstr-cmp-ffh-rel__text\">\u003Ch4>Embed Forms\u003C\u002Fh4>\u003Csmall>Drop a form into any HTML page\u003C\u002Fsmall>\u003C\u002Fdiv>\n\u003Cspan class=\"fmstr-cmp-ffh-rel__arrow\" aria-hidden=\"true\">&rarr;\u003C\u002Fspan>\n\u003C\u002Fa>\n\n\u003Ca class=\"fmstr-cmp-ffh-rel__card\" href=\"https:\u002F\u002Fformester.com\u002Ffeatures\u002Fspam-protection\u002F\">\n\u003Cdiv class=\"fmstr-cmp-ffh-rel__icon\" aria-hidden=\"true\">&#128737;\u003C\u002Fdiv>\n\u003Cdiv class=\"fmstr-cmp-ffh-rel__text\">\u003Ch4>Spam Protection\u003C\u002Fh4>\u003Csmall>Honeypot + reCAPTCHA built in\u003C\u002Fsmall>\u003C\u002Fdiv>\n\u003Cspan class=\"fmstr-cmp-ffh-rel__arrow\" aria-hidden=\"true\">&rarr;\u003C\u002Fspan>\n\u003C\u002Fa>\n\n\u003Ca class=\"fmstr-cmp-ffh-rel__card\" href=\"https:\u002F\u002Fformester.com\u002Ftemplates\u002Fcustomer-feedback-form-31840\u002F\">\n\u003Cdiv class=\"fmstr-cmp-ffh-rel__icon\" aria-hidden=\"true\">&#11088;\u003C\u002Fdiv>\n\u003Cdiv class=\"fmstr-cmp-ffh-rel__text\">\u003Ch4>Customer Feedback Form\u003C\u002Fh4>\u003Csmall>Pre-built template\u003C\u002Fsmall>\u003C\u002Fdiv>\n\u003Cspan class=\"fmstr-cmp-ffh-rel__arrow\" aria-hidden=\"true\">&rarr;\u003C\u002Fspan>\n\u003C\u002Fa>\n\n\u003Ca class=\"fmstr-cmp-ffh-rel__card\" href=\"https:\u002F\u002Fformester.com\u002Ftemplates\u002Fcategories\u002Ffeedback-forms\u002F\">\n\u003Cdiv class=\"fmstr-cmp-ffh-rel__icon\" aria-hidden=\"true\">&#128196;\u003C\u002Fdiv>\n\u003Cdiv class=\"fmstr-cmp-ffh-rel__text\">\u003Ch4>All Feedback Templates\u003C\u002Fh4>\u003Csmall>Customer, product, employee\u003C\u002Fsmall>\u003C\u002Fdiv>\n\u003Cspan class=\"fmstr-cmp-ffh-rel__arrow\" aria-hidden=\"true\">&rarr;\u003C\u002Fspan>\n\u003C\u002Fa>\n\n\u003Ca class=\"fmstr-cmp-ffh-rel__card\" href=\"https:\u002F\u002Fformester.com\u002Fai-form-generator\u002F\">\n\u003Cdiv class=\"fmstr-cmp-ffh-rel__icon\" aria-hidden=\"true\">&#10024;\u003C\u002Fdiv>\n\u003Cdiv class=\"fmstr-cmp-ffh-rel__text\">\u003Ch4>AI Form Generator\u003C\u002Fh4>\u003Csmall>The no-code alternative\u003C\u002Fsmall>\u003C\u002Fdiv>\n\u003Cspan class=\"fmstr-cmp-ffh-rel__arrow\" aria-hidden=\"true\">&rarr;\u003C\u002Fspan>\n\u003C\u002Fa>\n\n\u003Ca class=\"fmstr-cmp-ffh-rel__card\" href=\"https:\u002F\u002Fformester.com\u002Fblog\u002Fhow-to-send-contact-form-data-to-google-sheets-free\u002F\">\n\u003Cdiv class=\"fmstr-cmp-ffh-rel__icon\" aria-hidden=\"true\">&#128203;\u003C\u002Fdiv>\n\u003Cdiv class=\"fmstr-cmp-ffh-rel__text\">\u003Ch4>Send form data to Google Sheets\u003C\u002Fh4>\u003Csmall>Free, step-by-step\u003C\u002Fsmall>\u003C\u002Fdiv>\n\u003Cspan class=\"fmstr-cmp-ffh-rel__arrow\" aria-hidden=\"true\">&rarr;\u003C\u002Fspan>\n\u003C\u002Fa>\n\n\u003Ca class=\"fmstr-cmp-ffh-rel__card\" href=\"https:\u002F\u002Fformester.com\u002Fblog\u002Fcontact-form-design-tips-best-practices-and-examples\u002F\">\n\u003Cdiv class=\"fmstr-cmp-ffh-rel__icon\" aria-hidden=\"true\">&#127912;\u003C\u002Fdiv>\n\u003Cdiv class=\"fmstr-cmp-ffh-rel__text\">\u003Ch4>Contact form design tips\u003C\u002Fh4>\u003Csmall>Best practices and examples\u003C\u002Fsmall>\u003C\u002Fdiv>\n\u003Cspan class=\"fmstr-cmp-ffh-rel__arrow\" aria-hidden=\"true\">&rarr;\u003C\u002Fspan>\n\u003C\u002Fa>\n\n\u003Ca class=\"fmstr-cmp-ffh-rel__card\" href=\"https:\u002F\u002Fformester.com\u002Fblog\u002Fhow-to-build-spam-free-contact-forms-for-your-website\u002F\">\n\u003Cdiv class=\"fmstr-cmp-ffh-rel__icon\" aria-hidden=\"true\">&#129302;\u003C\u002Fdiv>\n\u003Cdiv class=\"fmstr-cmp-ffh-rel__text\">\u003Ch4>Build spam-free contact forms\u003C\u002Fh4>\u003Csmall>Stop bots before they hit your inbox\u003C\u002Fsmall>\u003C\u002Fdiv>\n\u003Cspan class=\"fmstr-cmp-ffh-rel__arrow\" aria-hidden=\"true\">&rarr;\u003C\u002Fspan>\n\u003C\u002Fa>\n\n\u003C\u002Fdiv>\n\u003C\u002Fdiv>\n\u003C\u002Fsection>\n","blog\u002Fblog\u002Fhow-to-make-feedback-form-in-html.md",{"text":67},"16 min read",{"title":69,"author":70,"authorImage":8,"authorProfile":71,"coverImg":72,"coverImgAlt":73,"createdAt":74,"description":75,"featured":14,"jsonld":76,"keywords":164,"metaDescription":96,"metaImage":165,"metaTitle":90,"publishedAt":166,"slug":167,"updatedAt":168,"__hash__":169,"body":170,"id":171,"coverImgWidth":172,"coverImgHeight":173,"readingStats":174},"How to View and Release Scores in Google Forms","Harsh Shah","https:\u002F\u002Flinkedin.com\u002Fin\u002Fharshshahseo","https:\u002F\u002Fformester-strapi.s3.ap-south-1.amazonaws.com\u002Fhow_to_view_scores_in_google_forms_cover_7022953515.png","Blog cover showing a laptop with a Google Forms quiz score ring reading 18 out of 20 beside one correct and one incorrect graded question row","2026-08-24T10:18:23.391Z","Google Forms hides quiz scores in three separate tabs, and one setting decides whether respondents ever see their own. This guide covers answer keys and points, both release modes, what respondents can and cannot see, and where Google Forms scoring runs out.",[77],{"@graph":78,"@context":163},[79,87,98,111,119,153],{"@id":80,"url":81,"logo":82,"name":85,"@type":86},"https:\u002F\u002Fformester.com\u002F#organization","https:\u002F\u002Fformester.com\u002F",{"url":83,"@type":84},"https:\u002F\u002Fformester.com\u002Flogo.png","ImageObject","Formester","Organization",{"@id":88,"url":89,"name":90,"@type":91,"isPartOf":92,"breadcrumb":93,"inLanguage":95,"description":96,"dateModified":97,"datePublished":97},"https:\u002F\u002Fformester.com\u002Fblog\u002Fhow-to-view-scores-in-google-forms\u002F#webpage","https:\u002F\u002Fformester.com\u002Fblog\u002Fhow-to-view-scores-in-google-forms\u002F","How to View and Release Scores in Google Forms | Formester","WebPage",{"@id":80},{"@id":94},"https:\u002F\u002Fformester.com\u002Fblog\u002Fhow-to-view-scores-in-google-forms\u002F#breadcrumb","en-US","See quiz scores in Google Forms three ways, release grades instantly or after review, and fix the setting that hides scores from students.","2026-08-24",{"@id":94,"@type":99,"itemListElement":100},"BreadcrumbList",[101,105,109],{"item":81,"name":102,"@type":103,"position":104},"Home","ListItem",1,{"item":106,"name":107,"@type":103,"position":108},"https:\u002F\u002Fformester.com\u002Fblog\u002F","Blog",2,{"item":89,"name":69,"@type":103,"position":110},3,{"@id":112,"@type":113,"image":72,"author":114,"headline":69,"keywords":116,"publisher":117,"inLanguage":95,"description":75,"dateModified":97,"datePublished":97,"mainEntityOfPage":118},"https:\u002F\u002Fformester.com\u002Fblog\u002Fhow-to-view-scores-in-google-forms\u002F#article","BlogPosting",{"url":71,"name":70,"@type":115},"Person","view score in google form, google form view score, view score google form, google form answer key, google forms answer key, how to release scores in google form, how to release scores on google forms, google form release grades",{"@id":80},{"@id":88},{"@id":120,"@type":121,"mainEntity":122},"https:\u002F\u002Fformester.com\u002Fblog\u002Fhow-to-view-scores-in-google-forms\u002F#faq","FAQPage",[123,129,133,137,141,145,149],{"name":124,"@type":125,"acceptedAnswer":126},"Can I see the results of a Google Form?","Question",{"text":127,"@type":128},"Yes, if you own the form or have editing access. Open the form and click Responses. Summary gives you group totals, Question walks you through one question across everyone, and Individual shows one person's full submission with their score.","Answer",{"name":130,"@type":125,"acceptedAnswer":131},"Why can't I see results on Google Forms?",{"text":132,"@type":128},"If you're the respondent, the quiz is probably set to release grades after manual review and the owner hasn't released yours yet. You'll see only \"Your response has been recorded\" until they do. If you're the owner and Responses shows submissions but no scores, check that quiz mode is actually on. A plain form never calculates a score. Also look for questions sitting as \"ungraded\". That happens on short answers that didn't exactly match your answer key.",{"name":134,"@type":125,"acceptedAnswer":135},"How do I remove the view score from the Google Form?",{"text":136,"@type":128},"Open Settings and set Release grades to \"Later, after manual review\", then don't release the scores. New respondents stop seeing a score straight away. To keep the total but hide the answers, leave the release mode alone and switch off the respondent toggles for missed questions and correct answers. Scores you already emailed can't be pulled back.",{"name":138,"@type":125,"acceptedAnswer":139},"What is view result summary in Google Forms?",{"text":140,"@type":128},"It's the Summary tab under Responses. For a quiz it shows the average, median and range of scores, plus a chart of how many people scored what. It's the fastest read on how a group performed.",{"name":142,"@type":125,"acceptedAnswer":143},"How do I view my score in a Google Form as a student?",{"text":144,"@type":128},"That depends on how your teacher set the quiz up. If grades release immediately, your score appears right after you submit, usually behind a \"View score\" link. If the quiz is set to manual review, you get an email once your teacher releases it. There's no page you can log into to check later, so keep that email.",{"name":146,"@type":125,"acceptedAnswer":147},"Can I see the results of a Google Form that isn't mine?",{"text":148,"@type":128},"No. Responses are only visible to the form owner and anyone they add as an editor. If you need the results, ask the owner to share editing access or send you a summary. No add-on or workaround gets around this.",{"name":150,"@type":125,"acceptedAnswer":151},"Can I view Google Forms scores on my phone?",{"text":152,"@type":128},"Yes. Open the form in a mobile browser and the Responses tab works the same way, including all three views. There's no dedicated Google Forms app for iPhone or Android. Grading long written answers on a phone is slow going. The Question view is the least painful of the three.",{"@id":154,"url":81,"name":85,"@type":155,"offers":156,"operatingSystem":161,"applicationCategory":162},"https:\u002F\u002Fformester.com\u002F#software","SoftwareApplication",{"@type":157,"price":158,"description":159,"priceCurrency":160},"Offer","0","Free forever plan, no credit card required","USD","Web, iOS, Android","BusinessApplication","https:\u002F\u002Fschema.org","view score in google form,google form view score,view score google form,google form answer key,google forms answer key,how to release scores in google form,how to release scores on google forms,google form release grades",[],"2026-08-26T05:25:48.941Z","how-to-view-scores-in-google-forms","2026-08-26T05:25:48.945Z","IfhdA-9WSj-jtk3ls1PZa4qRdCcF2pNUvW80RdO8_rw","![Blog cover showing a laptop with a Google Forms quiz score ring reading 18 out of 20 beside one correct and one incorrect graded question row](https:\u002F\u002Fformester-strapi.s3.ap-south-1.amazonaws.com\u002Fhow_to_view_scores_in_google_forms_cover_7022953515.png)\n\n\u003Cp style=\"font-size: inherit;\">You built the quiz. The responses are in. Now you want the scores, and Google Forms has hidden them in three different places.\u003C\u002Fp>\n\n\u003Cp>There's also one setting that decides whether your respondents ever see their own score. Pick the wrong option when you build the form and every score goes out the second someone hits submit, before you've checked a single answer.\u003C\u002Fp>\n\n\u003Cblockquote>\u003Cp>Scores live under \u003Cstrong>Responses\u003C\u002Fstrong>, in three tabs. Summary gives you the class picture. Question marks one question across everyone. Individual shows a single person's paper. Whether they see their score is a separate setting, \u003Cstrong>Release grades\u003C\u002Fstrong>, in Settings.\u003C\u002Fp>\u003C\u002Fblockquote>\n\n\u003Ch2>First, the form has to be a quiz\u003C\u002Fh2>\n\n\u003Cp>Google Forms won't calculate a score unless quiz mode is on. A plain form collects answers and stops there. That's why people open Responses looking for scores and find nothing but a list of submissions.\u003C\u002Fp>\n\n\u003Col>\n\u003Cli>Open the form and click \u003Cstrong>Settings\u003C\u002Fstrong>.\u003C\u002Fli>\n\u003Cli>Turn on \u003Cstrong>Make this a quiz\u003C\u002Fstrong>.\u003C\u002Fli>\n\u003C\u002Fol>\n\n\u003Cp>\u003Cimg src=\"https:\u002F\u002Fformester-strapi.s3.ap-south-1.amazonaws.com\u002Fgforms_s1_make_this_a_quiz_27ecc2c2c2.jpg\" alt=\"Google Forms Settings with Make this a quiz switched on, revealing the Release grades and Respondent settings options\" loading=\"lazy\" style=\"width:100%;max-width:900px;height:auto;border-radius:8px;border:1px solid #e5e7eb;margin:16px 0;\" \u002F>\u003C\u002Fp>\n\n\u003Cp>One choice here matters more than it looks. If you decide to hold scores back for review, Google switches on \u003Cstrong>Collect email addresses\u003C\u002Fstrong> for you and sets it to \u003Cstrong>Verified\u003C\u002Fstrong>.\u003C\u002Fp>\n\n\u003Cp>Verified means everyone has to sign in to a Google account. That's fine in a school on Workspace. It quietly locks out anyone who doesn't have a Google login.\u003C\u002Fp>\n\n\u003Cp>If your respondents are the public, switch it:\u003C\u002Fp>\n\n\u003Col>\n\u003Cli>Open \u003Cstrong>Settings\u003C\u002Fstrong> and expand \u003Cstrong>Responses\u003C\u002Fstrong>.\u003C\u002Fli>\n\u003Cli>Set \u003Cstrong>Collect email addresses\u003C\u002Fstrong> to \u003Cstrong>Responder input\u003C\u002Fstrong>.\u003C\u002Fli>\n\u003C\u002Fol>\n\n\u003Cp>They type an address instead of signing in, and manual release still works.\u003C\u002Fp>\n\n\u003Cp>\u003Cimg src=\"https:\u002F\u002Fformester-strapi.s3.ap-south-1.amazonaws.com\u002Fgforms_s4b_collect_email_verified_7fdff40d20.jpg\" alt=\"Collect email addresses set to Verified, labelled Required to release grades manually and Respondents will be required to sign in to Google\" loading=\"lazy\" style=\"width:100%;max-width:900px;height:auto;border-radius:8px;border:1px solid #e5e7eb;margin:16px 0;\" \u002F>\u003C\u002Fp>\n\n\u003Cp>Building the quiz itself is a separate job. If you're starting from an empty form, our walkthrough on \u003Ca href=\"https:\u002F\u002Fformester.com\u002Fblog\u002Fhow-to-create-a-quiz-in-google-forms-the-only-guide-youll-need-in-2023\u002F\">how to create a quiz in Google Forms\u003C\u002Fa> covers question setup.\u003C\u002Fp>\n\n\u003Ch2>Set the answer key and the points\u003C\u002Fh2>\n\n\u003Cp>A score is just the sum of the points you attached to correct answers. Nothing shows up until you tell Google which answers are right.\u003C\u002Fp>\n\n\u003Col>\n\u003Cli>Click a question, then click \u003Cstrong>Answer key\u003C\u002Fstrong> at the bottom left.\u003C\u002Fli>\n\u003Cli>Pick the correct answer.\u003C\u002Fli>\n\u003Cli>Set the point value in the top right.\u003C\u002Fli>\n\u003C\u002Fol>\n\n\u003Cp>Add answer feedback attaches an explanation or a YouTube video that appears once grading is done. Worth the extra minute on questions people reliably get wrong.\u003C\u002Fp>\n\n\u003Cp>\u003Cimg src=\"https:\u002F\u002Fformester-strapi.s3.ap-south-1.amazonaws.com\u002Fgforms_s2_answer_key_points_427e99112a.jpg\" alt=\"Answer key panel on a multiple choice question with Mitochondrion marked correct and the question set to 2 points\" loading=\"lazy\" style=\"width:100%;max-width:900px;height:auto;border-radius:8px;border:1px solid #e5e7eb;margin:16px 0;\" \u002F>\u003C\u002Fp>\n\n\u003Cp>Two things will catch you out. New questions default to 0 points, so anything you skipped contributes nothing to the total.\u003C\u002Fp>\n\n\u003Cp>And the points box only takes whole numbers. Type 0.5 and it'll sit there looking accepted. Reload the form and it's back to 0, with no warning. There are no half marks, so scale up instead: make the question worth 2 and award 1 for a partial answer.\u003C\u002Fp>\n\n\u003Cp>Answer keys don't work on every question type. Six of them grade themselves:\u003C\u002Fp>\n\n\u003Cdiv class=\"table-wrap\">\n\u003Ctable>\n\u003Cthead>\n\u003Ctr>\u003Cth>Question type\u003C\u002Fth>\u003Cth>Answer key\u003C\u002Fth>\u003Cth>Grades automatically\u003C\u002Fth>\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\n\u003Ctr>\u003Ctd>Short answer\u003C\u002Ftd>\u003Ctd>Yes\u003C\u002Ftd>\u003Ctd>Yes, on exact text match including capitalisation\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>Multiple choice\u003C\u002Ftd>\u003Ctd>Yes\u003C\u002Ftd>\u003Ctd>Yes\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>Checkboxes\u003C\u002Ftd>\u003Ctd>Yes\u003C\u002Ftd>\u003Ctd>Yes, every correct box required\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>Dropdown\u003C\u002Ftd>\u003Ctd>Yes\u003C\u002Ftd>\u003Ctd>Yes\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>Multiple choice grid\u003C\u002Ftd>\u003Ctd>Yes\u003C\u002Ftd>\u003Ctd>Yes\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>Checkbox grid\u003C\u002Ftd>\u003Ctd>Yes\u003C\u002Ftd>\u003Ctd>Yes\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>Paragraph, file upload, date, time, linear scale, rating\u003C\u002Ftd>\u003Ctd>No\u003C\u002Ftd>\u003Ctd>No, you assign points by hand\u003C\u002Ftd>\u003C\u002Ftr>\n\u003C\u002Ftbody>\n\u003C\u002Ftable>\n\u003C\u002Fdiv>\n\n\u003Cp>You can still put points on any question type, a paragraph answer included. What you lose is the automatic part. Someone has to read it and award the marks.\u003C\u002Fp>\n\n\u003Cp>On a paragraph question the panel even renames itself to \"Edit feedback and points\", because there's no correct answer to set.\u003C\u002Fp>\n\n\u003Cp>Short answer grading has a trap worth knowing before you send a quiz to thirty people. The match is exact, capitalisation and all. A near miss isn't marked wrong. It's left ungraded.\u003C\u002Fp>\n\n\u003Cp>Answer \"photosynthesis\" against a key of \"Photosynthesis\" and you get an empty points box and a quiet \"1 ungraded response\" label. That person's total under-reports until somebody grades it by hand.\u003C\u002Fp>\n\n\u003Cp>\u003Cimg src=\"https:\u002F\u002Fformester-strapi.s3.ap-south-1.amazonaws.com\u002Fgforms_s8_ungraded_case_mismatch_b8838b5419.jpg\" alt=\"Question view showing Photosynthesis graded 2 out of 2 while the lowercase photosynthesis sits as one ungraded response with an empty points box\" loading=\"lazy\" style=\"width:100%;max-width:900px;height:auto;border-radius:8px;border:1px solid #e5e7eb;margin:16px 0;\" \u002F>\u003C\u002Fp>\n\n\u003Cp>Two ways out. List every spelling and capitalisation you'll accept as separate correct answers, or tick \u003Cstrong>Mark all other answers incorrect\u003C\u002Fstrong> so a miss scores a real zero instead of sitting in limbo.\u003C\u002Fp>\n\n\u003Ch2>Where scores appear once responses come in\u003C\u002Fh2>\n\n\u003Cp>Click \u003Cstrong>Responses\u003C\u002Fstrong> at the top of the quiz. The three tabs answer different questions, and picking the wrong one is why grading takes longer than it should.\u003C\u002Fp>\n\n\u003Cdiv class=\"table-wrap\">\n\u003Ctable>\n\u003Cthead>\n\u003Ctr>\u003Cth>View\u003C\u002Fth>\u003Cth>What it shows\u003C\u002Fth>\u003Cth>Use it when\u003C\u002Fth>\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\n\u003Ctr>\u003Ctd>\u003Cstrong>Summary\u003C\u002Fstrong>\u003C\u002Ftd>\u003Ctd>An Insights panel with the average, median and range of scores, plus a histogram of who scored what\u003C\u002Ftd>\u003Ctd>You want to know how the group did at a glance\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>\u003Cstrong>Question\u003C\u002Fstrong>\u003C\u002Ftd>\u003Ctd>One question across every respondent, with buttons to mark it right, wrong or worth part marks\u003C\u002Ftd>\u003Ctd>You're grading written answers and want to stay in one question's headspace\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>\u003Cstrong>Individual\u003C\u002Fstrong>\u003C\u002Ftd>\u003Ctd>One person's whole submission, with their total and the points per question\u003C\u002Ftd>\u003Ctd>Someone queries a mark, or you're releasing scores one at a time\u003C\u002Ftd>\u003C\u002Ftr>\n\u003C\u002Ftbody>\n\u003C\u002Ftable>\n\u003C\u002Fdiv>\n\n\u003Cp>\u003Cimg src=\"https:\u002F\u002Fformester-strapi.s3.ap-south-1.amazonaws.com\u002Fgforms_s3_summary_insights_222cd8f89b.jpg\" alt=\"Responses Summary Insights panel showing average 2.67 of 8, median 2 of 8, range 2 to 4 points and a total points distribution chart\" loading=\"lazy\" style=\"width:100%;max-width:900px;height:auto;border-radius:8px;border:1px solid #e5e7eb;margin:16px 0;\" \u002F>\u003C\u002Fp>\n\n\u003Cp>Summary is the one to open first. It reads out the average, median and range against the total, and the distribution chart shows the shape of the class in a glance.\u003C\u002Fp>\n\n\u003Cp>Google also surfaces frequently missed questions here, once a quiz has enough responses for the pattern to mean anything. For the full tour of these tabs beyond scoring, see \u003Ca href=\"https:\u002F\u002Fformester.com\u002Fblog\u002F5-ways-to-view-responses-in-google-forms\u002F\">the five ways to view Google Forms responses\u003C\u002Fa>.\u003C\u002Fp>\n\n\u003Ch2>Release scores automatically after each submission\u003C\u002Fh2>\n\n\u003Cp>This is the default, and it catches people out. Unless you changed it, every respondent saw their score the moment they submitted.\u003C\u002Fp>\n\n\u003Cp>To check which mode you're on:\u003C\u002Fp>\n\n\u003Col>\n\u003Cli>Open \u003Cstrong>Settings\u003C\u002Fstrong>.\u003C\u002Fli>\n\u003Cli>Under \u003Cstrong>Release grades\u003C\u002Fstrong>, pick \u003Cstrong>Immediately after each submission\u003C\u002Fstrong>.\u003C\u002Fli>\n\u003C\u002Fol>\n\n\u003Cp>\u003Cimg src=\"https:\u002F\u002Fformester-strapi.s3.ap-south-1.amazonaws.com\u002Fgforms_s4_release_grades_manual_52e4dcee67.jpg\" alt=\"Release grades set to Later, after manual review, with the note that it turns on Collect email addresses\" loading=\"lazy\" style=\"width:100%;max-width:900px;height:auto;border-radius:8px;border:1px solid #e5e7eb;margin:16px 0;\" \u002F>\u003C\u002Fp>\n\n\u003Cp>Instant release suits practice quizzes and revision, or anything where the score is feedback rather than a grade. It only works cleanly when every question has an answer key.\u003C\u002Fp>\n\n\u003Cp>A paragraph question in an instant-release quiz shows up ungraded, which reads to the respondent as a zero they didn't earn.\u003C\u002Fp>\n\n\u003Ch2>Release scores later, after you review\u003C\u002Fh2>\n\n\u003Cp>Pick \u003Cstrong>Later, after manual review\u003C\u002Fstrong> in the same setting and Google holds every score until you send it. Respondents see a confirmation that their response was recorded and nothing about how they did.\u003C\u002Fp>\n\n\u003Cp>There are two ways to hand the scores back. For one person at a time:\u003C\u002Fp>\n\n\u003Col>\n\u003Cli>Open \u003Cstrong>Responses\u003C\u002Fstrong> and click \u003Cstrong>Individual\u003C\u002Fstrong>.\u003C\u002Fli>\n\u003Cli>Click \u003Cstrong>Release score\u003C\u002Fstrong> at the top right.\u003C\u002Fli>\n\u003Cli>Tick the people you want, then confirm with \u003Cstrong>Send emails and release\u003C\u002Fstrong>.\u003C\u002Fli>\n\u003C\u002Fol>\n\n\u003Cp>\u003Cimg src=\"https:\u002F\u002Fformester-strapi.s3.ap-south-1.amazonaws.com\u002Fgforms_s5_individual_release_score_f0eada3b11.jpg\" alt=\"Individual response view showing 4 of 8 points, a padlock reading Score not released, and the Release score button\" loading=\"lazy\" style=\"width:100%;max-width:900px;height:auto;border-radius:8px;border:1px solid #e5e7eb;margin:16px 0;\" \u002F>\u003C\u002Fp>\n\n\u003Cp>To release in bulk, stay on \u003Cstrong>Summary\u003C\u002Fstrong>. The Scores panel lists every respondent with a \"Score released\" column and a single \u003Cstrong>Release scores\u003C\u002Fstrong> button covers the lot.\u003C\u002Fp>\n\n\u003Cp>That button only appears on responses that have an email address attached. If a response came in before email collection was switched on, Google Forms gives you no way to hand that person a score. You can't fix it retroactively.\u003C\u002Fp>\n\n\u003Cdiv class=\"table-wrap\">\n\u003Ctable>\n\u003Cthead>\n\u003Ctr>\u003Cth>Situation\u003C\u002Fth>\u003Cth>Release mode\u003C\u002Fth>\u003Cth>Why\u003C\u002Fth>\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\n\u003Ctr>\u003Ctd>Practice quiz, everything auto-graded\u003C\u002Ftd>\u003Ctd>Immediately after each submission\u003C\u002Ftd>\u003Ctd>Instant feedback is the point and there's nothing to review\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>Graded test with written answers\u003C\u002Ftd>\u003Ctd>Later, after manual review\u003C\u002Ftd>\u003Ctd>Paragraph answers need a human before a total means anything\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>Everyone must submit before anyone sees marks\u003C\u002Ftd>\u003Ctd>Later, after manual review\u003C\u002Ftd>\u003Ctd>Stops early finishers passing answers to the rest of the group\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>Anonymous quiz with no email collection\u003C\u002Ftd>\u003Ctd>Immediately after each submission\u003C\u002Ftd>\u003Ctd>Manual release needs an email address, so it's your only option\u003C\u002Ftd>\u003C\u002Ftr>\n\u003C\u002Ftbody>\n\u003C\u002Ftable>\n\u003C\u002Fdiv>\n\n\u003Cdiv class=\"fmstr-blog-cta\">\n\u003Cp>\u003Cstrong>Want pass marks and negative marking without stitching on an add-on?\u003C\u002Fstrong> Formester weights points per question, judges every submission against a pass mark you set, and can print the score on the thank you page.\u003C\u002Fp>\n\u003Cp>\u003Ca class=\"fmstr-blog-cta__btn\" href=\"https:\u002F\u002Fapp.formester.com\u002Fusers\u002Fsign_up\">Build a scored quiz free\u003C\u002Fa>\u003C\u002Fp>\n\u003Cp class=\"fmstr-blog-cta__meta\">Free forever plan · No credit card · Setup in 2 minutes\u003C\u002Fp>\n\u003C\u002Fdiv>\n\n\u003Ch2>What respondents see, and what they cannot\u003C\u002Fh2>\n\n\u003Cp>What lands on a respondent's screen is controlled separately from the release mode. In \u003Cstrong>Settings\u003C\u002Fstrong>, under \u003Cstrong>Respondent settings\u003C\u002Fstrong>, three toggles decide what they get:\u003C\u002Fp>\n\n\u003Cul>\n\u003Cli>\u003Cstrong>Missed questions.\u003C\u002Fstrong> Whether they can see which ones they got wrong.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Correct answers.\u003C\u002Fstrong> Whether the right answers are revealed after grades go out.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Point values.\u003C\u002Fstrong> Whether they see the total and the points per question.\u003C\u002Fli>\n\u003C\u002Ful>\n\n\u003Cp>They're independent, so you can show someone their total while hiding the correct answers. That's the setup you want if the same quiz goes to a second group later.\u003C\u002Fp>\n\n\u003Cp>Two limits are worth stating plainly, because they're what respondents actually ask about.\u003C\u002Fp>\n\n\u003Cp>Until you release, they see nothing at all. The confirmation page says only \"Your response has been recorded\", with no score and no hint that one exists. That single line is the honest answer to most \"why can't I see my score\" searches.\u003C\u002Fp>\n\n\u003Cp>\u003Cimg src=\"https:\u002F\u002Fformester-strapi.s3.ap-south-1.amazonaws.com\u002Fgforms_s7_response_recorded_no_score_e29ed37043.jpg\" alt=\"Google Forms confirmation page reading Your response has been recorded, with no score shown to the respondent\" loading=\"lazy\" style=\"width:100%;max-width:900px;height:auto;border-radius:8px;border:1px solid #e5e7eb;margin:16px 0;\" \u002F>\u003C\u002Fp>\n\n\u003Cp>Respondents also can't browse back to an old score. Google Forms emails it or shows it once at submission. There's no student dashboard to log into, so tell people to keep the email.\u003C\u002Fp>\n\n\u003Cp>And you can't see results for a form that isn't yours. Response data belongs to the owner. Unless they gave you editing access or published a summary link, the answer is no. No add-on gets around it.\u003C\u002Fp>\n\n\u003Ch2>How to stop showing scores\u003C\u002Fh2>\n\n\u003Cp>To take the score away after the fact:\u003C\u002Fp>\n\n\u003Col>\n\u003Cli>Open \u003Cstrong>Settings\u003C\u002Fstrong> and set \u003Cstrong>Release grades\u003C\u002Fstrong> to \u003Cstrong>Later, after manual review\u003C\u002Fstrong>.\u003C\u002Fli>\n\u003Cli>Don't release the scores.\u003C\u002Fli>\n\u003C\u002Fol>\n\n\u003Cp>New submissions stop showing a score straight away.\u003C\u002Fp>\n\n\u003Cp>To keep the total but hide the working, leave the release mode alone and switch off the respondent toggles for missed questions and correct answers. People still get a number, and your question bank stays unpublished.\u003C\u002Fp>\n\n\u003Cp>\u003Cimg src=\"https:\u002F\u002Fformester-strapi.s3.ap-south-1.amazonaws.com\u002Fgforms_s9_respondent_toggles_off_6a38d03e40.jpg\" alt=\"Google Forms Respondent settings with Missed questions and Correct answers switched off while Point values stays on\" loading=\"lazy\" style=\"width:100%;max-width:900px;height:auto;border-radius:8px;border:1px solid #e5e7eb;margin:16px 0;\" \u002F>\u003C\u002Fp>\n\n\u003Cp>One thing this won't do: scores you already emailed can't be recalled. Changing the setting affects what happens next, not what already went out.\u003C\u002Fp>\n\n\u003Ch2>Where Google Forms scoring runs out\u003C\u002Fh2>\n\n\u003Cp>For a quick knowledge check, quiz mode is genuinely enough. The gaps show up when the quiz carries weight, like a certification, a hiring screen or an exam with a pass mark.\u003C\u002Fp>\n\n\u003Cdiv class=\"table-wrap\">\n\u003Ctable>\n\u003Cthead>\n\u003Ctr>\u003Cth>What you need\u003C\u002Fth>\u003Cth>Google Forms\u003C\u002Fth>\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\n\u003Ctr>\u003Ctd>Pass or fail threshold\u003C\u002Ftd>\u003Ctd>Not available, you compare totals yourself\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>Negative marking for wrong answers\u003C\u002Ftd>\u003Ctd>Not available\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>Partial credit on a multi-select\u003C\u002Ftd>\u003Ctd>Manual, per response\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>Half marks or decimal points\u003C\u002Ftd>\u003Ctd>Not available, the field takes 0.5 then saves 0\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>Accepting spelling variants on a short answer\u003C\u002Ftd>\u003Ctd>Only if you list each one, otherwise it sits ungraded\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>Quiz timer\u003C\u002Ftd>\u003Ctd>No built-in timer, add-ons only\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>Different questions per respondent\u003C\u002Ftd>\u003Ctd>Shuffle reorders the same questions, there's no question bank\u003C\u002Ftd>\u003C\u002Ftr>\n\u003C\u002Ftbody>\n\u003C\u002Ftable>\n\u003C\u002Fdiv>\n\n\u003Cp>The timer gap is the one people hit first, and it's solvable inside Google Forms if that's where you want to stay. We wrote up \u003Ca href=\"https:\u002F\u002Fformester.com\u002Fblog\u002Fhow-to-add-a-timer-to-your-google-quiz-includes-latest-alternative-works-without-add-ons-2023\u002F\">how to add a timer to a Google Forms quiz\u003C\u002Fa> separately.\u003C\u002Fp>\n\n\u003Ch2>Scoring the same quiz in Formester\u003C\u002Fh2>\n\n\u003Cp>If your quiz needs a pass mark or negative marking, the scoring model has to be built in rather than bolted on. Formester handles the parts Google Forms leaves to you.\u003C\u002Fp>\n\n\u003Cp>Scoring isn't a toggle you flip on an existing form, which is the bit that trips people up. You choose it when you create the form, so start there.\u003C\u002Fp>\n\n\u003Ch3>Step 1. Pick the scored-quiz type\u003C\u002Fh3>\n\n\u003Cp>From the dashboard, click \u003Cstrong>Create New Form\u003C\u002Fstrong>, then \u003Cstrong>Start with AI\u003C\u002Fstrong>. Three options appear. Take \u003Cstrong>Create Score Quiz with AI\u003C\u002Fstrong>, not the outcome-quiz one, which routes people to a result instead of scoring them.\u003C\u002Fp>\n\n\u003Cp>\u003Cimg src=\"https:\u002F\u002Fformester-strapi.s3.ap-south-1.amazonaws.com\u002Fformester_score_quiz_entry_b49ed51577.jpg\" alt=\"Formester's Start with AI screen offering Create Form with AI, Create Outcome Quiz with AI and Create Score Quiz with AI\" loading=\"lazy\" style=\"width:100%;max-width:900px;height:auto;border-radius:8px;border:1px solid #e5e7eb;margin:16px 0;\" \u002F>\u003C\u002Fp>\n\n\u003Ch3>Step 2. Describe the quiz you want\u003C\u002Fh3>\n\n\u003Cp>Type what you need in plain English and say how it should be scored. Ours was \"a 5 question cell biology quiz for high school students, multiple choice, scored out of 10, with a pass mark\". You can attach a PDF instead and let it pull questions from your material.\u003C\u002Fp>\n\n\u003Cp>\u003Cimg src=\"https:\u002F\u002Fformester-strapi.s3.ap-south-1.amazonaws.com\u002Fformester_score_quiz_prompt_bdbb1f2e1b.jpg\" alt=\"Formester's Create Score Quiz with AI screen with a Describe Your Form box and ready-made prompt suggestions\" loading=\"lazy\" style=\"width:100%;max-width:900px;height:auto;border-radius:8px;border:1px solid #e5e7eb;margin:16px 0;\" \u002F>\u003C\u002Fp>\n\n\u003Ch3>Step 3. Check what it built\u003C\u002Fh3>\n\n\u003Cp>It comes back as a working quiz with the points already assigned. Ours landed as five questions worth 10 points, with the total printed under the title, so a respondent knows what they're playing for before they start.\u003C\u002Fp>\n\n\u003Cp>\u003Cimg src=\"https:\u002F\u002Fformester-strapi.s3.ap-south-1.amazonaws.com\u002Fformester_scored_quiz_builder_7b07c13e2d.jpg\" alt=\"Formester builder showing a generated scored quiz titled Cell Biology Mastery Quiz, headed 5 Questions and 10 Points Total\" loading=\"lazy\" style=\"width:100%;max-width:900px;height:auto;border-radius:8px;border:1px solid #e5e7eb;margin:16px 0;\" \u002F>\u003C\u002Fp>\n\n\u003Ch3>Step 4. Adjust the scoring, then share it\u003C\u002Fh3>\n\n\u003Cp>From here you can reword a question, swap which answer is correct, or change what each one is worth. Then publish and send the link. The pieces that matter for a graded test:\u003C\u002Fp>\n\n\u003Cp>For section-based tests with negative scores and a timer running together, the \u003Ca href=\"https:\u002F\u002Fformester.com\u002Fblog\u002Fhow-to-create-online-section-based-tests-and-quizzes-with-negative-scores-and-timer\u002F\">section-based test walkthrough\u003C\u002Fa> covers the setup.\u003C\u002Fp>\n\n\u003Cp>You can also start from the \u003Ca href=\"https:\u002F\u002Fformester.com\u002Fai-quiz-maker\u002F\">AI quiz maker\u003C\u002Fa> and let it draft the questions, or read the \u003Ca href=\"https:\u002F\u002Fformester.com\u002Ffeatures\u002Fquiz-maker-features\u002F\">quiz maker feature list\u003C\u002Fa> before you commit.\u003C\u002Fp>\n\n\u003Cp>None of that makes Google Forms the wrong tool. It's free and everyone already has it. For a ten question check-in that's plenty. Switch when the score starts having consequences.\u003C\u002Fp>\n\n\u003Csection class=\"faq\">\n\u003Cdetails>\u003Csummary>Can I see the results of a Google Form?\u003C\u002Fsummary>\u003Cp>Yes, if you own the form or have editing access. Open the form and click Responses. Summary gives you group totals, Question walks you through one question across everyone, and Individual shows one person's full submission with their score.\u003C\u002Fp>\u003C\u002Fdetails>\n\u003Cdetails>\u003Csummary>Why can't I see results on Google Forms?\u003C\u002Fsummary>\u003Cp>If you're the respondent, the quiz is probably set to release grades after manual review and the owner hasn't released yours yet. You'll see only \"Your response has been recorded\" until they do.\u003C\u002Fp>\u003Cp>If you're the owner and Responses shows submissions but no scores, check that quiz mode is actually on. A plain form never calculates a score.\u003C\u002Fp>\u003Cp>Also look for questions sitting as \"ungraded\". That happens on short answers that didn't exactly match your answer key.\u003C\u002Fp>\u003C\u002Fdetails>\n\u003Cdetails>\u003Csummary>How do I remove the view score from the Google Form?\u003C\u002Fsummary>\u003Cp>Open Settings and set Release grades to \"Later, after manual review\", then don't release the scores. New respondents stop seeing a score straight away.\u003C\u002Fp>\u003Cp>To keep the total but hide the answers, leave the release mode alone and switch off the respondent toggles for missed questions and correct answers. Scores you already emailed can't be pulled back.\u003C\u002Fp>\u003C\u002Fdetails>\n\u003Cdetails>\u003Csummary>What is view result summary in Google Forms?\u003C\u002Fsummary>\u003Cp>It's the Summary tab under Responses. For a quiz it shows the average, median and range of scores, plus a chart of how many people scored what. It's the fastest read on how a group performed.\u003C\u002Fp>\u003C\u002Fdetails>\n\u003Cdetails>\u003Csummary>How do I view my score in a Google Form as a student?\u003C\u002Fsummary>\u003Cp>That depends on how your teacher set the quiz up. If grades release immediately, your score appears right after you submit, usually behind a \"View score\" link.\u003C\u002Fp>\u003Cp>If the quiz is set to manual review, you get an email once your teacher releases it. There's no page you can log into to check later, so keep that email.\u003C\u002Fp>\u003C\u002Fdetails>\n\u003Cdetails>\u003Csummary>Can I see the results of a Google Form that isn't mine?\u003C\u002Fsummary>\u003Cp>No. Responses are only visible to the form owner and anyone they add as an editor. If you need the results, ask the owner to share editing access or send you a summary. No add-on or workaround gets around this.\u003C\u002Fp>\u003C\u002Fdetails>\n\u003Cdetails>\u003Csummary>Can I view Google Forms scores on my phone?\u003C\u002Fsummary>\u003Cp>Yes. Open the form in a mobile browser and the Responses tab works the same way, including all three views. There's no dedicated Google Forms app for iPhone or Android.\u003C\u002Fp>\u003Cp>Grading long written answers on a phone is slow going. The Question view is the least painful of the three.\u003C\u002Fp>\u003C\u002Fdetails>\n\u003C\u002Fsection>\n\n\u003Ch2>Related reading\u003C\u002Fh2>\n\n\u003Cp>More on scoring, grading and moving quizzes off Google Forms.\u003C\u002Fp>\n\n\u003Cul>\n\u003Cli>\u003Ca href=\"https:\u002F\u002Fformester.com\u002Fblog\u002Fhow-to-create-a-scored-quiz\u002F\">\u003Cstrong>How to create a scored quiz\u003C\u002Fstrong>\u003C\u002Fa> - build the scoring model from scratch, including point weighting and result logic.\u003C\u002Fli>\n\u003Cli>\u003Ca href=\"https:\u002F\u002Fformester.com\u002Ftest-creator\u002F\">\u003Cstrong>Online test creator\u003C\u002Fstrong>\u003C\u002Fa> - set up a timed test with a pass mark and per-question scoring.\u003C\u002Fli>\n\u003Cli>\u003Ca href=\"https:\u002F\u002Fformester.com\u002Fblog\u002Fhow-to-turn-google-forms-into-student-assessment-dashboard\u002F\">\u003Cstrong>Turn Google Forms into a student assessment dashboard\u003C\u002Fstrong>\u003C\u002Fa> - push quiz scores into Sheets and chart performance over a term.\u003C\u002Fli>\n\u003Cli>\u003Ca href=\"https:\u002F\u002Fformester.com\u002Fblog\u002Fbest-online-quiz-maker-for-teachers\u002F\">\u003Cstrong>Best online quiz makers for teachers\u003C\u002Fstrong>\u003C\u002Fa> - how the main options compare on grading, timers and question types.\u003C\u002Fli>\n\u003Cli>\u003Ca href=\"https:\u002F\u002Fformester.com\u002Fblog\u002Ftop-google-forms-alternatives\u002F\">\u003Cstrong>Top Google Forms alternatives\u003C\u002Fstrong>\u003C\u002Fa> - where each one is genuinely stronger, and where Google Forms still wins.\u003C\u002Fli>\n\u003Cli>\u003Ca href=\"https:\u002F\u002Fformester.com\u002Fuse-case\u002Fformester-for-training-and-assessments\u002F\">\u003Cstrong>Formester for training and assessments\u003C\u002Fstrong>\u003C\u002Fa> - scoring, certificates and reporting for course and compliance testing.\u003C\u002Fli>\n\u003C\u002Ful>\n\n","blog\u002Fblog\u002Fhow-to-view-scores-in-google-forms.md",2400,1350,{"text":175},"13 min read",{"title":177,"author":178,"authorImage":8,"authorProfile":179,"coverImg":180,"coverImgAlt":181,"createdAt":182,"description":183,"featured":14,"jsonld":184,"keywords":211,"metaDescription":212,"metaImage":213,"metaTitle":177,"publishedAt":182,"slug":214,"updatedAt":215,"__hash__":216,"body":217,"id":218,"coverImgWidth":219,"coverImgHeight":26,"readingStats":220},"Google Form Auto Filler: Pre-fill Links vs Extensions","Ankit Singhaniya","https:\u002F\u002Flinkedin.com\u002Fin\u002Fankitsinghaniyaz","https:\u002F\u002Fformester-strapi.s3.ap-south-1.amazonaws.com\u002F1761380fe68fe6cd_google-form-auto-filler-cover.png","Cover art for a guide to auto-filling Google Forms with pre-fill links and extensions","2026-09-01T00:00:00.000Z","A Google Form auto filler is either a link that opens the form with answers already in it, or a browser tool that types your saved details into a form someone sent you. This guide walks through Google's built-in pre-fill link and the entry IDs behind it. It then covers the Chrome extensions for filling forms you were sent and answers the bot question. The last section shows where pre-fill stops.",[185],{"@context":163,"@type":121,"mainEntity":186},[187,191,195,199,203,207],{"@type":125,"name":188,"acceptedAnswer":189},"How do I automatically fill in a Google Form?",{"@type":128,"text":190},"Open the form in the editor, click the three-dot menu in the top right, choose Pre-fill form, enter the answers you want, and click Get link. Anyone who opens the link sees those answers already filled in and can still change them before submitting.",{"@type":125,"name":192,"acceptedAnswer":193},"Is there a bot that can automatically fill out Google Forms?",{"@type":128,"text":194},"Yes. A script can open a form and submit it with set values as many times as you like. It can break when the form's questions change, and using one on a form you do not own goes against Google's terms of service. For your own form, a pre-filled link or the linked response sheet covers most common needs.",{"@type":125,"name":196,"acceptedAnswer":197},"Can respondents change pre-filled answers?",{"@type":128,"text":198},"Yes. A pre-filled link only sets the starting value of a field. The respondent can edit or clear it before submitting. Google Forms has no setting that locks a pre-filled value in place.",{"@type":125,"name":200,"acceptedAnswer":201},"Does a pre-filled link work on mobile?",{"@type":128,"text":202},"Yes. It is an ordinary link, so it opens the form with the answers already filled in in any mobile browser. Browser extensions such as Google Forms Auto Filler run on desktop Chrome only, which is one reason a link is the better option when you own the form.",{"@type":125,"name":204,"acceptedAnswer":205},"Why is my pre-filled link not filling the answers?",{"@type":128,"text":206},"Common causes are a question that was deleted and added back, which gives it a new entry ID; a multiple choice value that does not match an option word for word; or a special character that was not URL-encoded. Generate a fresh link in the editor and compare its entry numbers with the old link.",{"@type":125,"name":208,"acceptedAnswer":209},"Can I pre-fill a Google Form from a spreadsheet?",{"@type":128,"text":210},"Yes. Create one link per row. First generate one pre-filled link to learn the entry IDs, then build the URL in a formula with ENCODEURL around each cell value and drag the formula down. Each row gets a link that opens the form with that row's details already filled in.","google form auto filler, google forms auto filler, prefill google form, autofill google forms, google form autofill, google form prefilled link, google form filler bot","Auto-fill a Google Form with Google's pre-fill link or a Chrome extension. What each does and where it stops, plus how to make one link per person.",[],"google-form-auto-filler","2026-09-01T12:00:00.000Z","mTaLTbvEHHPavCtQ9BSbz6sbY9rZrwu7eKt0RUUfUUU","\n![Cover art for a guide to auto-filling Google Forms with pre-fill links and extensions](https:\u002F\u002Fformester-strapi.s3.ap-south-1.amazonaws.com\u002F1761380fe68fe6cd_google-form-auto-filler-cover.png)\n\u003C!-- IMAGE: cover per cover-design layout A, title \"Auto-Fill a Google Form\" with Auto-Fill in orange, UI card showing a form with three fields already populated and a link bar above it -->\n\n\u003Cp style=\"font-size: inherit;\">A Google Form auto filler can mean two things. It can be a link with answers already filled in, or a browser tool that fills in your saved details. Which one you need depends on whether you made the form or you are filling it out. If you made the form, use the link. If someone sent you the form, use the tool. This guide covers both, plus the scripts people use to submit forms automatically.\u003C\u002Fp>\n\n\u003Cdiv class=\"tldr\">\n\u003Cp>\u003Cstrong>Quick answer\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\u003Cstrong>You made the form:\u003C\u002Fstrong> use the built-in \u003Cstrong>Pre-fill form\u003C\u002Fstrong> option. It gives you a link with your chosen answers already filled in.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>You were sent the form:\u003C\u002Fstrong> a Chrome extension such as Google Forms Auto Filler or QuickFill can fill in details you saved.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>You want a bot:\u003C\u002Fstrong> scripts can submit forms automatically, but they can break when the form changes. Using one on a form you do not own is against Google's terms.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003C\u002Fdiv>\n\n\u003Ch2>What does auto filler mean for a Google Form?\u003C\u002Fh2>\n\n\u003Cp>If you own the form, auto filling means sending it with some answers already filled in. You may already know the person's name, email, or booking reference, so you put those details in the link and they only fill in what you do not know. Google Forms does this with a pre-filled link, and that is usually what people mean when they search for a Google Forms auto filler.\u003C\u002Fp>\n\u003Cp>If you are filling out someone else's form, auto filling means a browser extension that stores your details once and types them into forms for you. That saves you from entering your name and email again and again. The extension can only fill details it already knows, so it cannot answer the form's actual questions.\u003C\u002Fp>\n\u003Cp>Read the section that matches your situation. The bot question near the end applies to both.\u003C\u002Fp>\n\n\u003Ch2>How to send a Google Form with answers already filled in\u003C\u002Fh2>\n\n\u003Cp>Pre-filling saves people from typing information you already have. It also helps keep those answers consistent. Google Forms has this built in, so you do not need to install anything.\u003C\u002Fp>\n\u003Col class=\"steps\">\n\u003Cli>\n\u003Ch3>Open the form in the editor\u003C\u002Fh3>\n\u003Cp>Go to forms.google.com and open the form you want to send. You need edit access, not just the link people use to submit responses.\u003C\u002Fp>\n\u003C\u002Fli>\n\u003Cli>\n\u003Ch3>Choose Pre-fill form\u003C\u002Fh3>\n\u003Cp>Click the three-dot \u003Cstrong>More\u003C\u002Fstrong> menu in the top right and select \u003Cstrong>Pre-fill form\u003C\u002Fstrong>. Google Forms opens a version of the form where anything you type becomes a starting answer.\u003C\u002Fp>\n\u003C\u002Fli>\n\u003Cli>\n\u003Ch3>Type the answers you want filled in\u003C\u002Fh3>\n\u003Cp>Fill only the fields you want to pre-fill and leave the rest empty. For multiple choice and dropdown questions, use the exact option text. The link matches the answer word for word.\u003C\u002Fp>\n\u003C\u002Fli>\n\u003Cli>\n\u003Ch3>Get the link\u003C\u002Fh3>\n\u003Cp>Click \u003Cstrong>Get link\u003C\u002Fstrong> at the bottom, then copy the link Google shows at the top. Anyone who opens it will see your answers already filled in. You can send it by email, add it to a calendar invite, or paste it into a message.\u003C\u002Fp>\n\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Cdiv class=\"note\">\u003Cp>Respondents can still change any pre-filled answer. The link only sets a starting value. It does not lock the field.\u003C\u002Fp>\u003C\u002Fdiv>\n\n\u003Ch2>How do the entry IDs in a pre-filled link work?\u003C\u002Fh2>\n\n\u003Cp>Open the link you copied and look at the end of the URL. Google adds something like this:\u003C\u002Fp>\n\u003Cp>\u003Ccode>?usp=pp_url&amp;entry.1234567890=Priya+Sharma&amp;entry.987654321=Marketing\u003C\u002Fcode>\u003C\u002Fp>\n\u003Cp>Each \u003Ccode>entry.\u003C\u002Fcode> number is the ID for a question. The text after the equals sign is the answer. The ID stays the same as long as the question exists, so you can change the answers by hand without opening the form editor again.\u003C\u002Fp>\n\u003Cp>Spaces become a plus sign or \u003Ccode>%20\u003C\u002Fcode>. Other special characters need URL encoding. Otherwise, the answer may not show up correctly.\u003C\u002Fp>\n\n\u003Ch3>Make one link per person from a Google Sheet\u003C\u002Fh3>\n\n\u003Cp>Creating a link for each person gets tedious pretty quickly. If their details are already in a spreadsheet, you can create the links with a formula.\u003C\u002Fp>\n\u003Col>\n\u003Cli>Generate one pre-filled link the normal way and paste it into a cell. Note which entry number belongs to each column.\u003C\u002Fli>\n\u003Cli>In a new column, build the link with a formula. With the base URL in A1 and the person's name and team in B2 and C2, use: \u003Ccode>=A1&amp;\"?usp=pp_url&amp;entry.1234567890=\"&amp;ENCODEURL(B2)&amp;\"&amp;entry.987654321=\"&amp;ENCODEURL(C2)\u003C\u002Fcode>\u003C\u002Fli>\n\u003Cli>Drag the formula down. Each row gets its own link, and ENCODEURL handles spaces and symbols for you.\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Cp>This is the closest thing Google Forms has to a mail merge. It works, but watch the entry numbers. One wrong digit can send a value to the wrong field.\u003C\u002Fp>\n\n\u003Ch2>Which extensions auto-fill Google Forms for you?\u003C\u002Fh2>\n\n\u003Cp>If you fill out Google Forms that other people send you, a pre-fill link does not help because you do not control the form. A browser extension can fill in details you saved once.\u003C\u002Fp>\n\u003Cp>Google Forms Auto Filler, on the Chrome Web Store, matches saved details such as your name and email to fields on a Google Form. QuickFill is an open-source extension on GitHub. You save a profile once, then click to fill. If it guesses a field wrong, you can undo it. QuickFill is installed through Chrome's developer mode instead of the Web Store, so setup takes a few extra steps.\u003C\u002Fp>\n\u003Cp>Both extensions fill in details you saved. If an extension does not recognize a question, it leaves it empty. Check the form before you submit.\u003C\u002Fp>\n\u003Cdiv class=\"table-wrap\">\n\u003Ctable>\n\u003Cthead>\u003Ctr>\u003Cth>\u003C\u002Fth>\u003Cth>Pre-filled link\u003C\u002Fth>\u003Cth>Browser extension\u003C\u002Fth>\u003Cth>Script or bot\u003C\u002Fth>\u003C\u002Ftr>\u003C\u002Fthead>\n\u003Ctbody>\n\u003Ctr>\u003Ctd>Who sets it up\u003C\u002Ftd>\u003Ctd>The form owner\u003C\u002Ftd>\u003Ctd>The person filling it\u003C\u002Ftd>\u003Ctd>Whoever writes it\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>What it fills\u003C\u002Ftd>\u003Ctd>Values you choose, per link\u003C\u002Ftd>\u003Ctd>Details the extension has saved\u003C\u002Ftd>\u003Ctd>Anything the script is told to\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>Works on a phone\u003C\u002Ftd>\u003Ctd>Yes, it is a link\u003C\u002Ftd>\u003Ctd>Desktop Chrome only for the two above\u003C\u002Ftd>\u003Ctd>Depends on where it runs\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>Still works when the form changes\u003C\u002Ftd>\u003Ctd>Breaks if a question is deleted and re-added\u003C\u002Ftd>\u003Ctd>Usually\u003C\u002Ftd>\u003Ctd>Breaks on layout changes\u003C\u002Ftd>\u003C\u002Ftr>\n\u003C\u002Ftbody>\n\u003C\u002Ftable>\n\u003C\u002Fdiv>\n\n\u003Ch2>Is there a bot that fills out Google Forms automatically?\u003C\u002Fh2>\n\n\u003Cp>Yes. A script written in Apps Script, Python, or a browser automation tool can open a Google Form and submit it with the values you give it.\u003C\u002Fp>\n\u003Cp>The problem is that scripts depend on the form's questions or positions. If the form changes, the script can break. And using a script to submit responses to a form you do not own is against Google's terms of service. The form owner can also report it as abuse.\u003C\u002Fp>\n\u003Cp>If you want people's details filled in before they open the form, use a pre-filled link. If you already have their details in a spreadsheet, you can also add them directly to the linked response sheet.\u003C\u002Fp>\n\n\u003Ch2>Where Google's pre-fill stops\u003C\u002Fh2>\n\n\u003Cp>A pre-filled link works when you already know the answers. It cannot look up or decide anything when the form opens.\u003C\u002Fp>\n\u003Cul>\n\u003Cli>It fills fixed values only. The link cannot look anything up when it opens, so it cannot pull today's booking from your calendar or a respondent's current plan from your CRM.\u003C\u002Fli>\n\u003Cli>Entry IDs are copied by hand. There is no field name to type; you get the number by creating a pre-filled link and reading the URL.\u003C\u002Fli>\n\u003Cli>Deleting a question and adding it back gives it a new ID. Any old link that uses the old ID leaves that field blank.\u003C\u002Fli>\n\u003Cli>There are no rules. You cannot fill the department from the email domain or skip a section because a value was pre-filled.\u003C\u002Fli>\n\u003Cli>File upload questions cannot be pre-filled.\u003C\u002Fli>\n\u003C\u002Ful>\n\n\u003Ch2>Where Formester fits\u003C\u002Fh2>\n\n\u003Cp>Formester covers these gaps. Its \u003Ca href=\"\u002Ffeatures\u002Fpre-fill-fields\u002F\">pre-fill fields\u003C\u002Fa> use the field label in the link instead of an entry ID. For example, a link that fills the name field can use \u003Ccode>?name=Priya\u003C\u002Fcode>. You can write the link without generating it first.\u003C\u002Fp>\n\u003Cp>The values stay editable, just like Google's. The respondent only fills in what is missing. The full walkthrough is in \u003Ca href=\"\u002Fblog\u002Fhow-to-pre-fill-form-fields-by-url-parameters\u002F\">pre-fill form fields by URL parameters\u003C\u002Fa>.\u003C\u002Fp>\n\u003Cp>If you need to look up information when the form opens, you can \u003Ca href=\"\u002Ffeatures\u002Fauto-fill-forms-with-external-data\u002F\">pull it from Airtable, Google Sheets, or Notion\u003C\u002Fa>. Once the respondent enters a trigger value, the matching details are added to the other fields. Each time the form opens, the data is fetched again, so the form can show current information instead of an old value saved in the link.\u003C\u002Fp>\n\n\u003Cdiv style=\"background:linear-gradient(135deg,#7f56d9 0%,#6941c6 100%);padding:32px 28px;margin:36px 0;border-radius:12px;color:#ffffff;font-family:inherit;text-align:center;\">\n\u003Cp style=\"margin:0 0 12px 0;font-size:18px;font-weight:700;color:#ffffff;font-family:inherit;\">Send a form that already knows who is filling it\u003C\u002Fp>\n\u003Cp style=\"margin:0 0 20px 0;font-size:14px;line-height:1.55;color:#f4ebff;font-family:inherit;\">Pre-fill fields by name in the link, or pull the respondent's record from Airtable, Google Sheets, or Notion the moment the form opens.\u003C\u002Fp>\n\u003Ca href=\"https:\u002F\u002Fapp.formester.com\u002Fusers\u002Fsign_up\" style=\"display:inline-block;padding:12px 24px;background:#ffffff;color:#6941c6;text-decoration:none;font-weight:700;border-radius:9999px;font-family:inherit;\">Try Formester free\u003C\u002Fa>\n\u003Cp style=\"margin:12px 0 0 0;font-size:13px;color:#e9d7fe;font-family:inherit;\">Free forever · No credit card · 56,000+ teams\u003C\u002Fp>\n\u003C\u002Fdiv>\n\n\u003Ch2>Related reading\u003C\u002Fh2>\n\n\u003Cul>\n\u003Cli>\u003Ca href=\"\u002Fblog\u002Fhow-to-link-google-sheets-to-google-forms\u002F\">Link Google Sheets to Google Forms\u003C\u002Fa>, where the response sheet used by the formula above comes from.\u003C\u002Fli>\n\u003Cli>\u003Ca href=\"\u002Fblog\u002Fgoogle-forms-webhooks\u002F\">Google Forms webhooks\u003C\u002Fa>, for sending each response somewhere else as soon as it arrives.\u003C\u002Fli>\n\u003Cli>\u003Ca href=\"\u002Fblog\u002Fcaptcha-for-google-forms\u002F\">CAPTCHA for Google Forms\u003C\u002Fa>, if the bot question brought you here because your form is being hit.\u003C\u002Fli>\n\u003C\u002Ful>\n\n\u003Csection class=\"faq\">\n\u003Ch2>Google Form auto filler FAQ\u003C\u002Fh2>\n\u003Cdetails>\u003Csummary>How do I automatically fill in a Google Form?\u003C\u002Fsummary>\u003Cdiv>Open the form in the editor, click the three-dot menu in the top right, choose Pre-fill form, enter the answers you want, and click Get link. Anyone who opens the link sees those answers already filled in and can still change them before submitting.\u003C\u002Fdiv>\u003C\u002Fdetails>\n\u003Cdetails>\u003Csummary>Is there a bot that can automatically fill out Google Forms?\u003C\u002Fsummary>\u003Cdiv>Yes. A script can open a form and submit it with set values as many times as you like. It can break when the form's questions change, and using one on a form you do not own goes against Google's terms of service. For your own form, a pre-filled link or the linked response sheet covers most common needs.\u003C\u002Fdiv>\u003C\u002Fdetails>\n\u003Cdetails>\u003Csummary>Can respondents change pre-filled answers?\u003C\u002Fsummary>\u003Cdiv>Yes. A pre-filled link only sets the starting value of a field. The respondent can edit or clear it before submitting. Google Forms has no setting that locks a pre-filled value in place.\u003C\u002Fdiv>\u003C\u002Fdetails>\n\u003Cdetails>\u003Csummary>Does a pre-filled link work on mobile?\u003C\u002Fsummary>\u003Cdiv>Yes. It is an ordinary link, so it opens the form with the answers already filled in in any mobile browser. Browser extensions such as Google Forms Auto Filler run on desktop Chrome only, which is one reason a link is the better option when you own the form.\u003C\u002Fdiv>\u003C\u002Fdetails>\n\u003Cdetails>\u003Csummary>Why is my pre-filled link not filling the answers?\u003C\u002Fsummary>\u003Cdiv>Common causes are a question that was deleted and added back, which gives it a new entry ID; a multiple choice value that does not match an option word for word; or a special character that was not URL-encoded. Generate a fresh link in the editor and compare its entry numbers with the old link.\u003C\u002Fdiv>\u003C\u002Fdetails>\n\u003Cdetails>\u003Csummary>Can I pre-fill a Google Form from a spreadsheet?\u003C\u002Fsummary>\u003Cdiv>Yes. Create one link per row. First generate one pre-filled link to learn the entry IDs, then build the URL in a formula with ENCODEURL around each cell value and drag the formula down. Each row gets a link that opens the form with that row's details already filled in.\u003C\u002Fdiv>\u003C\u002Fdetails>\n\u003C\u002Fsection>\n","blog\u002Fblog\u002Fgoogle-form-auto-filler.md",1200,{"text":221},"10 min read",1788439057780]