better layout

alphons <alphons@heijden.com> 5 Aug 2026, 21:08
7bc978bacf097293ee99f14d0dd142db93f67c9e
8 files changed
  • MailSharp.MailClient/Views/Account/Login.cshtml
  • MailSharp.MailClient/Views/Contacts/Index.cshtml
  • MailSharp.MailClient/Views/Mail/Compose.cshtml
  • MailSharp.MailClient/Views/Mail/Index.cshtml
  • MailSharp.MailClient/Views/Maintenance/Index.cshtml
  • MailSharp.MailClient/Views/Settings/Index.cshtml
  • MailSharp.MailClient/Views/Shared/_Layout.cshtml
  • MailSharp.MailClient/wwwroot/css/site.css
diff --git a/MailSharp.MailClient/Views/Account/Login.cshtml b/MailSharp.MailClient/Views/Account/Login.cshtml
index a137781..bb3cbca 100644
--- a/MailSharp.MailClient/Views/Account/Login.cshtml
+++ b/MailSharp.MailClient/Views/Account/Login.cshtml
@@ -57,5 +57,5 @@
</div>
</div>
@section Scripts {
- <script src="~/js/login.js"></script>
+ <script src="~/js/login.js" asp-append-version="true"></script>
}
diff --git a/MailSharp.MailClient/Views/Contacts/Index.cshtml b/MailSharp.MailClient/Views/Contacts/Index.cshtml
index 5f4fc66..ecd31dd 100644
--- a/MailSharp.MailClient/Views/Contacts/Index.cshtml
+++ b/MailSharp.MailClient/Views/Contacts/Index.cshtml
@@ -30,5 +30,5 @@
</div>
</div>
@section Scripts {
- <script src="~/js/contacts.js"></script>
+ <script src="~/js/contacts.js" asp-append-version="true"></script>
}
diff --git a/MailSharp.MailClient/Views/Mail/Compose.cshtml b/MailSharp.MailClient/Views/Mail/Compose.cshtml
index 3c8f8bb..2227c4f 100644
--- a/MailSharp.MailClient/Views/Mail/Compose.cshtml
+++ b/MailSharp.MailClient/Views/Mail/Compose.cshtml
@@ -102,5 +102,5 @@
</div>
</div>
@section Scripts {
- <script src="~/js/compose.js"></script>
+ <script src="~/js/compose.js" asp-append-version="true"></script>
}
diff --git a/MailSharp.MailClient/Views/Mail/Index.cshtml b/MailSharp.MailClient/Views/Mail/Index.cshtml
index 013b88c..a307da6 100644
--- a/MailSharp.MailClient/Views/Mail/Index.cshtml
+++ b/MailSharp.MailClient/Views/Mail/Index.cshtml
@@ -51,16 +51,12 @@
<a href="#" data-sort="size" data-i18n="mail_sort_size"></a>
</div>
</div>
- <div class="list-toolbar-row checkbox-grid-row">
+ <div class="list-toolbar-row checkbox-grid-row toolbar-checkbox-row">
<span class="flag-col"></span>
<input type="checkbox" data-select-all />
- <div class="toolbar-row-rest">
- <label class="unread-only-toggle">
- <input type="checkbox" id="unreadOnlyToggle" />
- <span data-i18n="mail_unread_only"></span>
- </label>
- <a class="btn" href="#" id="spamBtn" data-i18n="mail_spam"></a>
- </div>
+ <input type="checkbox" id="unreadOnlyToggle" />
+ <label for="unreadOnlyToggle" class="unread-only-label" data-i18n="mail_unread_only"></label>
+ <a class="btn" href="#" id="spamBtn" data-i18n="mail_spam"></a>
</div>
</div>
<div id="messageListBody"></div>
@@ -71,5 +67,5 @@
</div>
</div>
@section Scripts {
- <script src="~/js/mail.js"></script>
+ <script src="~/js/mail.js" asp-append-version="true"></script>
}
diff --git a/MailSharp.MailClient/Views/Maintenance/Index.cshtml b/MailSharp.MailClient/Views/Maintenance/Index.cshtml
index b67d721..e1d32ee 100644
--- a/MailSharp.MailClient/Views/Maintenance/Index.cshtml
+++ b/MailSharp.MailClient/Views/Maintenance/Index.cshtml
@@ -117,5 +117,5 @@
</div>
</div>
@section Scripts {
- <script src="~/js/maintenance.js"></script>
+ <script src="~/js/maintenance.js" asp-append-version="true"></script>
}
diff --git a/MailSharp.MailClient/Views/Settings/Index.cshtml b/MailSharp.MailClient/Views/Settings/Index.cshtml
index f946ccc..9a083ec 100644
--- a/MailSharp.MailClient/Views/Settings/Index.cshtml
+++ b/MailSharp.MailClient/Views/Settings/Index.cshtml
@@ -92,5 +92,5 @@
</div>
</div>
@section Scripts {
- <script src="~/js/settings.js"></script>
+ <script src="~/js/settings.js" asp-append-version="true"></script>
}
diff --git a/MailSharp.MailClient/Views/Shared/_Layout.cshtml b/MailSharp.MailClient/Views/Shared/_Layout.cshtml
index d053ac1..d4175ee 100644
--- a/MailSharp.MailClient/Views/Shared/_Layout.cshtml
+++ b/MailSharp.MailClient/Views/Shared/_Layout.cshtml
@@ -5,7 +5,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
<base href="@Url.Content("~/")" />
<title>MailSharp</title>
- <link rel="stylesheet" href="~/css/site.css" />
+ <link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
</head>
<body>
@RenderBody()
@@ -13,7 +13,7 @@
<button type="button" id="cancelRequestBtn" data-i18n="common_cancel_request"></button>
</div>
<div id="indexingToast" class="toast" hidden></div>
- <script src="~/js/common.js"></script>
+ <script src="~/js/common.js" asp-append-version="true"></script>
@await RenderSectionAsync("Scripts", required: false)
</body>
</html>
diff --git a/MailSharp.MailClient/wwwroot/css/site.css b/MailSharp.MailClient/wwwroot/css/site.css
index 2cc246a..9f86b1a 100644
--- a/MailSharp.MailClient/wwwroot/css/site.css
+++ b/MailSharp.MailClient/wwwroot/css/site.css
@@ -240,21 +240,33 @@ label { font-size: 13px; color: var(--text-muted); display: block; margin-bottom
/* Single shared source of truth for the checkbox column's geometry, used by BOTH this row and
.message-row below (they carry this exact same class) - grid-template-columns/column-gap can
only be defined once, here, so the two can never drift apart the way matching flex gaps by hand
- kept doing. Only the fixed-width leading columns (flag icon, checkbox) need to line up; the rest
- of each row's content differs entirely, hence 1fr swallowing everything after that. */
-.checkbox-grid-row { display: grid; grid-template-columns: 20px 20px 1fr; column-gap: 10px; align-items: center; }
-.toolbar-row-rest { display: flex; align-items: center; gap: 10px; }
+ kept doing. Only the fixed-width leading columns (flag icon, checkbox) need to line up.
+ Deliberately flat - every child is a direct grid item, none of them wrapped in their own nested
+ flex container, so align-items:center on this one grid is the only thing controlling vertical
+ position for all of them; nesting a flex row inside a grid item left its contents centered
+ relative to their own (different) box instead of the shared row. */
+.checkbox-grid-row { display: grid; grid-template-columns: 20px 20px auto auto; column-gap: 10px; align-items: center; justify-content: start; }
+/* Overrides the base 4-column template with 5 - unreadOnlyToggle's checkbox and its label are now
+ two separate flat grid items (see the markup) instead of one nested inside the other, so there's
+ nothing left that could center relative to its own sub-container instead of this row. */
+.toolbar-checkbox-row { grid-template-columns: 20px 20px 20px auto auto; }
.list-toolbar .sort-links { display: flex; align-items: center; gap: 4px; font-size: 13px; }
.list-toolbar .sort-links a { padding: 6px 8px; border-radius: 6px; color: var(--text-muted); }
.list-toolbar .sort-links a.active { color: var(--primary-dark); font-weight: 600; background: var(--accent-bg); }
.list-toolbar select { width: auto; padding: 8px 10px; font-size: 13px; flex-shrink: 0; }
-.unread-only-toggle { display: flex; align-items: center; gap: 6px; font-size: 13px; line-height: 1; color: var(--text-muted); cursor: pointer; flex-shrink: 0; }
-.unread-only-toggle input { cursor: pointer; }
-/* Normalizes checkbox box-model across browsers - without this, native checkbox rendering height
- varies just enough from the "Alleen ongelezen" text's own line-height/the Spam button's padding
- that align-items:center on the row centers three slightly different box heights instead of
- visually lining up their actual glyphs/baselines. */
-.list-toolbar-row input[type=checkbox] { width: 15px; height: 15px; margin: 0; flex-shrink: 0; }
+/* The global `label { display:block; margin-top:12px; margin-bottom:4px; }` rule (for form field
+ labels elsewhere) still applies to any property this rule doesn't explicitly override - a class
+ selector beats an element selector on specificity, but only for the properties it actually sets.
+ This was silently inheriting that 12px top margin the whole time: every earlier fix (grid
+ columns, checkbox sizing, line-height) was correct, but got undone by a form label style bleeding
+ into an unrelated toolbar checkbox label. display/margin here override it explicitly. */
+.unread-only-label { display: inline; margin: 0; font-size: 13px; color: var(--text-muted); cursor: pointer; white-space: nowrap; }
+/* One rule for every checkbox in both the toolbar and the message list (not two separate rules
+ with two separate sizes) - a native, unstyled checkbox's rendered size varies by browser/OS, so
+ the toolbar's select-all checkbox and a message row's own checkbox only ever end up the same
+ visible size, and therefore actually centered on the same line, if they share this one
+ declaration instead of one being explicitly sized and the other left to its native default. */
+.list-toolbar-row input[type=checkbox], .message-row input[type=checkbox] { width: 15px; height: 15px; margin: 0; flex-shrink: 0; }
.detail-header-row { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; margin-bottom: 12px; }
.detail-header-main { flex: 1; min-width: 0; }
@@ -276,7 +288,6 @@ label { font-size: 13px; color: var(--text-muted); display: block; margin-bottom
.message-row.unread { background: #fbfcff; }
.message-row.unread .subject { font-weight: 700; }
.message-row.selected { background: var(--accent-bg); box-shadow: inset 3px 0 0 var(--primary); }
-.message-row input[type=checkbox] { flex-shrink: 0; }
.message-row .main { flex: 1; min-width: 0; }
.message-row .subject { font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.message-row .from { color: var(--text-muted); font-size: 13px; margin-top: 2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }