SmarkForm

🚀 Powerful while effortless Markup-driven and Extendable form controller.

NPM Version npm dependencies NPM Downloads jsDelivr Hits License

SmarkForm is a lightweight library designed for front-end developers and designers to enhance HTML forms with powerful features like subforms and dynamic, variable-length lists, context driveh hotkeys and more…

🔧 It seamlessly integrates with the DOM to provide a markup-agnostic solution, freeing your form layout from rigid structure and styling constraints while enabling JSON form data import and export and ensuring compatibility with modern workflows.

♿ With a focus on accessibility (a11y), SmarkForm offers configurable hotkeys, smooth navigation, and a low-code experience, making it an extendable and versatile tool for building HTML form applications.

[More…]

Main Features

  • <> Markup agnostic: Maximum decoupling between design and development teams.
  • 🧩 Low code: No manual wiring between controls and fields.
  • 🗂 Subforms: Nested forms to any depth.
  • 📑 Lists: Sortable and variable-length lists (arrays) either of scalars or subforms.
  • 🫳 Configurable hot keys: Context-driven and discoverable keyboard shortcuts.
  • 🫶 Consistent UX: Smooth navigation and consistent behaviour across all forms.
  • {} JSON format: Data is imported / exported as JSON.
  • 🪶 Lightweight: Only 43KB minified.
  • Accessibility: Focus on UX and accessibility (a11y).
  • 🆓 Dependency-free: No external dependencies required.
  • 💪 Flexible, extendable and more…

Sample Code

The following code snippet shows SmarkForm simplicity.

✅ Click everywhere in the form to focus it.

✅ Hit the Ctrl key to see the available hotkeys revealed. Notice they may change depending on the focused context.

✅ Check the JS tab to see that there is no JS code other than the library instantiation.

✅ Check the HTML tab to see that how straightforward and simple it is.

🔗
🗒️ HTML
🎨 CSS
⚙️ JS
👁️ Preview
📝 Notes
<div id="myForm">
    <p>
        <label data-smark='{"type": "label"}'>Name:</label>
        <input name='name' data-smark='{"type": "input"}' />
    </p>
    <p>
        <label data-smark='{"type": "label"}'>Surname:</label>
        <input name='surname' data-smark='{"type": "input"}' />
    </p>
    <button data-smark='{"action":"removeItem", "context":"phones", "target":"*", "hotkey":"Delete", "preserve_non_empty":true}' title='Remove unused fields'>🧹</button>
    <button data-smark='{"action":"removeItem", "context":"phones", "hotkey":"-", "preserve_non_empty":true}' title='Remove phone number'></button>
    <button data-smark='{"action":"addItem","context":"phones", "hotkey":"+"}' title='Add phone number'></button>
    <strong data-smark='label'>Phones:</strong>
    <ul data-smark='{"name": "phones", "of": "input", "sortable":true, "max_items":5, "exportEmpties": true}'>
        <li class="row">
            <label data-smark>📞 Telephone
            <span data-smark='{"action":"position"}'>N</span>
            </label>
            <button data-smark='{"action":"removeItem", "hotkey":"-"}' title='Remove this phone number'></button>
            <input type="tel" data-smark>
            <button data-smark='{"action":"addItem", "hotkey":"+"}' title='Insert phone number'></button>
        </li>
    </ul>
</div>
/* *******************************************************************
✔ The only `CSS` code is almost just to materialize the hotkeys hints
when pressing the `Ctrl` key (Remember SmarkForm is HTML agnostic).
******************************************************************* */

/* Materialize hotkey hints from data-hotkey attribute */
#myForm [data-hotkey] {
  position: relative;
  overflow-x: display;
}
#myForm [data-hotkey]::before {
  content: attr(data-hotkey);
  display: inline-block;
  position: absolute;
  top: 2px;
  left: 2px;
  z-index: 10;
  pointer-events: none;
  background-color: #ffd;
  outline: 1px solid lightyellow;
  padding: 2px 8px;
  border-radius: 4px;
  font-weight: bold;
  font-family: sans-serif;
  font-size: 0.8em;
  white-space: nowrap;
  transform: scale(1.8) translate(0.1em, 0.1em);
}
/* Hide list bullets */
#myForm ul li {
    list-style-type: none;
}
/* Make disabled buttons more evident: */
#myForm :disabled {
    opacity: 0.4;
}

const myForm = new SmarkForm(document.getElementById("myForm"));

Phones:

👉 This is a simple form to show the power of SmarkForm.

  • Tinker with it in the Preview tab, modifying data, etc…
    • Add or remove items from the Phones list.
    • Sort the list by dragging them with the mouse.
    • Use the ⬇️ to export the data as JSON.
    • Use the to clear the form.
    • Use the ⬆️ to import the JSON back to the form. You can modify the JSON before importing it back.
  • Notice you can navigate forward and backward using the keyboard:
    • Using the Enter and Shift+Enter from field to field bypassing control buttons.
    • Using the Tab and Shift+Tab as usual, to reach both fields and control buttons.
    • Don’t miss the hotkeys! Move the focus to a telephone field and hit the Ctrl key to see the avaliable ones (depending on focused context) revealed.

👉 Its behavior is driven by the data-smark attributes, which are declarative and intuitive with straightforward defaults to match most common use cases.

  • …for instance, min_items is set to 1 by default, so you cannot remove the last item from the Phones list. But you can change it by setting min_items to 0, allowing an empty list.

  • Another interesting case is the exportEmpties property, which is set to false by default, so empty items are not usually exported. In this example, it is set to true since, for a first contact, it might seem counterintuitive.

👉 Check the JS tab to see the little JS just to initialize it as a SmarkForm and show you the data when exported.

👉 In the CSS tab you will find some non-essential CSS primarily to materialize hotkeys’ revealing feature when pressing the Ctrl key.

👉 You will find similar examples working preview along this documentation. Don’t miss the 📝 Notes tab to be aware of the nitty-gritty details.

To minimize clutter, the ⬇️ Export, ⬆️ Import and ❌ Clear buttons implementation have been omitted from the source code, as they are common to all examples and will be explained in detail in a 🔗 later section.

Current Status

SmarkForm implementation is stable and fully functional, but not all initially planned requirements are yet implemented. Hence, it’s not yet in the 1.0.0 version. [🔗 More…]

Last Updated: Thu Oct 23 2025.

Where to Go Next?

To get started with SmarkForm you can:

👉 Take a look to our 🔗 Showcase section to see its full potential at a glance.
👉 Follow our 🔗 Quick Start Guide to rapidly dive in.
👉 Check out our 🔗 Downloadable Examples to see them in action and/or start tinkering.

Community and Support

If you don’t find a solution there, feel free to open a discussion on our GitHub repository.

For further support, you can contact me through our Contact Page or reach out via email at smarkform@bitifet.net.

If you want to stay updated with the latest news, releases, and announcements, or join the community chat, you can follow us on Telegram:

🚀 Stay tuned

News and announcements: SmarkForm Telegram Channel
Community Chat: SmarkForm Telegram Community

Contributing

We welcome any feedback, suggestions, or improvements as we continue to enhance and expand the functionality of SmarkForm.

👉 See the 🔗 Contributing Section for more details.

License

🔗 MIT