Horizontal Scroll
- Details
- Jeremy Meyer
Horizontal Scrollable Grid with non-clickable grid items. Scrolls off screen on desktop and mobile. This requires javascript to function.
j-horizontal-scroll
/* --- .j-horizontal-scroll Horizontal Scroll Styles --- */
.j-horizontal-scroll .g-content-array {
flex-wrap: nowrap !important;
justify-content: flex-start !important;
align-items: flex-start !important;
overflow-x: auto !important;
padding-bottom: 1.5rem !important;
scrollbar-width: thin;
cursor: grab;
user-select: none;
-webkit-user-select: none;
/* Full-bleed breakout aligned with container edge */
width: 100% !important;
box-sizing: content-box !important;
margin-left: calc(50% - 50vw) !important;
margin-right: calc(50% - 50vw) !important;
padding-left: calc(50vw - 50%) !important;
padding-right: calc(50vw - 50%) !important;
scroll-padding-left: calc(50vw - 50%) !important;
scroll-padding-right: calc(50vw - 50%) !important;
}
.j-horizontal-scroll .g-content-array:active {
cursor: grabbing;
}
/* Scrollbar Styling */
.j-horizontal-scroll .g-content-array::-webkit-scrollbar {
height: 8px;
}
.j-horizontal-scroll .g-content-array::-webkit-scrollbar-track {
background: rgba(0, 0, 0, 0.05);
border-radius: 4px;
}
.j-horizontal-scroll .g-content-array::-webkit-scrollbar-thumb {
background: rgba(26, 60, 130, 0.4);
border-radius: 4px;
}
.j-horizontal-scroll .g-content-array::-webkit-scrollbar-thumb:hover {
background: rgba(26, 60, 130, 0.8);
}
/* Grid Item Sizing */
.j-horizontal-scroll .g-grid {
flex: 0 0 calc(33.333% - 21.44px) !important;
max-width: calc(33.333% - 21.44px) !important;
scroll-snap-align: start;
}
.j-horizontal-scroll .g-array-item-image {
overflow: hidden !important;
display: block;
}
/* Hover Effects */
.j-horizontal-scroll .g-array-item-image img {
transition: transform 0.5s cubic-bezier(0.165, 0.84, 0.44, 1), opacity 0.5s ease !important;
}
.j-horizontal-scroll .g-array-item-image a:hover img {
transform: scale(1.05) !important;
opacity: 0.9 !important;
}
.j-horizontal-scroll .g-item-title a {
transition: color 0.3s ease;
}
.j-horizontal-scroll .g-item-title a:hover {
color: rgb(198, 147, 56) !important;
}
/* Mobile Responsiveness */
@media (max-width: 50.99rem) {
.j-horizontal-scroll .g-grid {
flex: 0 0 calc(85% - 16px) !important;
max-width: calc(85% - 16px) !important;
scroll-snap-align: center;
}
.j-horizontal-scroll .g-content-array {
scroll-padding: 0 7.5% !important;
scroll-snap-type: x mandatory !important;
}
/* Target site-sub only when it contains our specific scroll section */
.site-sub:has(.j-horizontal-scroll) .g-content-array .g-grid:not(:first-child) .g-content {
padding-top: 0 !important;
}
}
document.addEventListener('DOMContentLoaded', () => {
// Updated selector to match the new class name
const sliders = document.querySelectorAll('.j-horizontal-scroll .g-content-array');
sliders.forEach(slider => {
let isDown = false;
let startX;
let scrollLeft;
let velocity = 0;
let lastX = 0;
let momentumID;
// The inertia/momentum function
const beginMomentum = () => {
slider.scrollLeft += velocity;
velocity *= 0.80; // Heavier friction: stops the slide quicker
if (Math.abs(velocity) > 0.5) {
momentumID = requestAnimationFrame(beginMomentum);
}
};
slider.addEventListener('mousedown', (e) => {
isDown = true;
cancelAnimationFrame(momentumID); // Stop any existing glide
slider.style.scrollBehavior = 'auto'; // Immediate 1:1 dragging response
startX = e.pageX - slider.offsetLeft;
scrollLeft = slider.scrollLeft;
lastX = e.pageX;
});
const endDrag = () => {
if (!isDown) return;
isDown = false;
beginMomentum(); // Start the heavy glide when mouse is released
};
slider.addEventListener('mouseleave', endDrag);
slider.addEventListener('mouseup', endDrag);
slider.addEventListener('mousemove', (e) => {
if (!isDown) return;
e.preventDefault();
const x = e.pageX - slider.offsetLeft;
const walk = (x - startX); // Standard 1:1 drag speed
slider.scrollLeft = scrollLeft - walk;
// Track velocity based on cursor movement
velocity = lastX - e.pageX;
lastX = e.pageX;
});
// Prevent image links from triggering if the user was dragging
slider.addEventListener('click', (e) => {
// If velocity is high, it means the user was flicking/dragging, not clicking
if (Math.abs(velocity) > 3) {
e.preventDefault();
e.stopPropagation();
}
}, true);
});
});
Rows
- Details
- Jeremy Meyer
Rows on desktop scroll snap on mobile. Supports multiple aspect ratio. Intro text overflows and is scrollable.
square-rows
.square-rows {
--img-w: 280px;
}
/* Ensure the container height matches the image width to maintain 1:1 */
.square-rows .g-array-item {
position: relative;
display: grid;
grid-template-columns: var(--img-w) 1fr;
grid-template-rows: auto 1fr auto;
height: var(--img-w) !important;
background: var(--surface-color);
border: 1px solid rgba(var(--primary-color-rgb), 0.12);
overflow: hidden;
transition: box-shadow 0.3s ease, transform 0.3s ease;
}
.square-rows .g-array-item:hover {
box-shadow: 0 6px 18px rgba(var(--primary-color-rgb), 0.18);
transform: translateY(-2px);
}
/* Strict 1:1 Aspect Ratio for Image */
.square-rows .g-array-item-image {
grid-column: 1;
grid-row: 1 / 4;
height: 100% !important;
}
.square-rows .g-array-item-image img {
display: block;
width: 100% !important;
height: 100% !important;
aspect-ratio: 1 / 1 !important;
object-fit: cover !important;
}
/* Scrollable Text Area */
.square-rows .g-array-item-text {
position: relative;
z-index: 30;
grid-column: 2;
padding: 0.5rem 1.5rem;
overflow-y: auto;
color: var(--primary-color);
font-size: 0.95rem;
line-height: 1.5;
scrollbar-width: thin;
scrollbar-color: rgba(var(--primary-color-rgb), 0.3) transparent;
}
@media (min-width: 50.99rem) {
.square-rows .g-array-item-text {
pointer-events: none;
}
}
/* Webkit scrollbar styling for Chrome/Edge/Safari */
.square-rows .g-array-item-text::-webkit-scrollbar {
width: 6px;
}
.square-rows .g-array-item-text::-webkit-scrollbar-thumb {
background-color: rgba(var(--primary-color-rgb), 0.2);
border-radius: 10px;
}
/* Padding and spacing for Title/Button */
.square-rows .g-array-item-title {
grid-column: 2;
padding: 1.25rem 1.5rem 0.25rem;
}
.square-rows .g-array-item-title a {
color: var(--primary-color) !important;
font-size: 1.5rem;
font-weight: 700;
text-decoration: none;
transition: opacity 0.3s ease;
}
.square-rows .g-array-item-title a:hover {
opacity: 0.8;
}
.square-rows .g-array-item-read-more {
grid-column: 2;
padding: 0.5rem 1.5rem 1.25rem;
text-align: right;
background: var(--surface-color);
z-index: 10;
}
/* Primary color button */
.square-rows .g-array-item-read-more a.button {
background-color: var(--primary-color) !important;
color: #ffffff !important;
border-color: var(--primary-color) !important;
transition: background-color 0.3s ease, opacity 0.3s ease;
}
.square-rows .g-array-item-read-more a.button:hover {
opacity: 0.85;
}
/* Make the entire card clickable via the read-more link */
.square-rows .g-array-item-read-more a.button::after {
content: "";
position: absolute;
inset: 0;
z-index: 40;
cursor: pointer;
}
/* Mobile: Horizontal scroll-snap carousel */
@media (max-width: 50.99rem) {
/* Scroll container — the Gantry .g-content-array wraps all .g-grid items */
.square-rows .g-content-array {
display: flex !important;
flex-direction: row !important;
flex-wrap: nowrap !important;
overflow-x: auto;
overflow-y: hidden;
scroll-snap-type: x mandatory;
-webkit-overflow-scrolling: touch;
gap: 1rem;
padding-left: 2rem !important;
padding-right: 2rem !important;
padding-top: 2rem !important;
padding-bottom: 2rem !important;
/* hide scrollbar but keep swipe */
scrollbar-width: none;
-ms-overflow-style: none;
}
.square-rows .g-content-array::-webkit-scrollbar {
display: none;
}
/* Each .g-grid wraps one news item — make it a snap card at ~80vw
so the next card peeks in and signals swipe-ability */
.square-rows .g-content-array>.g-grid {
flex: 0 0 80vw;
max-width: 360px;
scroll-snap-align: center;
scroll-snap-stop: always;
}
/* Reset inner wrappers so the card fills properly */
.square-rows .g-grid>.g-block,
.square-rows .g-grid>.g-block>.g-content {
width: 100%;
max-width: 100%;
margin: 0;
padding: 0;
}
/* Card layout: image on top, content below */
.square-rows .g-array-item {
display: flex;
flex-direction: column;
height: auto !important;
border-radius: 4px;
overflow: hidden;
}
/* Square image on top */
.square-rows .g-array-item-image {
width: 100%;
height: auto;
aspect-ratio: 1 / 1;
flex-shrink: 0;
}
.square-rows .g-array-item-image img {
aspect-ratio: 1 / 1 !important;
width: 100% !important;
height: 100% !important;
}
.square-rows .g-array-item-title {
padding: 1rem 1rem 0.25rem;
}
.square-rows .g-array-item-title a {
font-size: 1.5rem;
}
/* Scrollable excerpt inside the card */
.square-rows .g-array-item-text {
padding: 0.25rem 1rem;
max-height: 120px;
overflow-y: auto;
touch-action: pan-y;
-webkit-overflow-scrolling: touch;
}
.square-rows .g-array-item-read-more {
padding: 0.5rem 1rem 1rem;
}
}