contact messages: messaging settings as a two-row grid

Labels on row one, the flag selector and boxes on row two — the flag
centers with the boxes for real (grid cells), and its auto column takes
only the flag's width. Field wrappers are display:contents; an empty
label spacer above the flag keeps the fields in the 1fr columns even
when the selector renders nothing (single-language sites).
This commit is contained in:
LeoVasanko committed 2026-09-29 01:35:36 +00:00
1 parent fc7697dda3
commit 38b08679c6
1 file changed
+30 -35
+30 -35
View File
@@ -769,8 +769,8 @@ onUnmounted(() => {
</section>
<section class="block">
<div class="block-head msg-head">
<div v-if="contactLangOptions.length > 1" class="field msg-flag">
<div class="msg-grid">
<div class="msg-flag">
<span class="field-label" aria-hidden="true"></span>
<LangSelect
v-model="lang"
@@ -960,47 +960,42 @@ onUnmounted(() => {
font-size: 1rem;
}
/* The messaging block: one line — the article editor's flag selector,
then the labeled boxes (contact button label = the enable switch,
email subject; the mailto "our email" last, where the planned SMTP
address joins it). Labels sit directly above their own box; the row
stretches so all columns share one height and the flag, in its own
column under an empty label spacer, centers against the boxes. The
boxes are readonly until first interaction (+ vendor ignore
/* The messaging block: a two-row grid — labels on the first row, the
article editor's flag selector and the boxes on the second, so the
flag centers with the boxes and every label sits directly above its
own field (contact button label = the enable switch, email subject,
the mailto "our email" last, where the planned SMTP address joins
it). The flag column sizes to the flag; when only one language is
configured the selector renders nothing and the column collapses.
The boxes are readonly until first interaction (+ vendor ignore
attributes): password managers offer credential autofill on them no
matter the autocomplete setting. */
.msg-head {
align-items: stretch;
flex-wrap: wrap;
}
.msg-head .field {
flex: 1 1 8rem;
flex-direction: column;
align-items: stretch;
gap: 0.15rem;
min-width: 7rem;
}
.msg-head .msg-flag {
flex: 0 0 auto;
}
/* The flag fills its column below the label spacer, so centering inside
it centers against the input row exactly. */
.msg-flag .lang-select {
flex: 1;
display: flex;
.msg-grid {
display: grid;
grid-template-columns: auto minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1fr);
align-items: center;
gap: 0.15rem 0.6rem;
}
/* The shared 5rem label track is for side-by-side labels; stacked
labels size to their text. */
.msg-head .field > .field-label {
/* Field wrappers vanish into the grid: labels land on row 1 (the
flag's empty spacer keeps the fields in the 1fr columns whether or
not the flag renders), the flag and boxes on row 2. */
.msg-grid .field,
.msg-grid .msg-flag {
display: contents;
}
.msg-grid .field-label {
grid-row: 1;
min-width: 0;
}
.msg-head .text-input {
.msg-grid .lang-select,
.msg-grid .text-input {
grid-row: 2;
}
.msg-grid .text-input {
flex: none;
font-size: 0.85rem;
}