diff --git a/components/masonry.css b/components/masonry.css new file mode 100644 index 00000000..06a1d2c0 --- /dev/null +++ b/components/masonry.css @@ -0,0 +1,227 @@ +/* ============================================================ + EaseMotion CSS — masonry.css + Pinterest-style masonry layout utilities for flexible content grids + ============================================================ */ + +/* ──────────────────────────────────────────────────────────── + MASONRY BASE CLASS + – Defines the base container for masonry layouts + – Uses CSS columns for a lightweight, accessible approach + ──────────────────────────────────────────────────────────── */ + +.ease-masonry { + column-gap: var(--ease-space-4); + break-inside: avoid-column; +} + +.ease-masonry > * { + break-inside: avoid; + margin-bottom: var(--ease-space-4); +} + +/* ──────────────────────────────────────────────────────────── + 2-COLUMN MASONRY LAYOUT + – Responsive: 1 column mobile (< 640px), 2 columns tablet+ + ──────────────────────────────────────────────────────────── */ + +.ease-masonry-2 { + columns: 2; + column-gap: var(--ease-space-4); +} + +.ease-masonry-2 > * { + break-inside: avoid; + margin-bottom: var(--ease-space-4); +} + +/* Mobile: single column */ +@media (max-width: 639px) { + .ease-masonry-2 { + columns: 1; + } +} + +/* ──────────────────────────────────────────────────────────── + 3-COLUMN MASONRY LAYOUT + – Responsive: 1 column mobile (< 640px) + – 2 columns tablet (640px - 1023px) + – 3 columns desktop (>= 1024px) + ──────────────────────────────────────────────────────────── */ + +.ease-masonry-3 { + columns: 3; + column-gap: var(--ease-space-4); +} + +.ease-masonry-3 > * { + break-inside: avoid; + margin-bottom: var(--ease-space-4); +} + +/* Mobile: single column */ +@media (max-width: 639px) { + .ease-masonry-3 { + columns: 1; + } +} + +/* Tablet: two columns */ +@media (min-width: 640px) and (max-width: 1023px) { + .ease-masonry-3 { + columns: 2; + } +} + +/* ──────────────────────────────────────────────────────────── + 4-COLUMN MASONRY LAYOUT + – Responsive: 1 column mobile (< 640px) + – 2 columns tablet (640px - 1023px) + – 3 columns small desktop (1024px - 1279px) + – 4 columns large desktop (>= 1280px) + ──────────────────────────────────────────────────────────── */ + +.ease-masonry-4 { + columns: 4; + column-gap: var(--ease-space-4); +} + +.ease-masonry-4 > * { + break-inside: avoid; + margin-bottom: var(--ease-space-4); +} + +/* Mobile: single column */ +@media (max-width: 639px) { + .ease-masonry-4 { + columns: 1; + } +} + +/* Tablet: two columns */ +@media (min-width: 640px) and (max-width: 1023px) { + .ease-masonry-4 { + columns: 2; + } +} + +/* Small desktop: three columns */ +@media (min-width: 1024px) and (max-width: 1279px) { + .ease-masonry-4 { + columns: 3; + } +} + +/* ──────────────────────────────────────────────────────────── + MASONRY GAP VARIANTS + – Override default gap spacing using ease-space-* variables + ──────────────────────────────────────────────────────────── */ + +.ease-masonry.ease-gap-1, +.ease-masonry-2.ease-gap-1, +.ease-masonry-3.ease-gap-1, +.ease-masonry-4.ease-gap-1 { + column-gap: var(--ease-space-1); +} + +.ease-masonry.ease-gap-1 > *, +.ease-masonry-2.ease-gap-1 > *, +.ease-masonry-3.ease-gap-1 > *, +.ease-masonry-4.ease-gap-1 > * { + margin-bottom: var(--ease-space-1); +} + +.ease-masonry.ease-gap-2, +.ease-masonry-2.ease-gap-2, +.ease-masonry-3.ease-gap-2, +.ease-masonry-4.ease-gap-2 { + column-gap: var(--ease-space-2); +} + +.ease-masonry.ease-gap-2 > *, +.ease-masonry-2.ease-gap-2 > *, +.ease-masonry-3.ease-gap-2 > *, +.ease-masonry-4.ease-gap-2 > * { + margin-bottom: var(--ease-space-2); +} + +.ease-masonry.ease-gap-3, +.ease-masonry-2.ease-gap-3, +.ease-masonry-3.ease-gap-3, +.ease-masonry-4.ease-gap-3 { + column-gap: var(--ease-space-3); +} + +.ease-masonry.ease-gap-3 > *, +.ease-masonry-2.ease-gap-3 > *, +.ease-masonry-3.ease-gap-3 > *, +.ease-masonry-4.ease-gap-3 > * { + margin-bottom: var(--ease-space-3); +} + +.ease-masonry.ease-gap-6, +.ease-masonry-2.ease-gap-6, +.ease-masonry-3.ease-gap-6, +.ease-masonry-4.ease-gap-6 { + column-gap: var(--ease-space-6); +} + +.ease-masonry.ease-gap-6 > *, +.ease-masonry-2.ease-gap-6 > *, +.ease-masonry-3.ease-gap-6 > *, +.ease-masonry-4.ease-gap-6 > * { + margin-bottom: var(--ease-space-6); +} + +.ease-masonry.ease-gap-8, +.ease-masonry-2.ease-gap-8, +.ease-masonry-3.ease-gap-8, +.ease-masonry-4.ease-gap-8 { + column-gap: var(--ease-space-8); +} + +.ease-masonry.ease-gap-8 > *, +.ease-masonry-2.ease-gap-8 > *, +.ease-masonry-3.ease-gap-8 > *, +.ease-masonry-4.ease-gap-8 > * { + margin-bottom: var(--ease-space-8); +} + +/* ──────────────────────────────────────────────────────────── + MASONRY IMAGE SUPPORT + – Ensure images are responsive within masonry columns + ──────────────────────────────────────────────────────────── */ + +.ease-masonry img, +.ease-masonry-2 img, +.ease-masonry-3 img, +.ease-masonry-4 img { + width: 100%; + height: auto; + display: block; +} + +/* ──────────────────────────────────────────────────────────── + ACCESSIBILITY: REDUCED MOTION SUPPORT + – Respect user preferences for animations/transitions + ──────────────────────────────────────────────────────────── */ + +@media (prefers-reduced-motion: reduce) { + .ease-masonry > *, + .ease-masonry-2 > *, + .ease-masonry-3 > *, + .ease-masonry-4 > * { + transition: none !important; + } +} + +/* ──────────────────────────────────────────────────────────── + MASONRY + CARD INTEGRATION + – Seamless integration with ease-card utilities + ──────────────────────────────────────────────────────────── */ + +.ease-masonry .ease-card, +.ease-masonry-2 .ease-card, +.ease-masonry-3 .ease-card, +.ease-masonry-4 .ease-card { + margin-bottom: inherit; +} diff --git a/docs/masonry-layout-guide.md b/docs/masonry-layout-guide.md new file mode 100644 index 00000000..ac8a2141 --- /dev/null +++ b/docs/masonry-layout-guide.md @@ -0,0 +1,422 @@ +# Masonry Layout Utilities + +Create flexible Pinterest-style masonry grids with EaseMotion CSS. Perfect for portfolios, image galleries, blog cards, and responsive content layouts. + +## Overview + +The masonry utilities use CSS columns to create natural, flowing layouts where items of varying heights fit together seamlessly. This approach is: + +- **Lightweight**: Pure CSS, no JavaScript required +- **Responsive**: Mobile-first breakpoints built-in +- **Accessible**: Respects reduced motion preferences +- **Composable**: Works with existing EaseMotion utilities like `ease-card` and `ease-gap-*` + +## Base Masonry Class + +The base `ease-masonry` class sets up default masonry behavior with 2 columns on desktop, collapsing to 1 column on mobile. + +```html +
+
Item 1
+
Item 2
+
Item 3
+
Item 4
+
+``` + +### Features +- Default 2-column layout on desktop +- 1 column on mobile (< 640px) +- 4px gap between items (configurable) +- All child elements prevent column breaks + +--- + +## 2-Column Layout + +Use `ease-masonry-2` for a dedicated 2-column grid. + +```html +
+ Portfolio item 1 + Portfolio item 2 + Portfolio item 3 + Portfolio item 4 +
+``` + +### Responsive Behavior +| Device | Columns | +|--------|---------| +| Mobile (< 640px) | 1 | +| Tablet+ (≥ 640px) | 2 | + +--- + +## 3-Column Layout + +Use `ease-masonry-3` for progressive 3-column layouts with intermediate tablet support. + +```html +
+
+

Blog Post 1

+

January 15, 2024

+
+

Article summary and preview text...

+
+
+ +
+``` + +### Responsive Behavior +| Device | Columns | +|--------|---------| +| Mobile (< 640px) | 1 | +| Tablet (640–1023px) | 2 | +| Desktop (≥ 1024px) | 3 | + +--- + +## 4-Column Layout + +Use `ease-masonry-4` for dense, full-featured grids with maximum responsiveness. + +```html +
+ Gallery item 1 + Gallery item 2 + Gallery item 3 + +
+``` + +### Responsive Behavior +| Device | Columns | +|--------|---------| +| Mobile (< 640px) | 1 | +| Tablet (640–1023px) | 2 | +| Small Desktop (1024–1279px) | 3 | +| Large Desktop (≥ 1280px) | 4 | + +--- + +## Customizing Gaps + +Combine masonry classes with `ease-gap-*` utilities to adjust spacing. + +### Available Gap Sizes + +```html + +
...
+ + +
...
+ + +
...
+ + +
...
+ + +
...
+``` + +--- + +## Integration Examples + +### With Cards + +```html +
+
+
+ Featured +
+

Project Title

+

By Author Name

+
+

Brief description of the project or article...

+
+ +
+ +
+``` + +### With Images + +```html +
+
+ Gallery image 1 +
Image caption
+
+ +
+``` + +### With Custom Content + +```html +
+
+
+

Testimonial

+

"Amazing product and service!"

+
— Jane Doe
+
+
+ +
+``` + +--- + +## Accessibility + +### Reduced Motion Support + +All masonry layouts automatically respect the `prefers-reduced-motion` media query. Animations and transitions are disabled for users who prefer minimal motion. + +```css +/* Automatically applied if user prefers reduced motion */ +@media (prefers-reduced-motion: reduce) { + .ease-masonry > *, + .ease-masonry-2 > *, + .ease-masonry-3 > *, + .ease-masonry-4 > * { + transition: none !important; + } +} +``` + +### Semantic HTML + +Always use semantic HTML within masonry items: + +```html + +
+
+

Article Title

+

Content...

+
+
+ + +
+
+
Article Title
+
Content...
+
+
+``` + +--- + +## Browser Support + +The masonry utilities use CSS Columns, which is supported in all modern browsers: + +| Browser | Version | +|---------|---------| +| Chrome | 50+ | +| Firefox | 52+ | +| Safari | 9+ | +| Edge | 12+ | +| Opera | 37+ | + +For older browsers, content will render as a single column (graceful degradation). + +--- + +## Performance Tips + +1. **Limit column count**: More columns = more layout calculations + - Use `ease-masonry-2` or `ease-masonry-3` for best performance + - Avoid `ease-masonry-4` on mobile or with 100+ items + +2. **Optimize images**: Use responsive images with `srcset` for better performance + ```html + Description + ``` + +3. **Batch rendering**: If adding items dynamically, batch DOM updates + ```javascript + const fragment = document.createDocumentFragment(); + items.forEach(item => fragment.appendChild(item)); + container.appendChild(fragment); + ``` + +--- + +## Common Use Cases + +### Portfolio Grid +```html +
+

My Work

+
+ +
+
+``` + +### Blog Feed +```html +
+

Latest Articles

+
+ +
+
+``` + +### Image Gallery +```html +
+

Photo Collection

+
+ +
+
+``` + +### Testimonial Wall +```html +
+

Client Testimonials

+
+ +
+
+``` + +--- + +## Troubleshooting + +### Items Not Breaking Properly + +**Problem**: Long items span multiple columns unexpectedly. + +**Solution**: Ensure parent container has sufficient width or use `ease-masonry-2` for simpler layouts. + +### Images Distorting + +**Problem**: Images are stretching or shrinking unevenly. + +**Solution**: The masonry utilities set `width: 100%` and `height: auto` on images. Check your image aspect ratio or use `object-fit`: + +```css +img { + object-fit: cover; + aspect-ratio: 1 / 1; /* or your desired ratio */ +} +``` + +### Mobile Layout Issues + +**Problem**: Content appears in wrong column order on mobile. + +**Solution**: Columns naturally reflow to single column on mobile. If items appear out of order, ensure DOM order matches visual order. + +--- + +## Migration Guide + +### From CSS Grid +If migrating from `ease-grid` utilities: + +**Before** (Fixed columns): +```html +
+ +
+``` + +**After** (Masonry): +```html +
+ +
+``` + +### From Flexbox +If migrating from `ease-flex` utilities: + +**Before** (Complex wrapping): +```html +
+ +
+``` + +**After** (Masonry): +```html +
+ +
+``` + +--- + +## Advanced Techniques + +### Custom Column Counts + +Use CSS custom properties to create utility variants: + +```css +.ease-masonry-5 { + columns: 5; + column-gap: var(--ease-space-4); +} + +@media (max-width: 1535px) { + .ease-masonry-5 { + columns: 4; + } +} +``` + +### Varying Item Heights + +Masonry naturally handles items of different heights: + +```html +
+
+

Short Item

+
+
+

Longer Item

+

With more content that naturally flows...

+
+
+

Medium Item

+

Somewhere in between

+
+
+``` + +--- + +## Related Utilities + +- `ease-grid-*`: Fixed-column grids for more structured layouts +- `ease-flex`: Flexible layouts with wrapping +- `ease-gap-*`: Spacing between flex/grid items +- `ease-card`: Card component for content containers +- `ease-container`: Max-width constraint wrapper diff --git a/easemotion.css b/easemotion.css index 25ec4093..2e52c22e 100644 --- a/easemotion.css +++ b/easemotion.css @@ -22,6 +22,7 @@ @import "./components/buttons.css"; @import "./components/cards.css"; @import "./components/navbar.css"; +@import "./components/masonry.css"; /* Accessibility: Respect user's reduced motion preference */ @media (prefers-reduced-motion: reduce) { diff --git a/examples/masonry-layouts.html b/examples/masonry-layouts.html new file mode 100644 index 00000000..dbf0eb9f --- /dev/null +++ b/examples/masonry-layouts.html @@ -0,0 +1,546 @@ + + + + + + Masonry Layouts — EaseMotion CSS + + + + + + + + + + + + + + + + + + + + +
+
+
+ +

+ Masonry Layouts +

+

+ Create responsive Pinterest-style grids for portfolios, galleries, and content walls with pure CSS. +

+
+
+
+ +
+ + +
+
+ +

Portfolio Masonry (3 Columns)

+

+ Responsive 3-column masonry layout for portfolio projects. Adapts to 2 columns on tablet and 1 column on mobile. +

+ +
// HTML Structure
+
<div class="ease-masonry-3 ease-gap-4">
+  <article class="ease-card ease-card-shadow ease-card-hover">
+    <!-- Portfolio item -->
+  </article>
+  <!-- More items -->
+</div>
+ +
+
+
+ Project 1 +
+

Web Redesign

+

2024

+
+

Modern responsive website redesign for tech startup with focus on performance and accessibility.

+
+ +
+ +
+
+ Project 2 +
+

Mobile App Design

+

2024

+
+

Complete UI/UX design system for fitness tracking application with custom animations and micro-interactions.

+
+ +
+ +
+
+ Project 3 +
+

Brand Identity

+

2023

+
+

Complete brand identity system including logo, color palette, and design guidelines.

+
+ +
+ +
+
+ Project 4 +
+

E-commerce Platform

+

2023

+
+

Full-featured e-commerce platform with product filtering, cart, and checkout experience.

+
+ +
+ +
+
+ Project 5 +
+

Dashboard Design

+

2023

+
+

Analytics dashboard with real-time data visualization and interactive charts.

+
+ +
+ +
+
+ Project 6 +
+

SaaS Landing

+

2023

+
+

High-converting SaaS landing page with testimonials and pricing comparison.

+
+ +
+
+
+
+ +
+ + +
+
+ +

Image Gallery Masonry (4 Columns)

+

+ Dense 4-column image gallery that adapts responsively: 3 columns on small desktop, 2 on tablet, 1 on mobile. +

+ +
// Gallery with ease-masonry-4
+
+
+
Image 1
+
Mountain Valley
+
+
+
Image 2
+
Forest Green
+
+
+
Image 3
+
Sunset Gold
+
+
+
Image 4
+
Ocean Blue
+
+
+
Image 5
+
Pink Blossom
+
+
+
Image 6
+
Purple Dreams
+
+
+
Image 7
+
Cyan Sky
+
+
+
Image 8
+
Emerald Leaf
+
+
+
+
+ +
+ + +
+
+ +

Blog Card Masonry (3 Columns)

+

+ Blog articles in a masonry layout with varying content lengths. Each card adapts naturally. +

+ +
// Blog posts with ease-masonry-3
+
+
+
+ Tutorial +
+

Getting Started with Masonry

+

Published on Jan 15, 2024

+
+

Learn how to create responsive Pinterest-style layouts using CSS columns. This comprehensive guide covers all masonry utilities and responsive breakpoints.

+
+ +
+ +
+
+ Announcement +
+

EaseMotion v2.0 Released

+

Published on Jan 10, 2024

+
+

New masonry layout utilities, improved accessibility, and performance enhancements. Download the latest version and start building beautiful layouts.

+

Features include responsive columns, gap variants, and seamless card integration.

+
+ +
+ +
+
+ Tip +
+

Optimizing Masonry for Performance

+

Published on Jan 5, 2024

+
+

Pro tips for getting the best performance from masonry layouts. Learn about optimal column counts, image optimization, and rendering techniques.

+
+ +
+ +
+
+ Case Study +
+

Portfolio Redesign with Masonry

+

Published on Dec 28, 2023

+
+

See how one designer increased engagement by 340% using masonry layouts. Includes before/after screenshots and detailed breakdown of design decisions.

+

Learn from real-world implementation and best practices.

+
+ +
+ +
+
+ Guide +
+

Responsive Design Patterns

+

Published on Dec 20, 2023

+
+

Comprehensive guide to responsive design patterns with masonry. Perfect for designers and developers of all levels.

+
+ +
+ +
+
+ Video +
+

Masonry Layouts Explained (8 min video)

+

Published on Dec 15, 2023

+
+

Quick video walkthrough of masonry layout utilities. Perfect for getting started quickly and understanding responsive behavior.

+
+ +
+
+
+
+ +
+ + +
+
+ +

Responsive Behavior

+

+ All masonry layouts automatically adjust column count based on viewport width. Resize your browser to see the changes. +

+ +
+
+

ease-masonry-2

+
+

Mobile: 1 column

+

Tablet+: 2 columns

+

Best for: Two-column layouts, image pairs, side-by-side content.

+
+
+ +
+

ease-masonry-3

+
+

Mobile: 1 column

+

Tablet: 2 columns

+

Desktop: 3 columns

+

Best for: Portfolios, galleries, blogs.

+
+
+ +
+

ease-masonry-4

+
+

Mobile: 1 column

+

Tablet: 2 columns

+

Sm Desktop: 3 columns

+

Lg Desktop: 4 columns

+

Best for: Dense galleries, image walls.

+
+
+
+
+
+ +
+ + + + + + + + + diff --git a/scripts/validate-masonry.py b/scripts/validate-masonry.py new file mode 100644 index 00000000..e6ad343c --- /dev/null +++ b/scripts/validate-masonry.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python +"""Validate masonry utilities implementation.""" + +from pathlib import Path + +def validate(): + errors = [] + + # Test 1: Check CSS file syntax + css_file = Path('components/masonry.css') + if not css_file.exists(): + errors.append('❌ masonry.css not found') + else: + css_content = css_file.read_text() + brace_count = css_content.count('{') - css_content.count('}') + if brace_count == 0: + print('✓ CSS Brace Balance: OK') + else: + errors.append(f'❌ CSS Brace Balance: {brace_count}') + + # Test 2: Check if masonry is imported in main bundle + main_css = Path('easemotion.css').read_text() + if '@import "./components/masonry.css"' in main_css: + print('✓ Masonry imported in bundle: OK') + else: + errors.append('❌ Masonry not imported in easemotion.css') + + # Test 3: Check doc file + doc_file = Path('docs/masonry-layout-guide.md') + if doc_file.exists(): + doc_size = len(doc_file.read_text()) + print(f'✓ Documentation file exists: OK ({doc_size} bytes)') + else: + errors.append('❌ masonry-layout-guide.md not found') + + # Test 4: Check demo file + demo_file = Path('examples/masonry-layouts.html') + if demo_file.exists(): + print('✓ Demo file exists: OK') + else: + errors.append('❌ masonry-layouts.html not found') + + # Test 5: Check masonry classes + masonry_classes = ['ease-masonry', 'ease-masonry-2', 'ease-masonry-3', 'ease-masonry-4'] + for cls in masonry_classes: + if f'.{cls}' in css_content: + print(f'✓ Class {cls}: OK') + else: + errors.append(f'❌ Class {cls} not found') + + if errors: + print('\nValidation Errors:') + for error in errors: + print(error) + return False + + print('\n✓✓✓ All validations passed! ✓✓✓') + return True + +if __name__ == '__main__': + validate()