SmarkForm

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

NPM Version npm dependencies NPM Downloads jsDelivr Hits License

SmarkForm is a lightweight, markup-driven form controller for front-end developers: add data-smark attributes to your HTML, initialize with one line of JavaScript, and get powerful subforms, variable-length lists, context-driven hotkeys, and JSON import/export — all without touching your layout.

👉 See What SmarkForm Is (and Isn’t Yet) for more details.

Interactive Demo

A nested subform, a sortable list, context-driven hotkeys, and date/time coercion — all driven by data-smark attributes with zero extra JavaScript.

🔗
🗒️ HTML
🎨 CSS
⚙️ JS
👁️ Preview
<div id="myForm">
    <div class="ep">
        <p>
            <label data-smark>📋 Event:</label>
            <input data-smark name="title" type="text" placeholder="e.g. Sprint Review">
        </p>
        <p>
            <label data-smark>📅 Date:</label>
            <input data-smark name="date" type="date">
        </p>
        <p>
            <label data-smark>⏰ Time:</label>
            <input data-smark name="time" type="time">
        </p>
        <fieldset data-smark='{"type":"form","name":"organizer"}'>
            <legend data-smark='label'>👤 Organizer</legend>
            <p>
                <label data-smark>Name:</label>
                <input data-smark name="name" type="text">
            </p>
            <p>
                <label data-smark>Email:</label>
                <input data-smark name="email" type="email">
            </p>
        </fieldset>
        <div class="ep-list">
            <button data-smark='{"action":"removeItem","context":"attendees","hotkey":"Delete","preserve_non_empty":true}' title='Remove empty slots'>🧹</button>
            <button data-smark='{"action":"addItem","context":"attendees","hotkey":"+"}' title='Add attendee'></button>
            <strong data-smark='label'>👥 Attendees:</strong>
            <ul data-smark='{"type":"list","name":"attendees","of":"input","sortable":true,"exportEmpties":false}'>
                <li>
                    <span data-smark='{"action":"position"}'>N</span>.
                    <input data-smark type="text" placeholder="Name">
                    <button data-smark='{"action":"removeItem","hotkey":"-"}' title='Remove'></button>
                    <button data-smark='{"action":"addItem","hotkey":"+"}' title='Insert here'></button>
                </li>
            </ul>
        </div>
        <p class="ep-hint">💡 Hold <kbd>Ctrl</kbd> to reveal shortcuts</p>
    </div>
</div>
#myForm .ep {
    display: flex;
    flex-direction: column;
    gap: 0.35em;
    max-width: 460px;
    font-size: 0.95em;
}
#myForm .ep p {
    display: flex;
    align-items: center;
    gap: 0.5em;
    margin: 0;
}
#myForm .ep label {
    min-width: 4.5em;
    font-weight: 500;
    white-space: nowrap;
}
#myForm .ep input {
    padding: 0.3em 0.5em;
    border: 1px solid #ccc;
    border-radius: 4px;
}
#myForm .ep input[type="text"],
#myForm .ep input[type="email"] {
    flex: 1;
}
#myForm .ep fieldset {
    border: 1px solid #ddd;
    border-radius: 6px;
    padding: 0.4em 0.8em 0.6em;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 0.3em;
}
#myForm .ep fieldset legend {
    font-weight: bold;
    padding: 0 0.3em;
}
#myForm .ep-list ul {
    list-style: none;
    padding: 0;
    margin: 0.2em 0 0;
    display: flex;
    flex-direction: column;
    gap: 0.25em;
}
#myForm .ep-list ul li {
    display: flex;
    align-items: center;
    gap: 0.4em;
}
#myForm .ep-hint {
    font-size: 0.82em;
    color: #888;
    margin: 0.15em 0 0;
}
#myForm .ep-hint kbd {
    background: #f4f4f4;
    border: 1px solid #ccc;
    border-radius: 3px;
    padding: 1px 4px;
}
/* Hotkey hints revealed on Ctrl press */
#myForm [data-hotkey] {
    position: relative;
    overflow-x: visible;
}
#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;
    color: #44f;
    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);
}
const myForm = new SmarkForm(document.getElementById("myForm"), {
    value: { "title": "Sprint Review", "date": "2025-03-15", "time": "10:00", "organizer": { "name": "Alice Johnson", "email": "alice@example.com" }, "attendees": ["Bob Smith", "Carol White", "Dave Brown"] }
});

👤 Organizer

👥 Attendees:
  • N.

💡 Hold Ctrl to reveal shortcuts

Every example in this section comes with many of the following tabs:

  • HTML: HTML source code of the example.
  • CSS: CSS applied (if any)
  • JS: JavaScript source code of the example.
  • Preview: This is where you can see the code in action.
  • Notes: Additional notes and insights for better understanding. Don't miss it‼️

TL;DR

Want to dig deeper right away? Head to the 🔗 Showcase to explore interactive, editable demos — including the example above — that show SmarkForm’s full potential at a glance.

Prefer to jump straight into code? Browse 🔗 Live Examples for a collection of ready-to-use, downloadable forms you can run locally and start tinkering with immediately.

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 46KB minified.
  • Accessibility: Focus on UX and accessibility (a11y).
  • 🆓 Dependency-free: No external dependencies required.
  • 🤖 AI-agent ready: Generate complete, working forms by describing them to any AI assistant.
  • 💪 Flexible, extendable and more…

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: Mon Mar 02 2026.

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