Add CSS Grid Lanes support with toggleable shop setting
Implement CSS Grid Lanes (masonry layout) for product grids with graceful fallback to standard CSS Grid for browsers that don't support it yet. - Add grid_lanes_enabled column to Shop model (default: True) - Add toggle in Shop Settings under Announcement Ribbon Settings - Update product grid templates to conditionally apply grid-lanes-enabled class - CSS uses @supports (display: grid-lanes) for progressive enhancement - Mobile (160px min) and desktop (240px min) breakpoints supported When enabled and browser supports Grid Lanes, products flow into a waterfall/masonry layout where items fill the shortest column first, creating a Pinterest-style layout that handles varying image heights.
This commit is contained in:
parent
3bf65966c5
commit
b3270eb369
8 changed files with 107 additions and 6 deletions
|
|
@ -60,6 +60,9 @@ class Shop(RBase, Base):
|
|||
ribbon_color_1 = Column(Unicode(32), nullable=True, default="")
|
||||
ribbon_color_2 = Column(Unicode(32), nullable=True, default="")
|
||||
|
||||
# CSS Grid Lanes (masonry layout) - enabled by default
|
||||
grid_lanes_enabled = Column(Boolean, default=True)
|
||||
|
||||
# example: "UA-XX31XX60-3".
|
||||
google_analytics_id = Column(Unicode(32), nullable=True, default="")
|
||||
plausible_domain_name = Column(Unicode(256), nullable=True, default="")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
"""add grid_lanes_enabled to shop
|
||||
|
||||
Revision ID: a7c3e8f1d2b4
|
||||
Revises: b090f873502e
|
||||
Create Date: 2025-12-19 12:00:00.000000
|
||||
|
||||
"""
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = "a7c3e8f1d2b4"
|
||||
down_revision = "b090f873502e"
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
# Add grid_lanes_enabled column to mps_shop table with default True (enabled)
|
||||
op.add_column(
|
||||
"mps_shop",
|
||||
sa.Column("grid_lanes_enabled", sa.Boolean(), nullable=False, server_default="1"),
|
||||
)
|
||||
|
||||
|
||||
def downgrade():
|
||||
# Remove grid_lanes_enabled column from mps_shop table
|
||||
op.drop_column("mps_shop", "grid_lanes_enabled")
|
||||
|
|
@ -987,12 +987,36 @@ button.cart-public-button span.lock {
|
|||
background-color: #a3c765;
|
||||
}
|
||||
|
||||
/*
|
||||
* CSS Grid Lanes: Masonry-style layout with graceful fallback
|
||||
*
|
||||
* Grid Lanes is a new CSS feature that creates true masonry layouts natively.
|
||||
* We use @supports to detect browser support and fall back to regular CSS Grid.
|
||||
* Shop owners can toggle this via the "grid-lanes-enabled" class in settings.
|
||||
*
|
||||
* Fallback: Standard CSS Grid with auto-fit columns (items in rows)
|
||||
* Enhanced: CSS Grid Lanes (items flow into shortest column, waterfall style)
|
||||
*/
|
||||
|
||||
/* Default: Standard CSS Grid layout */
|
||||
section.serp {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(160px, 1.00fr));
|
||||
grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
|
||||
grid-auto-columns: max-content;
|
||||
grid-auto-flow: dense;
|
||||
grid-gap: 4px;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
/* Grid Lanes: Only apply when shop has it enabled AND browser supports it */
|
||||
@supports (display: grid-lanes) {
|
||||
section.serp.grid-lanes-enabled {
|
||||
display: grid-lanes;
|
||||
grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
|
||||
gap: 4px;
|
||||
/* item-tolerance controls sensitivity when deciding item placement */
|
||||
/* Prevents layout shuffling from minor size variations */
|
||||
item-tolerance: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
div.serp-item {
|
||||
|
|
@ -1403,7 +1427,7 @@ textarea.markup-editor-textarea {
|
|||
|
||||
/* The SERP page grid should have bigger items since it has more room.
|
||||
* mobile -> desktop
|
||||
* 140px -> 240px */
|
||||
* 160px -> 240px */
|
||||
section.serp {
|
||||
grid-template-columns: repeat(auto-fit, minmax(240px, .25fr));
|
||||
}
|
||||
|
|
@ -1538,6 +1562,24 @@ textarea.markup-editor-textarea {
|
|||
padding: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Desktop: Progressive enhancement for CSS Grid Lanes
|
||||
* This uses nested @supports inside @media to only apply when both
|
||||
* the viewport is desktop-sized AND the browser supports grid-lanes
|
||||
* AND the shop has grid-lanes-enabled class set
|
||||
*/
|
||||
@media (min-width: 960px) {
|
||||
@supports (display: grid-lanes) {
|
||||
section.serp.grid-lanes-enabled {
|
||||
display: grid-lanes;
|
||||
grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
|
||||
gap: 4px;
|
||||
item-tolerance: 1em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
div.message-ribbon {
|
||||
color: #ffffff;
|
||||
background-color: #5871ad;
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@
|
|||
{% else %}
|
||||
|
||||
{% if products %}
|
||||
<section class="serp">
|
||||
<section class="serp{% if request.shop.grid_lanes_enabled %} grid-lanes-enabled{% endif %}">
|
||||
{% for product in products %}
|
||||
|
||||
{% if product.is_ready %}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
{% block content -%}
|
||||
|
||||
<section class="serp">
|
||||
<section class="serp{% if request.shop.grid_lanes_enabled %} grid-lanes-enabled{% endif %}">
|
||||
{% if products %}
|
||||
{% for product in products %}
|
||||
|
||||
|
|
|
|||
|
|
@ -527,6 +527,16 @@
|
|||
<br />
|
||||
<br />
|
||||
|
||||
<label>Product Layout</label>
|
||||
<br />
|
||||
<input type="checkbox" name="grid-lanes-checkbox" id="grid-lanes-checkbox" {% if request.shop.grid_lanes_enabled %}checked{% endif %} />
|
||||
<label for="grid-lanes-checkbox" class="inline-label"><b>Enable Masonry Layout (Grid Lanes)</b></label>
|
||||
<br />
|
||||
<small class="note-text">When enabled, products flow into a waterfall/masonry layout where items fill the shortest column first. This creates a Pinterest-style layout that better handles varying product image heights. Requires browser support for CSS Grid Lanes.</small>
|
||||
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<input type="submit" name="submit" class="mps-submit" value="Save Settings" />
|
||||
|
||||
<br />
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
<section class="two-column">
|
||||
<div class="products-left">
|
||||
<h2>My Purchases</h2>
|
||||
<section class="serp">
|
||||
<section class="serp{% if request.shop and request.shop.grid_lanes_enabled %} grid-lanes-enabled{% endif %}">
|
||||
{% if products %}
|
||||
{% for product in products %}
|
||||
<div class="serp-item">
|
||||
|
|
|
|||
|
|
@ -385,6 +385,9 @@ def shop_settings(request):
|
|||
# Theme settings
|
||||
default_theme = request.params.get("default_theme", shop.default_theme)
|
||||
|
||||
# Grid lanes setting (keep current value by default)
|
||||
grid_lanes_enabled = shop.grid_lanes_enabled
|
||||
|
||||
google_analytics_id = request.params.get(
|
||||
"google_analytics_id", shop.google_analytics_id
|
||||
)
|
||||
|
|
@ -564,6 +567,19 @@ def shop_settings(request):
|
|||
)
|
||||
request.session.flash(msg)
|
||||
|
||||
# Handle grid lanes setting
|
||||
grid_lanes_checkbox = request.params.get("grid-lanes-checkbox", "off")
|
||||
grid_lanes_enabled = checkbox_to_bool(grid_lanes_checkbox)
|
||||
if shop.grid_lanes_enabled != grid_lanes_enabled:
|
||||
shop.grid_lanes_enabled = grid_lanes_enabled
|
||||
status = "enabled" if grid_lanes_enabled else "disabled"
|
||||
request.session.flash(
|
||||
(
|
||||
f"Masonry layout (Grid Lanes) {status}",
|
||||
"success",
|
||||
)
|
||||
)
|
||||
|
||||
# Handle stripe settings form
|
||||
if form_section == "stripe-settings":
|
||||
# Handle disable action
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue