← Back to Learning Path JavaScript • Level 3 • Lesson 8 of 9
Level 3 progress 0% complete

Lesson 8: Grid Animations

Animate grid layouts for smooth, delightful user experiences.

Animating Grid Properties

You can animate grid column and row changes using CSS transitions. Set the transition once, then any grid property changes will animate smoothly.

What Animates gridTemplateColumns, gridTemplateRows, gap, and gridTemplateAreas can all be animated.

Basic Grid Animation

Animate column count changes:

const container = document.getElementById('grid');

// Enable transitions
container.style.transition = 'grid-template-columns 0.3s ease';

// Now changes animate!
function toggleColumns() {
  const current = container.style.gridTemplateColumns;
  
  if (current.includes('3')) {
    container.style.gridTemplateColumns = 'repeat(4, 1fr)';
  } else {
    container.style.gridTemplateColumns = 'repeat(3, 1fr)';
  }
}

// Call this on button click - it animates!
toggleColumns();

Animating Gap

Smooth gap transitions:

container.style.transition = 'gap 0.3s ease';

// Gap changes smoothly
function setCompact() {
  container.style.gap = '0.5rem';
}

function setSpacious() {
  container.style.gap = '2rem';
}

Multiple Properties

Animate several grid properties at once:

container.style.transition = 'all 0.4s ease-in-out';

function setMobileLayout() {
  container.style.gridTemplateColumns = '1fr';
  container.style.gap = '0.5rem';
}

function setDesktopLayout() {
  container.style.gridTemplateColumns = 'repeat(4, 1fr)';
  container.style.gap = '2rem';
}

// Both properties animate together!
Performance Note Grid animations can be intensive. Use will-change for better performance on complex grids, but remove it after the animation completes.

Staggered Item Animations

Animate grid items appearing one by one:

function animateIn(items) {
  const container = document.getElementById('grid');
  
  items.forEach((item, index) => {
    const div = document.createElement('div');
    div.textContent = item.name;
    
    // Start invisible and scaled down
    div.style.opacity = '0';
    div.style.transform = 'scale(0.8)';
    div.style.transition = 'opacity 0.3s ease, transform 0.3s ease';
    
    container.appendChild(div);
    
    // Animate in with delay
    setTimeout(() => {
      div.style.opacity = '1';
      div.style.transform = 'scale(1)';
    }, index * 50); // 50ms stagger
  });
}

React Animated Grid

Animate layout changes in React:

function AnimatedGrid({ items }) {
  const [columns, setColumns] = useState(3);
  
  const gridStyle = {
    display: 'grid',
    gridTemplateColumns: `repeat(${columns}, 1fr)`,
    gap: '1rem',
    transition: 'grid-template-columns 0.3s ease'
  };
  
  return (
    <>
      <button onClick={() => setColumns(columns === 3 ? 4 : 3)}>
        Toggle Columns
      </button>
      
      <div style={gridStyle}>
        {items.map((item, i) => (
          <div 
            key={item.id}
            style={{
              transition: 'all 0.3s ease',
              transitionDelay: `${i * 0.05}s`
            }}
          >
            {item.name}
          </div>
        ))}
      </div>
    </>
  );
}

Expanding Grid Item

Click to expand an item to full width:

function setupExpandable() {
  const items = document.querySelectorAll('.grid-item');
  
  items.forEach(item => {
    item.style.transition = 'grid-column 0.3s ease';
    
    item.addEventListener('click', () => {
      const isExpanded = item.style.gridColumn === '1 / -1';
      
      if (isExpanded) {
        item.style.gridColumn = 'span 1';
      } else {
        item.style.gridColumn = '1 / -1'; // Full width
      }
    });
  });
}

Smooth Layout Reordering

Change grid order with smooth transitions:

function reorderGrid(newOrder) {
  const container = document.getElementById('grid');
  const items = Array.from(container.children);
  
  // Enable transitions
  items.forEach(item => {
    item.style.transition = 'all 0.3s ease';
  });
  
  // Reorder based on new order array
  newOrder.forEach((index, position) => {
    items[index].style.order = position;
  });
}

Entrance Animation

Grid fades in when page loads:

function animateGridIn() {
  const container = document.getElementById('grid');
  
  container.style.opacity = '0';
  container.style.transform = 'translateY(20px)';
  container.style.transition = 'opacity 0.5s ease, transform 0.5s ease';
  
  // Trigger animation
  setTimeout(() => {
    container.style.opacity = '1';
    container.style.transform = 'translateY(0)';
  }, 100);
}

// Call on page load
window.addEventListener('DOMContentLoaded', animateGridIn);
Best Practices
  • Keep animations under 400ms for responsiveness
  • Use ease-in-out for natural motion
  • Test on slower devices
  • Provide reduced-motion alternatives

Respecting Reduced Motion

Disable animations for users who prefer reduced motion:

const prefersReducedMotion = window.matchMedia(
  '(prefers-reduced-motion: reduce)'
).matches;

if (!prefersReducedMotion) {
  container.style.transition = 'all 0.3s ease';
} else {
  container.style.transition = 'none';
}

Combining with Transform

Use transform for performant animations:

items.forEach(item => {
  item.style.transition = 'transform 0.3s ease, opacity 0.3s ease';
  
  item.addEventListener('mouseenter', () => {
    item.style.transform = 'scale(1.05)';
  });
  
  item.addEventListener('mouseleave', () => {
    item.style.transform = 'scale(1)';
  });
});

Practice Challenge

Create a grid that smoothly animates between 2, 3, and 4 columns with buttons. Add staggered item entrance animations.

Quick Check

Test your knowledge before moving to the next lesson. All 3 questions must be correct to continue.

1. How do you enable grid animations?

2. What should you check before enabling animations?

3. What is a good duration for grid animations?

← Previous Lesson