fix: related content overflow and horizontal scroll issues (#1305)
* fix: resolve related content card overflow and page horizontal scroll * fix: prevent related content overflow on mobile while preserving shadow space * fix: align related content cards and prevent shadow clipping Expands the left margin of the related content carousel to match the main article, preserving the full card shadow. Adds a visual mask gradient to gracefully fade out the right edge. * feat: add mask image also to left side of subsection list, which is activated when scrolling * feat: fade out right mask image near the end of horizontal scroll --------- Co-authored-by: Jimmy Cai <jimmy@cai.im>
This commit is contained in:
@@ -44,24 +44,79 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@property --left-edge-fade-size {
|
||||||
|
syntax: "<length>";
|
||||||
|
inherits: false;
|
||||||
|
initial-value: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@property --right-edge-fade-size {
|
||||||
|
syntax: "<length>";
|
||||||
|
inherits: false;
|
||||||
|
initial-value: 64px;
|
||||||
|
}
|
||||||
|
|
||||||
.subsection-list {
|
.subsection-list {
|
||||||
--shadow-overlap-x: calc(var(--shadow-l2-blur) + 4px);
|
--shadow-overlap-x: calc(var(--shadow-l2-blur) + 4px);
|
||||||
--shadow-overlap-y: calc(var(--shadow-l2-blur) + var(--shadow-l2-y) + 4px);
|
--shadow-overlap-y: calc(var(--shadow-l2-blur) + var(--shadow-l2-y) + 4px);
|
||||||
|
--edge-fade-size: 64px;
|
||||||
|
--left-edge-fade-size: 0px;
|
||||||
|
--right-edge-fade-size: var(--edge-fade-size);
|
||||||
|
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
|
|
||||||
|
/// Limit the horizontal overlap to the container padding to prevent page overflow on mobile.
|
||||||
|
/// On desktop, it still allows the full shadow to be visible.
|
||||||
|
--overlap-x: min(var(--shadow-overlap-x), var(--container-padding));
|
||||||
|
|
||||||
/// These values are computed from the shadow of the article-list--tile (which uses shadow-l1 and shadow-l2)
|
/// These values are computed from the shadow of the article-list--tile (which uses shadow-l1 and shadow-l2)
|
||||||
/// so that the shadow is not cut off
|
/// so that the shadow is not cut off, while staying within the viewport on small screens.
|
||||||
margin-left: calc(var(--shadow-overlap-x) * -1);
|
/// Clamp both sides to prevent page-level horizontal overflow.
|
||||||
margin-right: calc(var(--shadow-overlap-x) * -1);
|
margin-left: calc(var(--overlap-x) * -1);
|
||||||
|
margin-right: calc(var(--overlap-x) * -1);
|
||||||
margin-bottom: calc(var(--shadow-overlap-y) * -1);
|
margin-bottom: calc(var(--shadow-overlap-y) * -1);
|
||||||
|
|
||||||
|
/// Smooth fade on both horizontal edges to avoid hard cuts where shadows are clamped.
|
||||||
|
--subsection-mask-image: linear-gradient(
|
||||||
|
to right,
|
||||||
|
transparent 0%,
|
||||||
|
rgb(0 0 0 / 0.06) calc(var(--left-edge-fade-size) * 0.12),
|
||||||
|
rgb(0 0 0 / 0.2) calc(var(--left-edge-fade-size) * 0.3),
|
||||||
|
rgb(0 0 0 / 0.45) calc(var(--left-edge-fade-size) * 0.52),
|
||||||
|
rgb(0 0 0 / 0.72) calc(var(--left-edge-fade-size) * 0.76),
|
||||||
|
black var(--left-edge-fade-size),
|
||||||
|
black calc(100% - var(--right-edge-fade-size)),
|
||||||
|
rgb(0 0 0 / 0.72) calc(100% - (var(--right-edge-fade-size) * 0.76)),
|
||||||
|
rgb(0 0 0 / 0.45) calc(100% - (var(--right-edge-fade-size) * 0.52)),
|
||||||
|
rgb(0 0 0 / 0.2) calc(100% - (var(--right-edge-fade-size) * 0.3)),
|
||||||
|
rgb(0 0 0 / 0.06) calc(100% - (var(--right-edge-fade-size) * 0.12)),
|
||||||
|
transparent 100%
|
||||||
|
);
|
||||||
|
-webkit-mask-image: var(--subsection-mask-image);
|
||||||
|
mask-image: var(--subsection-mask-image);
|
||||||
|
|
||||||
|
// CSS-only: left fade ramps in quickly once horizontal scrolling starts,
|
||||||
|
// and right fade turns off near the end of horizontal scroll.
|
||||||
|
animation: subsection-left-fade linear both, subsection-right-fade linear both;
|
||||||
|
animation-timeline: scroll(self inline);
|
||||||
|
animation-range: 1px 24px, 0% 100%;
|
||||||
|
animation-timing-function: ease-out, linear;
|
||||||
|
|
||||||
|
[dir="rtl"] & {
|
||||||
|
margin-left: calc(var(--overlap-x) * -1);
|
||||||
|
margin-right: calc(var(--overlap-x) * -1);
|
||||||
|
}
|
||||||
|
|
||||||
.article-list--tile {
|
.article-list--tile {
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: var(--spacing-xs) var(--shadow-overlap-x) var(--shadow-overlap-y) var(--shadow-overlap-x);
|
padding: var(--spacing-xs) var(--overlap-x) var(--shadow-overlap-y) var(--overlap-x);
|
||||||
width: max-content;
|
width: max-content;
|
||||||
gap: var(--spacing-lg);
|
gap: var(--spacing-lg);
|
||||||
|
|
||||||
|
[dir="rtl"] & {
|
||||||
|
padding: var(--spacing-xs) var(--overlap-x) var(--shadow-overlap-y) var(--overlap-x);
|
||||||
|
}
|
||||||
|
|
||||||
article {
|
article {
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
|
||||||
@@ -76,3 +131,22 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@keyframes subsection-left-fade {
|
||||||
|
from {
|
||||||
|
--left-edge-fade-size: 0px;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
--left-edge-fade-size: var(--edge-fade-size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes subsection-right-fade {
|
||||||
|
0%,
|
||||||
|
92% {
|
||||||
|
--right-edge-fade-size: var(--edge-fade-size);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
--right-edge-fade-size: 0px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user