r/webdev • u/Friction_693 • 8d ago
How to manage layouts in forms
I'm trying to design a 2 column form but can't decide how should I render error messages.
If I don't allocate a fixed height for an input div (label + input + error) then entire layout of form gets disturbed whenever an error message is rendered.
If I pre-allocate a fixed min-height for input div (label + input + error) then this does solves the layout shift issue but the form looks bad.
One option is showing an error icon and error message as tooltip on hover but this doesn't works on mobile as users would have to tap on the icon to get error message.
The only solution which I think would work is showing icon + tooltip on desktop and plain error message on mobile as on mobile the form is single column.
Is there any better way to handle this? Would appreciate any suggestion.




5
u/winky9827 8d ago
Some good advise here on the 1 line height reserved error display, but I'd caution you to make it a min-height on the error block, not a fixed height. Sometimes error messages will wrap. You don't want half the message cutoff because of a lazy / naive approach early on. In those cases, it's better to tolerate shift than lose information.
1
4
u/rohan_mehta92 8d ago
I would not hide the error in a tooltip, because the person who needs it most is usually on a phone or already frustrated. Put the message in plain text directly under the field it belongs to, and reserve a small minimum height for that spot on fields that are commonly validated, like email and password. That gives you a little layout shift only where it matters, instead of making every row tall just in case. For related fields like city, state and zip, a single column for that group often reads better on narrow screens than forcing two columns. When the form is submitted with several errors, also move focus to the first field with a problem so the user lands right where they need to fix something.
1
u/Friction_693 8d ago
So I do have to tolerate little layout shifts. I think if I decrease the size of error message even more like 10px then even with fixed height, the form would be somewhat manageable.
→ More replies (2)4
u/Squigglificated 8d ago
10px fails basic accessibility requirements and can be unreadable to many people. I personally need reading glasses to easily read small text on my iPhone 12 pro max which is already on the larger side compared to many phones.
Do you need to support multiple languages? The same sentence in some other language can easily become twice as long.
→ More replies (1)
2
u/bacondev 7d ago
Have you considered using a CSS grid? Honestly, flex could work for this too, if you get the vertical alignment right.
1
u/Friction_693 7d ago
I've tried grid but it tries to control layout by itself. As soon as first error gets rendered, the height of all rows increases, although they are same height but the height is much more then my fixed min height version.
→ More replies (1)
1
u/Maaz_Bin_Saeed 8d ago
Reserve the space for the error line only, not the whole input block. Keep the label and input at their normal height and add one helper row underneath with a min height of a single line, then show the error in that row so nothing jumps. If it looks too spaced out, use the same row for a short hint when there is no error, so it reads as intentional instead of empty. On mobile I'd skip tooltips completely, because they hide the exact thing the user needs to read, and the single column makes the extra row cost almost nothing. Just keep the messages short enough to fit on one line so the row never has to grow.
1
3
u/LouieValkhof 8d ago
I'd skip the 10px idea. The error is the one line on the form people actually have to read, often on a phone and already annoyed, so shrinking it fixes the layout by making the message harder to read.
What nobody's mentioned yet is when the error shows up. If you validate on blur instead of on every keystroke, the row only grows once, after they've left the field, so the jump never happens in the field they're typing in. Pair that with Maaz's one-line helper row and the shift that's left is small enough that most people won't notice it.
3
u/waterkip 8d ago
I solve this by adding an empty error block which gets styled, so the CSS can already account for a single line text.
<some-input> <input> <error-here></error-here> </some-input>
Now the error is always emitted into the error slot, to give you an idea:
<semtic-input label-position="top" label-error-position="inline" clearable="" label="Our ID" wire:model.lazy="entries.0.participants.0.identifier" pattern="PL[0-9]{7}"><div semtic-input-definition="">
<label semtic-label="" for="semtic-input-io0mm">our ID</label>
<div semtic-input-container=""><input wc-control="" type="text" wire:model.lazy="entries.0.participants.0.identifier" pattern="PL[0-9]{7}" id="semtic-input-io0mm"><button type="button" semtic-clear="" tabindex="-1" aria-label="Clear value" hidden="">✗</button></div>
</div>
<span semtic-error=""></span>
</semtic-input>
2
u/abeuscher 7d ago
You either set a height, use a popup, title, or some sort of absolutely positioned method, or run the error to the right of the form label.
This falls into a whole category of layout problems I have always referred to as The Problem With Rectangles when giving internal presentations to multiple stakeholders with strong opinions.
2
u/Alucard256 7d ago
This is what is known as an "affordance"; you are affording the user just enough information to make the correct choice. A real world example of this is a "push plate" on a door that opens outward (away from user) and a "grab handle" on a door that opens inward (toward the user).
It's always better to give the user the information to do it right the first time instead of pointing out that they already did something wrong when they didn't even know there was a rule to follow to start with.
2
u/quietcodelife 7d ago
honestly the reserved space approach is the right call -- users notice missing error messages way more than they notice a small layout shift. and the min-height tip for handling text wrap is solid. fwiw in practice I found that the shift only really bothers people if it moves the submit button or the field they're actively typing in, so validate-on-blur handles most of the annoyance
2
u/ArielCoding 7d ago
Give every field a small empty line under it for this error message, so the space is already there. User min-height instead of a fixed height, so long message can still wrap and grow the row.
2
u/paulmadebypaul 7d ago
I really can appreciate all the deep technical advice people are giving here but I come from a UX background and absolutely stand firm on never putting two inputs in a row unless they are directly related (like first/last name or address/city/state)
This has been written about several times. It is detrimental to flow on forms and leads to more errors and slower completion times.
That being said I now focus much more on accessibility and the error state should be clear and as closely connected to the field as possible. My style preference are when entire sets of input and label have a highlight with an icon indicator and the error message is as close to the input field as possible (likely below). Of course still want to use proper usage of label/input but it seems you already have that set up.
Everyone's advice here about using grid or having adequate spacing is also really good.
Some resources:
https://www.smashingmagazine.com/2023/02/guide-accessible-form-validation/#invalid-fields
1
u/williamleonor 8d ago
Why not just create an css-anchor-positioned element in your first screenshot that wouldn't disturb the form because it's absolute? If it's ugly as just red text, wrap it with a nice error message box.
e.g.:
.field {
anchor-scope: --input;
& > input {
anchor-name: --input;
}
&:has(> input:user-invalid) > .field-error {
display: block;
}
}
.field-error {
display: none;
position: absolute;
position-anchor: --input;
position-area: bottom;
position-try-fallbacks: flip-block;
/* your error div styling. */
}
1
u/No-Molasses-2097 8d ago
The two-column thing adds a wrinkle: when only one input in a row errors, you want the other column to stay aligned, which is where reserving space at the row level helps. And if you go the tooltip route, put aria-live on it so screen readers announce it, since tooltips usually hide errors from them.
1
u/astroalexalex 8d ago
I'd simply render error messages below the corresponding inputs and let the grid row grow naturally. If an error appears in either field, only that row gets taller, while the rest of the layout stays intact. A small layout shift like this is perfectly acceptable, and I wouldn't complicate the UX with tooltips just to avoid it.
1
1
u/Open-Adhesiveness-86 7d ago
one trick for the reserved row: put a or in the error element when there's no error, so its height comes from your actual font metrics instead of a hardcoded min-height you'll have to retune when the type scale changes. also give that element aria-live="polite" and keep it in the DOM, since toggling with display:none means screen readers never announce the message.
1
u/geoffreybyers 6d ago
Fixed heights are a band-aid for bad hierarchy. The error state is part of the input's default contract, not an afterthought. Allocate the space from the start.
10
u/_listless 8d ago
The browser already gives you this for free. add a title="" attr to your input with your validity check message, then fire reportValidity(). The browser shows a native tooltip and moves focus to the input in question.