Skip to main content
April 1, 2026Dan Rodney/13 min read

Animating the Panorama & Making the Layout Responsive

Master CSS Animations and Responsive Design Techniques

Prerequisites Required

This tutorial builds on previous exercises 1A-1B. If you haven't completed them, you'll need to set up the Hawaii project folder from the provided starter files before proceeding.

Exercise Preview

preview pano

Exercise Overview

In this comprehensive exercise, you'll master two critical modern web development techniques. First, you'll create a smooth CSS3 animation that makes the panorama background image pan seamlessly back and forth, bringing static imagery to life. Then you'll implement responsive design principles to ensure your layout adapts flawlessly across all device sizes—from desktop monitors to mobile phones. These skills are essential for creating engaging, accessible web experiences in today's multi-device landscape.

  1. If you completed the previous exercise, style.css should still be open in your code editor, and you can skip the following sidebar. If you closed style.css, re-open it now. We strongly recommend completing the previous exercises (1A–1B) before starting this one, as they provide essential foundation code. If you haven't finished them, follow the setup instructions in the sidebar below.

    Exercise Roadmap

    1

    Animate Panorama Background

    Create CSS keyframes to make the background image pan smoothly from left to right

    2

    Optimize for Mobile

    Disable fixed backgrounds on mobile devices to prevent display issues

    3

    Implement Responsive Design

    Use CSS media queries to adapt layout and typography across different screen sizes

If You Did Not Do the Previous Exercises (1A–1B)

  1. Close any files you may have open in your code editor.
  2. On the Desktop, navigate to Class Files > Responsive CSS3 Scrolling Effects.
  3. Delete the Hawaii folder if it exists.
  4. Duplicate the Hawaii YouTube Done folder.
  5. Rename the duplicate to Hawaii and open it in your preferred code editor.

Animating the Panorama Background

Currently, we have an exceptionally wide panoramic image in our page's panorama segment, but visitors can only see a small portion of this stunning vista. This limitation wastes the visual impact of our carefully selected imagery. We'll solve this by creating a smooth CSS animation that slowly scrolls the background from left to right, revealing the full breadth of the panoramic view.

Unlike CSS transitions, which work by changing between two distinct states (like hover effects), this animation requires a more sophisticated approach. We need CSS keyframe animation, which allows us to define multiple points along an animation timeline and create smooth, continuous motion.

  1. Scroll to the bottom of style.css and add the following keyframe declaration at the very end of the document:

    @keyframes moving-bg {
    
    }
  2. Define the animation's starting and ending keyframes by adding this code inside the brackets:

    @keyframes moving-bg {
       0% {
          background-position: 0;
       }
       100% {
          background-position: 100% 0;
       }
    }

    These positions use X, Y coordinate syntax to control background positioning. The 0% keyframe sets our starting position at the image's left edge (X-position: 0). The 100% keyframe moves to the far right (X-position: 100%), while maintaining the same vertical position (Y-position: 0). This creates a smooth horizontal panning effect that showcases the entire width of our panoramic background image without any vertical movement that might disorient users.

  3. Locate the .feature-wrap.panorama class (around line 98) and apply the animation by adding this property:

    .feature-wrap.panorama {
       padding: 10% 0;
       background-image: url(../img/panorama.jpg);
       animation: moving-bg 20s linear infinite alternate;
    }
  4. Let's break down each component of this animation declaration to understand how it creates the desired effect:

    • moving-bg references the keyframe animation we just defined.
    • 20s sets a 20-second duration—long enough to feel smooth and natural, not jarring or rushed.
    • linear applies linear easing, ensuring consistent movement speed throughout the animation (no acceleration or deceleration).
    • infinite makes the animation repeat continuously, creating an endless loop that keeps the page dynamic.
    • alternate reverses the animation direction on each iteration (left-to-right, then right-to-left), preventing jarring jumps back to the start position.
  5. Save the file and preview index.html in your browser. The panoramic photo behind the Mt. Haleakala text should now be smoothly panning back and forth, creating an immersive visual experience.
  6. Return to your code editor to add browser compatibility improvements.
  7. Modern web development requires supporting a range of browsers, including older versions that need vendor prefixes. Copy the animation property and paste it directly above the original:

    .feature-wrap.panorama {
       padding: 10% 0;
       background-image: url(../img/panorama.jpg);
       animation: moving-bg 20s linear infinite alternate;
       animation: moving-bg 20s linear infinite alternate;
    }
  8. Add the -webkit vendor prefix to the first declaration:

    -webkit-animation: moving-bg 20s linear infinite alternate;
    animation: moving-bg 20s linear infinite alternate;

    NOTE: The -webkit prefix ensures compatibility with older versions of Safari, Chrome, and other WebKit-based browsers. While browser support for unprefixed animations is excellent in 2026, including prefixes is still considered a best practice for enterprise applications that may need to support legacy systems. For current browser support data, always consult caniuse.com/#feat=css-animation

  9. The keyframes we created work with the standard animation property, but we also need vendor-prefixed keyframes for the -webkit-animation property. Scroll to the bottom of style.css.
  10. Copy the entire @keyframes block of code.
  11. Paste it directly below the original. You should now have two identical copies of this code block:

    @keyframes moving-bg {
       0% {
          background-position: 0;
       }
       100% {
          background-position: 100% 0;
       }
    }
  12. Add the -webkit- prefix to the first keyframes declaration:

    @-webkit-keyframes moving-bg {

    Code Omitted To Save Space

    }
    @keyframes moving-bg {

    Code Omitted To Save Space

    }
  13. Save the file and reload your browser. Take a moment to appreciate the smooth, professional animation you've created entirely with CSS3. This technique demonstrates the power of modern CSS for creating engaging user experiences without JavaScript dependencies.

CSS Animation Properties

Duration: 20s

The animation completes one full cycle in 20 seconds, providing smooth, subtle movement that isn't distracting.

Timing: Linear

Linear easing ensures consistent speed throughout the animation without acceleration or deceleration effects.

Direction: Alternate

The alternate direction creates seamless back-and-forth panning without jarring resets.

Browser Compatibility

Always include -webkit vendor prefixes for animations to support older browsers. Check caniuse.com for current browser support statistics.

Disabling the Fixed Background Images on Mobile Devices

In the previous exercise, we implemented fixed background positioning to create an elegant parallax scrolling effect on desktop browsers. However, this technique presents significant challenges on mobile devices. iOS Safari, in particular, handles fixed backgrounds poorly—often sizing them incorrectly, causing performance issues, or disabling the effect entirely. Rather than leaving mobile users with a broken experience, we'll implement a responsive solution that detects mobile devices and provides an optimized alternative.

  1. Return to style.css in your code editor.
  2. We'll use CSS media queries to create device-specific styling. Above the first set of keyframes, add this media query:

    @media (max-width: 600px) {
    
    }
    @-webkit-keyframes moving-bg {

    NOTE: This CSS media query creates a conditional rule set that only applies when the viewport width is 600 pixels or less. This covers the vast majority of mobile phones in portrait orientation. Any styles inside these brackets will override previous declarations when the condition is met, giving us precise control over the mobile experience.

  3. Add the background override rule inside the media query:

    @media (max-width: 600px) {
       .feature-wrap.photo {
          background-attachment: scroll;
       }
    }

    NOTE: CSS follows the cascade principle—when multiple rules have equal specificity, the last one wins. Since this rule appears later in our stylesheet than the original background-attachment: fixed; declaration, it successfully overrides the fixed positioning on smaller screens, replacing it with standard scrolling behavior that works reliably across all mobile browsers.

  4. Save the file and open it in Chrome (we'll use Chrome's developer tools for testing).
  5. Resize the browser window to be wide (more than 600 pixels) and scroll to verify that the photo backgrounds remain fixed to the viewport—this is the desktop experience we want to preserve.
  6. Now resize the browser to be narrower than 600 pixels and scroll again. Notice how the backgrounds now scroll naturally with the page content—this mimics the mobile experience and eliminates the problematic fixed positioning.
  7. Maximize the window to return to desktop view.
  8. To access Chrome's device emulation tools, Ctrl+click (Mac) or Right-click (Windows) on the page and select Inspect from the context menu.
  9. In the DevTools panel, locate and click the Toggle device toolbar button devtools device toolbar icon at the top-left:

    toggle device toolbar

  10. In the device emulation toolbar, select iPad Pro from the device dropdown menu:

    device toolbar choose ipad pro

  11. Reload the page to ensure proper rendering in the emulated environment.
  12. Scroll through the page and observe that the background images still appear fixed. This reveals a limitation of our width-based media query approach. While Chrome's emulator shows the effect working, real iOS Safari would render these backgrounds incorrectly, creating a poor user experience.

    The iPad Pro's resolution (1366px in landscape mode) exceeds our 600px media query threshold, so it doesn't receive the mobile-optimized styling. We could increase the media query breakpoint, but that would disable the parallax effect for many desktop users who can properly view it—clearly not an ideal solution.

    This highlights a fundamental limitation of CSS: it can detect screen size but cannot distinguish between device types. A 1366px desktop monitor and a 1366px iPad Pro look identical to CSS, despite having vastly different rendering capabilities. To solve this, we need JavaScript-based device detection.

  13. Keep the emulated view open for testing our upcoming changes.
  14. Switch back to your code editor and open Hawaii > snippets > mobile-detection.html
  15. Select and copy all the JavaScript code from this file.
  16. Close mobile-detection.html and return to index.html.
  17. Locate the <body> tag (around line 14).
  18. Paste the JavaScript code immediately after the opening body tag:

    <body>
    <script>
       var isMobile = navigator.userAgent.match(/(iPhone|iPod|iPad|Android)/);
       if( isMobile!= null ) {
          document.body.className += ' ' + 'mobile';
       }
    </script>

    This script performs user agent detection by examining the browser's identification string for mobile device keywords. When it detects iPhone, iPod, iPad, or Android devices, it dynamically adds a mobile class to the document body, giving us a reliable CSS hook for mobile-specific styling.

    Technical Deep Dive: Every browser sends a user agent string to websites, identifying itself and the device it's running on. Our JavaScript searches this string for specific mobile device identifiers. If found, the script modifies the DOM by adding a CSS class, which we can then target with our stylesheets. This approach provides more reliable device detection than viewport width alone, though it requires JavaScript to be enabled.

  19. Save index.html and return to style.css.
  20. Find the .feature-wrap.photo rule (around line 88) and add this mobile-specific override below it:

    .feature-wrap.photo {
       background-repeat: no-repeat;
       background-position: center;
       background-size: cover;
       background-attachment: fixed;
    }
    .mobile .feature-wrap.photo {
       background-attachment: scroll;
    }

    NOTE: This selector targets elements with the feature-wrap photo classes, but only when they're inside an element with the mobile class (which JavaScript adds to the body tag on mobile devices). This creates a failsafe system: JavaScript handles tablets and devices that CSS can't properly detect, while the media query handles devices with JavaScript disabled.

  21. Return to Chrome and reload the page in iPad Pro emulation.

    NOTE: While Chrome doesn't use the actual iOS Safari rendering engine, the device emulator does spoof the user agent string, allowing our JavaScript to properly detect the "iPad Pro" and apply mobile-optimized styling.

  22. Scroll through the page and verify that background images now scroll with the content, eliminating the problematic fixed positioning on this tablet device.
  23. Close DevTools by clicking the X in the top-right corner of the panel.
  24. Reload the page at full desktop size to ensure normal functionality is preserved.
  25. Test the responsive behavior by scrolling in desktop view—if the window exceeds 600px width, the parallax effect should work perfectly. We've successfully created a robust solution that delivers the best possible experience on every device type.

Fixed Background Attachment on Mobile

Pros
Creates engaging parallax scrolling effects on desktop
Enhances visual depth and user experience
Works reliably in modern desktop browsers
Cons
Causes display issues on iOS Safari
Images may be sized incorrectly on tablets
Can impact scrolling performance on mobile devices

CSS vs JavaScript Detection Methods

FeatureCSS Media QueriesJavaScript Detection
Detection MethodScreen width onlyUser agent string
Device AccuracyLimitedPrecise device detection
Tablet HandlingiPad Pro too large at 1366pxDetects all iOS devices
Fallback SupportAlways worksRequires JavaScript enabled
Recommended: Use both methods together for comprehensive mobile optimization

Creating Responsive Layouts with CSS Media Queries

While our page functions well across devices, the typography needs refinement for optimal mobile viewing. Large headlines that look impressive on desktop monitors can overwhelm small screens, covering too much of our carefully chosen imagery and creating poor visual hierarchy. We'll implement a comprehensive responsive typography system using CSS media queries, ensuring readable, proportionate text at every screen size.

  1. Return to style.css in your code editor.
  2. Above the existing (max-width: 600px) media query, add this new breakpoint for tablet-sized screens:

    @media (max-width: 1024px) {
    
    }
    @media (max-width: 600px) {
  3. Add responsive typography rules for the medium breakpoint:

    @media (max-width: 1024px) {
       .feature-wrap .text {
          font-size: 2em;
       }
    }
  4. Save the file and test the changes by resizing your browser. Notice how the text in photo highlight sections scales down appropriately on screens narrower than 1024 pixels, while maintaining full size on larger displays.
  5. While testing at the smaller size, observe the panorama animation. The reduced viewport size limits the panning distance, making the animation less dramatic. Let's optimize the panorama display for this breakpoint.
  6. Add panorama-specific styling to the 1024px media query:

    @media (max-width: 1024px) {
       .feature-wrap .text {
          font-size: 2em;
       }
       .feature-wrap.panorama {
          padding: 15% 0;
       }
    }
  7. Save and test the improved panorama sizing at medium screen widths.
  8. The zooming YouTube video effect, while impressive on large screens, becomes problematic at smaller sizes. When the video starts at 40% width on a narrow viewport, it appears uncomfortably small and the zoom transition feels jarring. Let's disable the zoom effect for medium and small screens.
  9. Add video optimization rules to the media query:

    .feature-wrap.panorama {
          padding: 15% 0;
       }
       .zoom {
          width: 100%;
       }
    }
  10. Test the changes by resizing your browser below 1024px width. The video should now display at full width without the zoom effect. However, you'll notice spacing issues that need correction.
  11. Add proper margins to the video container:

    .zoom {
       width: 100%;
       margin: 0 25px 0;
    }
  12. Ensure consistent spacing during hover states by targeting both normal and hover states (note the comma after the first selector):

    .zoom, .zoom:hover {
       width: 100%;
       margin: 0 25px 0;
    }
  13. Save and test the video behavior at narrow widths. The spacing should remain consistent whether hovering or not.
  14. Now we'll create an intermediate breakpoint for refined control over the responsive design. Add a new media query before the 600px breakpoint:
  15. Insert this media query between the existing ones:

    @media (max-width: 850px) {
    
    }
    @media (max-width: 600px) {

    NOTE: We're using a desktop-first approach for this project because desktop users experience the full range of effects (animations, parallax scrolling, etc.). This methodology starts with full desktop styling and progressively adapts downward using max-width media queries. While mobile-first approaches are common and valid, desktop-first makes sense here given our effect-heavy design that's optimized for larger screens.

  16. Add typography and spacing optimizations for the 850px breakpoint:

    @media (max-width: 850px) {
       .feature-wrap .text {
          font-size: 1.5em;
          margin: 0 5%;
       }
    }
  17. Save and test the subtle improvements at this breakpoint—notice the refined text sizing and improved margins that better utilize the available space.
  18. The panorama needs further optimization at this screen size. Add increased padding to make the image more prominent:

    @media (max-width: 850px) {
       .feature-wrap .text {
          font-size: 1.5em;
          margin: 0 5%;
       }
       .feature-wrap.panorama {
          padding: 20% 0;
       }
    }
  19. The photo stack layout also needs refinement at this size. Add centered, optimized styling for the stacked photo sections:

    .feature-wrap.panorama {
          padding: 20% 0;
       }
       .feature-wrap.stack .text {
          width: auto;
          margin: 0 5%;
          font-size: 3.5em;
          text-align: center;
       }
    }
  20. Save and test the changes. You may notice that the photo stack text isn't behaving as expected—this is a CSS specificity issue that we need to resolve.
  21. Fix the specificity problem by targeting all the specific text positioning classes that were defined earlier in the stylesheet:

    .feature-wrap.stack .text, .feature-wrap.stack .text.right, .feature-wrap.stack .text.left {
       width: auto;
       margin: 0 5%;
       font-size: 3.5em;
       text-align: center;
    }
  22. Save and test the complete responsive behavior by resizing your browser through all the breakpoints. Notice how the layout gracefully adapts from desktop (1024px+) to tablet (850px-1024px) to mobile (600px-850px) to small mobile (under 600px), with each providing an optimized experience for its screen size.

Media Query Breakpoints

1024px - Tablet landscape
1,024
850px - Tablet portrait
850
600px - Mobile devices
600

Responsive Design Implementation

1

Desktop-First Approach

Start with full desktop styles, then use max-width media queries to progressively simplify for smaller screens

2

Typography Scaling

Reduce font sizes at each breakpoint: 2em at 1024px, 1.5em at 850px for optimal readability

3

Layout Adjustments

Modify padding, margins, and element positioning to optimize for touch interfaces and smaller screens

Key Takeaways

1CSS keyframes animations require both standard and -webkit prefixed versions for broader browser compatibility
2Fixed background attachments create visual issues on mobile devices and should be disabled using CSS media queries and JavaScript detection
3Desktop-first responsive design uses max-width media queries starting from larger breakpoints and working down to mobile sizes
4JavaScript user agent detection provides more accurate mobile device identification than CSS media queries alone
5Multiple media query breakpoints (1024px, 850px, 600px) ensure optimal layouts across all device sizes
6CSS specificity rules determine which styles apply when multiple selectors target the same element
7Progressive enhancement techniques allow advanced effects on capable devices while maintaining functionality on all platforms
8Vendor prefixes and fallback methods ensure cross-browser compatibility and graceful degradation

RELATED ARTICLES