From 50b86890e2af881d4054777f9975053f5557156b Mon Sep 17 00:00:00 2001 From: realtushartyagi Date: Thu, 9 Jul 2026 00:47:13 +0530 Subject: [PATCH] feat: Add CSS Spring Physics Accordion for Product Catalog Layouts (#33122) --- .../README.md | 57 ++++ .../demo.html | 96 ++++++ .../style.css | 276 ++++++++++++++++++ 3 files changed, 429 insertions(+) create mode 100644 submissions/examples/css-spring-physics-accordion-for-product-catalog-layouts-realtushartyagi-33122/README.md create mode 100644 submissions/examples/css-spring-physics-accordion-for-product-catalog-layouts-realtushartyagi-33122/demo.html create mode 100644 submissions/examples/css-spring-physics-accordion-for-product-catalog-layouts-realtushartyagi-33122/style.css diff --git a/submissions/examples/css-spring-physics-accordion-for-product-catalog-layouts-realtushartyagi-33122/README.md b/submissions/examples/css-spring-physics-accordion-for-product-catalog-layouts-realtushartyagi-33122/README.md new file mode 100644 index 0000000000..f2523fe138 --- /dev/null +++ b/submissions/examples/css-spring-physics-accordion-for-product-catalog-layouts-realtushartyagi-33122/README.md @@ -0,0 +1,57 @@ +# CSS Spring Physics Accordion for Product Catalogs + +A pure CSS accordion component built on native `
` and `` HTML elements. Designed specifically for e-commerce and product catalogs, it features a snappy "Spring Physics" interaction pattern: when the accordion expands, the content reveals itself using a bouncy, custom `cubic-bezier` timing function, providing satisfying tactile feedback reminiscent of premium native mobile shopping apps. + +## Files +- `demo.html` – A standalone demonstration page featuring a mocked product detail layout with a gallery, pricing, and three interactive accordion sections (Description, Specs, Shipping). +- `style.css` – The heavily-commented stylesheet containing the custom `cubic-bezier` spring logic, the CSS Grid trick for height transitions, and the animated plus/minus indicator. + +## How it works +1. **Semantic Foundation**: Relies entirely on the native HTML5 `
` and `` tags, providing built-in accessibility and keyboard navigation out of the box. +2. **Spring Physics via CSS Grid**: Native `
` elements do not animate their height by default. This stylesheet uses the modern CSS Grid trick (`grid-template-rows: 0fr` to `1fr`) on the `.ease-spring-content` wrapper. The secret sauce is the `--ease-spring-easing` variable (`cubic-bezier(0.175, 0.885, 0.32, 1.1)`), which slightly overshoots the target height and settles back into place rapidly. +3. **Cascading Content Animation**: To amplify the effect, the inner `.accordion-body` block features a secondary `transform: scale(0.98) translateY(-4px)` and opacity fade. When the accordion opens, this content springs down and scales up into place, creating a fluid, multi-layered cascade effect. +4. **Animated Plus/Minus**: The toggle indicator is built from two absolute `` lines forming a plus icon. When opened, the vertical line rotates to form a minus sign, utilizing the exact same snappy spring curve. + +## Usage + +You can copy the HTML structure and CSS variables directly into your product detail layouts. + +```html +
+ +

Product Description

+
+ + +
+
+
+
+
+

Your product information goes here.

+
+
+
+
+``` + +### Customizing the Spring Physics +The physics are governed by standard CSS Custom Properties defined in `:root`, making it trivial to adjust the "snappiness" for your brand: + +```css +:root { + --ease-spring-transition-time: 0.5s; /* Duration of the spring */ + + /* + The Y-value of 1.1 is what causes the slight "overshoot". + Increase it for more bounce, decrease towards 1.0 for a flatter transition. + */ + --ease-spring-easing: cubic-bezier(0.175, 0.885, 0.32, 1.1); +} +``` + +## Accessibility (prefers-reduced-motion) +Because it uses `
` and ``, screen readers naturally understand the expanded/collapsed state without needing manual `aria-expanded` ARIA attributes. A strict `@media (prefers-reduced-motion: reduce)` block is included to instantly strip away the spring bezier transforms, grid animations, and content fades for users who are sensitive to motion. + +## Why it fits EaseMotion CSS +EaseMotion advocates for zero-JavaScript UI patterns whenever possible. High-end e-commerce animations are typically built using bloated React/Vue state libraries or heavy JS physics engines just to achieve snappy accordion transitions. By combining the native `
` element with modern CSS Grid height transitions and a custom overshoot cubic-bezier, this component delivers a deeply interactive, 60fps physics-based experience entirely within the browser's CSS rendering engine. diff --git a/submissions/examples/css-spring-physics-accordion-for-product-catalog-layouts-realtushartyagi-33122/demo.html b/submissions/examples/css-spring-physics-accordion-for-product-catalog-layouts-realtushartyagi-33122/demo.html new file mode 100644 index 0000000000..6b9945f40b --- /dev/null +++ b/submissions/examples/css-spring-physics-accordion-for-product-catalog-layouts-realtushartyagi-33122/demo.html @@ -0,0 +1,96 @@ + + + + + + CSS Spring Physics Accordion - Product Catalog + + + + +
+ + +
+
+

Premium Noise-Cancelling Headphones

+

$299.00

+ +
+ + +
+ + +
+ +

Product Description

+
+ + +
+
+
+
+
+

+ Immerse yourself in high-fidelity audio with our industry-leading active noise cancellation. + Engineered for all-day comfort, these headphones feature plush memory foam earcups and a lightweight, + durable aluminum frame. +

+
+
+
+
+ + +
+ +

Tech Specifications

+
+ + +
+
+
+
+
+
    +
  • Battery Life: Up to 30 hours
  • +
  • Bluetooth: Version 5.3
  • +
  • Weight: 254 grams
  • +
  • Charging: USB-C fast charge
  • +
+
+
+
+
+ + +
+ +

Shipping & Returns

+
+ + +
+
+
+
+
+

+ Free standard shipping on all orders over $50. Need it faster? Expedited shipping options + are available at checkout. We offer a hassle-free 30-day return policy on all products in their original packaging. +

+
+
+
+
+ +
+
+
+ + diff --git a/submissions/examples/css-spring-physics-accordion-for-product-catalog-layouts-realtushartyagi-33122/style.css b/submissions/examples/css-spring-physics-accordion-for-product-catalog-layouts-realtushartyagi-33122/style.css new file mode 100644 index 0000000000..87aac41f45 --- /dev/null +++ b/submissions/examples/css-spring-physics-accordion-for-product-catalog-layouts-realtushartyagi-33122/style.css @@ -0,0 +1,276 @@ +/* + EaseMotion CSS - Spring Physics Accordion for Product Catalogs + Pure CSS Accordion using semantic
and elements. +*/ + +:root { + /* Configurable CSS Variables for E-Commerce / Catalogs */ + --ease-accordion-text: #111827; + --ease-accordion-muted: #6b7280; + --ease-accordion-accent: #2563eb; + --ease-accordion-border: #e5e7eb; + + /* Spring Physics Parameters */ + --ease-spring-transition-time: 0.5s; + /* + This custom cubic-bezier creates the "spring" physics. + It shoots slightly past 1.0 (to 1.1) and settles back, creating a snappy, physical feel. + */ + --ease-spring-easing: cubic-bezier(0.175, 0.885, 0.32, 1.1); +} + +/* Base Page Styling (for Demo) */ +body { + font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; + background-color: #ffffff; + color: var(--ease-accordion-text); + margin: 0; + padding: 3rem 1rem; + display: flex; + justify-content: center; + -webkit-font-smoothing: antialiased; +} + +/* Mock Product Layout */ +.product-layout { + display: grid; + grid-template-columns: 1fr; + gap: 3rem; + width: 100%; + max-width: 1000px; +} + +@media (min-width: 768px) { + .product-layout { + grid-template-columns: 1fr 1fr; + } +} + +.product-gallery .mock-image { + width: 100%; + aspect-ratio: 1 / 1; + background-color: #f3f4f6; + border-radius: 1rem; + display: flex; + align-items: center; + justify-content: center; + color: var(--ease-accordion-muted); + font-size: 1.25rem; +} + +.product-header { + margin-bottom: 2.5rem; +} + +.product-header h1 { + margin: 0 0 0.5rem 0; + font-size: 2rem; + font-weight: 700; + letter-spacing: -0.025em; +} + +.product-header .price { + margin: 0 0 1.5rem 0; + font-size: 1.5rem; + color: var(--ease-accordion-muted); +} + +.add-to-cart { + width: 100%; + padding: 1rem; + background-color: var(--ease-accordion-text); + color: white; + border: none; + border-radius: 0.5rem; + font-size: 1rem; + font-weight: 600; + cursor: pointer; + transition: background-color 0.2s ease; +} + +.add-to-cart:hover { + background-color: #000000; +} + +/* + ======================================== + ACCORDION GROUP & BASE STYLING + ======================================== +*/ +.ease-spring-product-accordion-group { + display: flex; + flex-direction: column; +} + +.ease-spring-accordion { + border-top: 1px solid var(--ease-accordion-border); +} + +.ease-spring-accordion:last-child { + border-bottom: 1px solid var(--ease-accordion-border); +} + +/* Hide default marker in webkit/standard */ +.ease-spring-summary::-webkit-details-marker { + display: none; +} + +.ease-spring-summary { + display: flex; + align-items: center; + justify-content: space-between; + padding: 1.5rem 0; + cursor: pointer; + list-style: none; + outline: none; +} + +.ease-spring-summary h3 { + margin: 0; + font-size: 1.125rem; + font-weight: 600; + transition: color 0.3s ease; +} + +/* + ======================================== + INTERACTIVE STATES & FOCUS + ======================================== +*/ +.ease-spring-summary:hover h3, +.ease-spring-summary:focus-visible h3 { + color: var(--ease-accordion-accent); +} + +.ease-spring-summary:focus-visible { + box-shadow: inset 0 0 0 2px rgba(37, 99, 235, 0.4); + border-radius: 4px; /* Slight rounding for focus ring */ +} + +/* + ======================================== + THE PLUS/MINUS INDICATOR (Animated) + ======================================== +*/ +.ease-spring-indicator { + position: relative; + width: 20px; + height: 20px; + flex-shrink: 0; +} + +.indicator-line { + position: absolute; + top: 50%; + left: 0; + width: 100%; + height: 2px; + background-color: var(--ease-accordion-text); + margin-top: -1px; /* perfectly center */ + /* The indicator itself uses the snappy spring curve when it rotates */ + transition: transform var(--ease-spring-transition-time) var(--ease-spring-easing), + background-color 0.3s ease; +} + +.indicator-line.vertical { + transform: rotate(90deg); +} + +.ease-spring-summary:hover .indicator-line, +.ease-spring-summary:focus-visible .indicator-line { + background-color: var(--ease-accordion-accent); +} + +/* When open, rotate the vertical line to 0deg, turning the plus into a minus */ +.ease-spring-accordion[open] .indicator-line.vertical { + transform: rotate(0deg); +} + +.ease-spring-accordion[open] .indicator-line.horizontal { + transform: rotate(180deg); +} + + +/* + ======================================== + OPEN STATE & SPRING EXPANSION + ======================================== +*/ + +/* + CSS Grid technique for smooth height transition of the content. + The crucial part is the transition timing function, which uses our snappy spring curve. +*/ +.ease-spring-content { + display: grid; + grid-template-rows: 0fr; + transition: grid-template-rows var(--ease-spring-transition-time) var(--ease-spring-easing); +} + +.ease-spring-accordion[open] .ease-spring-content { + grid-template-rows: 1fr; +} + +.ease-content-inner { + overflow: hidden; /* Required for the grid height trick */ +} + +/* + Accordion Body Styling inside the expanding content +*/ +.accordion-body { + padding-bottom: 1.5rem; + color: var(--ease-accordion-muted); + line-height: 1.6; + + /* + Add a secondary transform to the content itself for a cascading spring effect. + It starts slightly scaled down and transparent, then springs up into place. + */ + transform: scale(0.98) translateY(-4px); + opacity: 0; + transform-origin: top center; + transition: transform var(--ease-spring-transition-time) var(--ease-spring-easing), + opacity calc(var(--ease-spring-transition-time) * 0.8) ease; +} + +/* Trigger the cascade when open */ +.ease-spring-accordion[open] .accordion-body { + transform: scale(1) translateY(0); + opacity: 1; +} + +.accordion-body p { + margin: 0; +} + +.spec-list { + margin: 0; + padding: 0; + list-style: none; + display: flex; + flex-direction: column; + gap: 0.5rem; +} + +.spec-list li { + display: flex; + justify-content: space-between; + border-bottom: 1px dotted var(--ease-accordion-border); + padding-bottom: 0.5rem; +} + +.spec-list li strong { + color: var(--ease-accordion-text); + font-weight: 500; +} + +/* Accessibility: Respect Reduced Motion */ +@media (prefers-reduced-motion: reduce) { + .ease-spring-content, + .indicator-line, + .accordion-body { + transition: none !important; + transform: none !important; + } +}