Thread-Layout: Strich als Flex-Geschwister, mittig unter dem Avatar
Strich neben dem Content wird über ein eigenes Flex-Element mit align-self: stretch gezeichnet statt über eine Border am Content – dadurch exakt so hoch wie der Inhalt, kein Über-/Unterstehen mehr. Vorfahren und Antworten teilen denselben Mechanismus (Antworten ohne Border). Strichposition und -dicke über CSS-Variablen an die halbe Avatargröße gekoppelt, sodass die Linie mittig unter dem Byline-Avatar sitzt. Antworten-Label in die Byline verschoben, vertikaler Abstand unter den .body-Container. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+39
-25
@@ -33,6 +33,8 @@
|
||||
}
|
||||
|
||||
html {
|
||||
--avatar-sm: 50px; /* Größe des Byline-Avatars; halbiert = Position des Thread-Strichs */
|
||||
--line-w: 3px; /* Dicke des Thread-Strichs */
|
||||
background-image: url("/static/assets/concrete/Concrete012_1024p_Color.jpg");
|
||||
font-family: "EB Garamond", serif;
|
||||
font-optical-sizing: auto;
|
||||
@@ -91,7 +93,6 @@ h2 {
|
||||
main {
|
||||
max-width: 600px;
|
||||
margin: auto;
|
||||
padding: 0 0.5rem;
|
||||
}
|
||||
|
||||
main > section,
|
||||
@@ -101,7 +102,10 @@ main > p {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
main > section,
|
||||
main > section {
|
||||
padding: 0rem 0.3rem;
|
||||
}
|
||||
|
||||
main > h2 {
|
||||
padding: 0.3rem 0.5rem;
|
||||
}
|
||||
@@ -141,11 +145,9 @@ a.button:hover, button:hover {
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
background-color: white;
|
||||
padding: 0.5rem;
|
||||
margin-bottom: 0;
|
||||
font-size: 1.2rem;
|
||||
border: none;
|
||||
border-bottom: 1px solid #ccc;
|
||||
}
|
||||
|
||||
.card:hover {
|
||||
@@ -158,6 +160,10 @@ a.button:hover, button:hover {
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
|
||||
#focus .card {
|
||||
margin: 0rem 0.3rem ;
|
||||
}
|
||||
|
||||
/* Beitragsbild (nicht der Byline-Avatar). */
|
||||
.card img:not(.avatar) {
|
||||
display: block;
|
||||
@@ -181,7 +187,7 @@ img.avatar {
|
||||
max-width: none;
|
||||
}
|
||||
|
||||
img.avatar-sm { width: 50px; height: 50px; }
|
||||
img.avatar-sm { width: var(--avatar-sm); height: var(--avatar-sm); }
|
||||
img.avatar-lg { width: 72px; height: 72px; }
|
||||
|
||||
/* Byline mit kleinem Avatar neben Name + Zeitstempel. */
|
||||
@@ -198,34 +204,42 @@ img.avatar-lg { width: 72px; height: 72px; }
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
/* Ahnenkette: der Strich links symbolisiert den Thread oberhalb des Beitrags. */
|
||||
#ancestors .card {
|
||||
border-left: 3px solid gray;
|
||||
margin-left: 3%;
|
||||
padding-left: 0.75rem;
|
||||
/* --- Thread-Strich ---
|
||||
Der Strich ist ein eigenes Flex-Geschwister links neben dem Inhalt, nicht
|
||||
eine Border am Inhalt selbst. align-self: stretch macht ihn exakt so hoch
|
||||
wie der Inhalt (kein Über-/Unterstehen). Die Meta-Zeile (.byline) liegt
|
||||
außerhalb des Wrappers, also volle Breite über dem Strich.
|
||||
Standard (Feed/Fokus): Strich aus, Inhalt volle Breite. */
|
||||
.threadline-wrapper { display: flex; }
|
||||
.threadline { display: none; align-self: stretch; }
|
||||
.body { flex: 1; min-width: 0; margin-bottom: 1rem; }
|
||||
|
||||
/* Vorfahren UND direkte Antworten: gleiche Einrückung, Meta-Zeile bleibt links.
|
||||
Die Strich-Spalte ist halb so breit wie der Avatar, ihr rechter Rand (= der
|
||||
Strich) liegt damit unter der Mitte des Byline-Avatars. Der Abstand zum
|
||||
Inhalt ist ebenfalls die halbe Avatarbreite -> Inhalt beginnt unter dem
|
||||
rechten Avatarrand. Der .body füllt per flex:1 den Rest. */
|
||||
#ancestors .threadline,
|
||||
#replies .threadline {
|
||||
display: block;
|
||||
/* Box um die Linienbreite schmaler -> die rechts gezeichnete border-right
|
||||
landet genau auf der Avatarmitte statt rechts daneben. */
|
||||
flex: 0 0 calc(var(--avatar-sm) / 2 - var(--line-w));
|
||||
margin-right: calc(var(--avatar-sm) / 2);
|
||||
}
|
||||
|
||||
/* Direkte Antworten unter dem Fokus-Beitrag: nur eingerückt, kein Thread-Strich. */
|
||||
#replies .card {
|
||||
margin-left: 3%;
|
||||
padding-left: 0.75rem;
|
||||
}
|
||||
/* Nur die Vorfahren bilden einen Thread -> Linie. Antworten nur eingerückt. */
|
||||
#ancestors .threadline { border-right: var(--line-w) solid gray; }
|
||||
|
||||
/* Interaktionsleiste: Vote-Buttons mittig (auto-Spalte zwischen zwei gleichen
|
||||
1fr-Spalten), das Antworten-Label links daneben. */
|
||||
/* Interaktionsleiste: Vote-Buttons zentriert (das Antworten-Label sitzt jetzt
|
||||
oben in der Byline). */
|
||||
.interactions {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr auto 1fr;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: 0.25rem;
|
||||
}
|
||||
|
||||
.interactions .replies {
|
||||
justify-self: start;
|
||||
}
|
||||
|
||||
.row {
|
||||
justify-self: center;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
|
||||
+20
-12
@@ -45,9 +45,13 @@ function renderEntry(e) {
|
||||
// Soft-gelöschter Beitrag: nur Platzhalter, damit der Thread navigierbar bleibt.
|
||||
if (e.deleted) {
|
||||
el.innerHTML = `
|
||||
<div class="muted">[deleted] · ${when}</div>
|
||||
<div class="content">[deleted]</div>
|
||||
<div class="muted"><a href="/e/${e.pid}">${replyLabel}</a></div>
|
||||
<div class="muted byline"><span>[deleted] · ${when} · <a href="/e/${e.pid}">${replyLabel}</a></span></div>
|
||||
<div class="threadline-wrapper">
|
||||
<div class="threadline"></div>
|
||||
<div class="body">
|
||||
<div class="content">[deleted]</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
el.addEventListener("click", (ev) => {
|
||||
if (!ev.target.closest("a, button")) location.href = `/e/${e.pid}`;
|
||||
@@ -64,16 +68,20 @@ function renderEntry(e) {
|
||||
el.innerHTML = `
|
||||
<div class="muted byline">
|
||||
<a href="/u/${user}"><img class="avatar avatar-sm" src="${avatarUrl(e.avatar)}" alt="" loading="lazy"></a>
|
||||
<span><a href="/u/${user}">${escapeHtml(e.username)}</a> · ${when}</span>
|
||||
<span><a href="/u/${user}">${escapeHtml(e.username)}</a> · ${when} · <a href="/e/${e.pid}">${replyLabel}</a></span>
|
||||
</div>
|
||||
<div class="content">${linkify(e.content)}</div>
|
||||
${media}
|
||||
<div class="interactions">
|
||||
<div class="muted replies"><a href="/e/${e.pid}">${replyLabel}</a></div>
|
||||
<div class="row">
|
||||
<button class="ghost" data-mode="left">Links</button>
|
||||
<span class="muted">– / –</span>
|
||||
<button class="ghost" data-mode="right">Rechts</button>
|
||||
<div class="threadline-wrapper">
|
||||
<div class="threadline"></div>
|
||||
<div class="body">
|
||||
<div class="content">${linkify(e.content)}</div>
|
||||
${media}
|
||||
<div class="interactions">
|
||||
<div class="row">
|
||||
<button class="ghost" data-mode="left">Links</button>
|
||||
<span class="muted">– / –</span>
|
||||
<button class="ghost" data-mode="right">Rechts</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
Reference in New Issue
Block a user