In the past few years I've moved to a "classes for styles only" design philosophy. I believe all other use cases - custom UI components, test hooks and third-party integrations, and event binding - have better solutions than a div with classes. Forms are no exception.
The challenge though is form fields require a wrapping element in order to implement layouts and custom styles and there's no native element for this. So, div and classes:
<div class="form-group">
<label>Name</label>
<input class="form-control">
</div>
But wanting to invent less and leverage more got me looking at fieldset with criminal intentions. Although uncommon, wrapping just one input does work and is technically valid markup. Even MDN has been caught in the act.
The result is the most clean and uniform form code I've ever seen:
<form>
<fieldset>
<label>Name</label>
<input>
</fieldset>
<fieldset>
<label>Phone</label>
<input type="tel">
</fieldset>
<fieldset>
<label>Address</label>
<input placeholder="Street">
<input placeholder="City">
<select>
<option>State...</option>
<option value="AL">Alabama</option>
<option value="WY">Wyoming</option>
</select>
</fieldset>
</form>
This enables the necessary selectors to customize form fields:
fieldset input,
fieldset select,
fieldset textarea {
border: 1px solid var(--m-color-gray-1);
}
fieldset textarea {
resize: vertical;
}
...
Does this push the boundaries a bit? Maybe, but I've done the same with bulletless lists and a custom "remove" button type in M- and it's all been a great experience so far. It's the HTML I wish we had without over-engineering to get it.
Take a look at M- forms and try the live code demos to get a feel for it. You might also find that sometimes breaking the web "law" feels good!


Discussion (6)
I'm coming here from totally out of the blue... so I might be missing some context here. 😅
But this question is about M- itself (since I couldn't quite figure out it immediately looking at the landing page, so I might be bit thick): The HTML at the M- forms page you linked to looks pretty standard. That is, it may feel a bit verbose, but to me it's pretty clean. Is it because M- is itself a bootstrap like library which styles (and maybe adds functionality to) the elements for you and also provides a way to easily create custom elements? 🤔
EDIT: Never mind; homepage says "UI Library." My embarrassing comment stays.
M- is like Bootstrap in the sense that it’s a ready-to-use collection of UI components and utility classes.
The purpose of this article is to just highlight how M- simply uses fieldset in a somewhat unconventional way rather than adding bloat like Bootstrap or similar. They require a div plus “input” classes, whereas M- just says fieldset all the things! I think it makes for much cleaner form code and avoids the extraneous input classes.
As long as the fieldsets make sense and you're not putting "first name" in one and "last name" in another, what's the problem? This is exactly the right element to use!
Agreed! But I've always wondered why do Bootstrap et al not use it? They do the div+classes thing. I think it's because convention taught us to only use fieldset for radio and checkbox groups...
I think bootstrap (and similar) are made by people who have already decided to reject semantic HTML. The philosophy is totally different - they assume you will be updating your templates when you make cosmetic changes, and that any machine-readable data will be presented in some other way, like as embedded JSON, and that you will manage accessibility with aria attributes as you go.
I don't agree with that (could you tell?) but it's the way a lot of frameworks are designed. Proponents say it makes things simpler and quicker to put together.
In Bootstrap’s they certainly made improvements in this direction, but it’s an old pattern.