Free Webflow components / Effect: form button with sending and done states
Webflow form button with loading and success states
A free newsletter form for Webflow whose button shows a sending state, then a green confirmation. Copy it, press ⌘V, and it pastes as a native Webflow form.
- Native form
- Responsive
- Hover states
What you receive in Webflow
- 16 native elements and 9 classes.
- Breakpoints: mobile landscape (767px).
- States: focus, hover.
- The form pastes as a native Webflow form, with a success message and an error message.
- 2 Embed elements keep the CSS or script that Webflow cannot express. To edit an Embed, you must have a paid Webflow site plan.
How to paste it
- Click Copy for Webflow.
- Open your page in the Webflow Designer.
- Press ⌘V or Ctrl+V.
HTML
<section class="fs">
<div class="fs-card">
<h2 class="fs-title">Get the monthly field notes</h2>
<p class="fs-text">The button shows each step: sending, then a confirmation when it's done.</p>
<form class="fs-form" name="field-notes">
<input class="fs-input" type="email" name="email" placeholder="you@company.com" required aria-label="Email address">
<button class="fs-btn" type="submit">Subscribe</button>
</form>
<p class="fs-note" role="status" aria-live="polite">No spam. One email a month.</p>
</div>
</section>
<style>
.fs { font-family: Arial, 'Helvetica Neue', Helvetica, sans-serif; background: #0f172a; color: #f8fafc; padding: 112px 24px; }
.fs-card { max-width: 600px; margin: 0 auto; text-align: center; }
.fs-title { font-size: 40px; line-height: 1.12; letter-spacing: -0.02em; margin: 0 0 12px; }
.fs-text { font-size: 17px; line-height: 1.6; color: #94a3b8; margin: 0 0 36px; }
.fs-form { display: flex; gap: 10px; justify-content: center; }
.fs-input { flex: 1 1 auto; max-width: 340px; font-family: Arial, 'Helvetica Neue', Helvetica, sans-serif; font-size: 16px; color: #f8fafc; background: #1e293b; border: 1px solid #334155; border-radius: 999px; padding: 16px 22px; }
.fs-input:focus { border-color: #22d3ee; outline: none; }
.fs-input::placeholder { color: #64748b; }
.fs-btn { min-width: 150px; height: 54px; font-family: Arial, 'Helvetica Neue', Helvetica, sans-serif; font-size: 16px; font-weight: 700; color: #0f172a; background-color: #22d3ee; background-size: 28px 28px; border: 0; border-radius: 999px; padding: 0 26px; cursor: pointer; transition: background-color 0.3s ease, min-width 0.35s ease; }
.fs-btn:hover { background-color: #67e8f9; }
.fs-btn:focus-visible { outline: 3px solid #a5f3fc; outline-offset: 3px; }
.fs-btn.is-loading { cursor: progress; background-color: #22d3ee; background-image: repeating-linear-gradient(-45deg, rgba(255, 255, 255, 0.35) 0 7px, rgba(255, 255, 255, 0) 7px 14px); animation: fs-stripes 0.6s linear infinite; }
.fs-btn.is-done { min-width: 170px; color: #052e1c; background-color: #34d399; }
.fs-note { font-size: 14px; color: #64748b; margin: 18px 0 0; }
@keyframes fs-stripes { to { background-position: 28px 0; } }
@media (max-width: 767px) { .fs { padding: 80px 20px; } .fs-title { font-size: 30px; } .fs-form { flex-direction: column; align-items: stretch; } .fs-input { max-width: none; } .fs-btn { align-self: center; } }
</style>
<script>
document.querySelectorAll(".fs-form").forEach(function (form) {
// Works with a <button> or with Webflow's form button, which is an <input type="submit">
var btn = form.querySelector(".fs-btn, [type=submit]");
var note = form.parentNode.querySelector(".fs-note");
var isInput = btn.tagName === "INPUT";
var label = isInput ? btn.value : btn.textContent;
function setLabel(t) { if (isInput) btn.value = t; else btn.textContent = t; }
var inWebflow = !!window.Webflow && !!form.closest(".w-form");
form.addEventListener("submit", function (e) {
if (btn.classList.contains("is-loading")) { e.preventDefault(); return; }
btn.classList.remove("is-done"); btn.classList.add("is-loading"); setLabel("Sending…");
if (note) note.textContent = "Sending…";
if (inWebflow) return; // Webflow sends the form and shows its own success message
e.preventDefault();
setTimeout(function () {
btn.classList.remove("is-loading"); btn.classList.add("is-done"); setLabel("\u2713 You're in");
if (note) note.textContent = "Check your inbox to confirm.";
form.reset();
setTimeout(function () { btn.classList.remove("is-done"); setLabel(label); if (note) note.textContent = "No spam. One email a month."; }, 2600);
}, 1200);
});
});
</script>
More examples
Questions
Do submissions go to Webflow?
Yes. It pastes as a native Form Block, so entries arrive in your Webflow form submissions and Webflow shows its success message.
Can I change the button text?
Yes. Edit the button text in the Designer. The script remembers it and puts it back after a submission.
Is this effect component free?
Yes. Copy it with no account and use it on client sites and your own sites.
Does it work on the free Webflow plan?
Yes. It pastes on every Webflow plan, including Starter. If it includes an Embed element, editing that Embed's code needs a paid site plan.