Developer News

How to Prepare for CSS-Specific Interview Questions

Css Tricks - Fri, 08/08/2025 - 3:42am

If you landed on this article, chances are you might have a front-end interview coming up, perhaps one with a focus on CSS, or you are in the market to start preparing for CSS-related interviews altogether. Depending on the exact role you are interviewing for, it’s unlikely that you will only be asked questions about CSS. Typically, you will encounter a combination questions covering things like HTML, CSS, and JavaScript.

For this article, we will focus primarily on a set of 10 CSS questions you likely will encounter in front-end interviews, even if they get grouped with HTML or JavaScript. And to be clear, these may or may not be the “best” questions for an interviewer to ask, but what you are likely to see, based on my experience as the founder of frontendlead.com, an all-in-one platform to help front-end engineers prepare for big tech interviews. I have been a software engineer for over 13 years and have been on both ends of hundreds of interviews.

The questions cover different levels of difficulty. To keep things simple, we will start with the “easiest” questions and end with the “hardest” ones.

#Interview QuestionDifficulty1How would you go about building a responsive website?Easy2What are CSS preprocessors, and why are they useful?Easy3How would you make fonts responsive in CSS?Easy4Describe z-index and how stacking context is formed.Medium5What’s the difference between block, inline, and inline-block?Medium6What does * { box-sizing: border-box; } do?Medium7How would you go about making an image responsive in CSS?Medium8How would you make CSS more performant?Hard9What are the pros and cons of CSS in JS vs external CSS import, and which would you choose?Hard10Can you build this layout in CSS?Hard

Before we dive in, I’d like to say that there are many ways to correctly answer the same question. Everything I’m providing here is merely guidance for approaching the types of questions you may face in an interview. The actual questions you encounter may need more elaboration in a particular area or require specific examples that demonstrate your understanding of different concepts.

1. How would you go about building a responsive website? (Easy)

Responsive design is one of the fundamentals you’ll be asked about. Building a responsive website means your layout, images, and typography adapt gracefully to any device or screen size.

The basic tools for responsive design include relative units (such as %, em, and rem), media queries, and fluid layouts. Most interviews expect you to mention a “mobile-first” approach, where your base styles are designed for mobile devices and scaled up for larger screens.

A quick code example using media queries:

/* Main container for your page content, centered and with a max width for larger screens */ .container { max-width: 1200px; /* Prevents content from stretching too wide on large displays */ margin: 0 auto; /* Horizontally center the container */ padding: 16px; /* Adds space inside the container */ } /* Make all images scale with their parent container */ img { max-width: 100%; /* Image will never be wider than its container */ height: auto; /* Keeps the aspect ratio intact */ display: block; /* Removes extra space below images (inline images have baseline spacing) */ } /* Responsive styles for small screens (phones, small tablets) */ @media (max-width: 600px) { .container { padding: 8px; /* Reduce padding to save space on smaller screens */ } /* Example: Stack nav links vertically on small screens nav ul { flex-direction: column; } */ }

You should also mention how you handle navigation and images on mobile devices (such as collapsing navigational menus or leveraging responsive image techniques), as well as how to test layouts using browser Developer Tools.

2. What are CSS preprocessors, and why are they useful? (Easy)

CSS preprocessors, such as SassLess, and Stylus, make writing and maintaining large CSS codebases significantly easier. They add features that aren’t in vanilla CSS, such as mixins, and functions — although those lines are becoming more blurred as CSS ships similar features, such as variablesnesting, and yes, mixins and functions.

Mixins and functions enable you to reuse common patterns and even generate code based on parameters. Here’s an example in Sass:

// Mixin: For a common box shadow you want to reuse @mixin shadow($opacity: 0.12) { box-shadow: 0 2px 8px 0 rgba(24, 39, 75, $opacity); } // Function: Calculate a spacing value for consistent margins and padding @function space($multiplier: 1) { @return $multiplier * 8px; } // Placeholder selector: For base button styles to extend %btn-base { display: inline-block; font-size: $font-size-lg; border-radius: 6px; text-align: center; cursor: pointer; } // Partial import: Example (would be in _variables.scss) // @import 'variables'; // Button styles using everything above .button { @extend %btn-base; // Use base button styles background: $primary; color: #fff; padding: space(1.5) space(3); // Use the custom function for spacing @include shadow(0.15); // Use the mixin for shadow // Nested selector for hover state &:hover { background: lighten($primary, 10%); } // Modifier class (e.g., .button.secondary) &.secondary { background: $secondary; color: #23272f; border: 2px solid $secondary; } // Nested media query (for responsive buttons) @media (max-width: 600px) { padding: space(1) space(2); font-size: 1rem; } }

Preprocessors help keep your codebase DRY (Don’t Repeat Yourself) and make refactoring less painful. While CSS now has native variables (--variable), preprocessors are still widely used for their advanced features.

This is a good opportunity to demonstrate your understanding of modern CSS as well since CSS now supports nesting and work on functions is underway (and indeed are already planned for Chrome 139).

3. How would you make fonts responsive in CSS? (Easy)

Font sizing is a common interview topic because it affects both design and accessibility. Responsive fonts adjust to screen size, ensuring your text remains readable. The classic approach is to use relative units, such as em (scoped to the parent element) and rem (scoped to the root element). Newer CSS features makes this even easier and more flexible with the clamp() function and viewport units (vw and vh). You can also use media queries to step up font sizes for larger screens.

Here are some practical examples:

/* Basic responsive text using rem (scales with root html font size) */ body { font-size: 1rem; /* 1rem is typically 16px, but can be increased for accessibility */ } /* Use rem for headings so they scale with user/browser settings */ h1 { font-size: 2.5rem; /* 2.5 × root font size */ line-height: 1.2; } /* Modern fluid sizing with clamp and viewport units */ h2 { /* Font size is at least 1.5rem, scales with viewport up to 3rem */ font-size: clamp(1.5rem, 4vw, 3rem); } /* Using viewport width units directly */ h3 { font-size: 6vw; /* 6% of viewport width (can get very large/small on extremes) */ } /* Responsive font-size using media queries (manual step-up) */ p { font-size: 1rem; } @media (min-width: 600px) { p { font-size: 1.2rem; } } @media (min-width: 1200px) { p { font-size: 1.4rem; } }
  • rem/em units make your text scale with the root or parent font size, making them more responsive to changes.
  • clamp() lets you set a minimum, fluid, and maximum font size at once (e.g., clamp(1.5rem, 4vw, 3rem) ensures the font size never falls below 1.5rem or exceeds 3rem, scaling smoothly in between).
  • Viewport units (vw, vh) make fonts fluid relative to the screen width or height.
  • Media queries enable fine-tuning of font size for various devices and breakpoints.

Absolute px units are usually avoided for body text, as they don’t scale for users who adjust browser settings for accessibility. Speaking of accessibility, it’s worth calling out that extra consideration needs to go into the possibility of the user zooming into the page.

4. Describe the z-index property and how stacking context is formed. (Medium)

Thez-index property determines which elements appear on top of others, but it only works on elements that have a positioning context, such as position: relative, absolute, or fixed.

stacking context is an environment where stacking and rendering order is controlled. New stacking contexts can be created by elements with specific properties, such as position with a z-index, or CSS properties like opacity less than 1, transform, or filter.

Understanding stacking context is essential for UI components like drop-downs, modals, and tooltips.

Here’s an example demonstrating a stacking context created by a parent element element that contains two children that stack one on top of the other, ordered by z-index:

/* The parent creates a new stacking context by having position and z-index */ .parent { position: relative; /* Triggers a positioning context */ z-index: 2; /* This parent will stack above siblings with lower z-index values */ width: 300px; height: 200px; background: #b3e6fc; margin: 32px; } /* The child is absolutely positioned inside .parent */ .child { position: absolute; /* Needed for z-index to work */ top: 40px; left: 40px; width: 200px; height: 100px; background: #4f46e5; color: #fff; z-index: 10; /* Relative to its parent's stacking context, not the whole page */ display: flex; align-items: center; justify-content: center; } /* Another sibling element at the root level for comparison */ .sibling { position: relative; z-index: 1; /* Lower than .parent, so .parent stacks on top */ width: 320px; height: 140px; background: #fca311; margin: -80px 0 0 220px; /* Overlap with .parent for demo */ display: flex; align-items: center; justify-content: center; color: #23272f; }

If you have ever run into an issue where z-index isn’t behaving as you expect, check if there’s an unexpected stacking context due to a parent element.

5. What’s the difference between the display property’s block, inline, and inline-block values? (Medium)

When you’re asked about the difference between the display property’s block, inline, and inline-block values in CSS, remember that they determine how elements are displayed in the document flow.

  • Block elements always start on a new line and take up the full width of their parent container, regardless of their actual content. Examples include <div> and <p>.
  • Inline elements flow within a line of text, only occupying as much width as needed for their content; you cannot set their width or height. Examples include <span> and <a>.
  • Inline-block elements combine the behaviors of both inline and block elements: They flow inline with text (without forcing a new line), but you can set their width and height like a block element, which makes them especially useful for custom buttons or navigation items.
Display ValueStarts New Line?Width/Height Settable?Example ElementsblockYesYes<div>, <p>, <h1>inlineNoNo<span>, <a>, <strong>inline-blockNoYesCustom buttons, images, icons 6. What does box-sizing: border-box do? (Medium)

By default, CSS uses the content-box model, which means that width and height only apply to the content, excluding padding and border. box-sizing: border-box changes this so that width and height include the padding and border, making sizing more predictable.

Here’s an example of how that might be demonstrated in CSS:

/* Apply border-box sizing to all elements and their pseudo-elements */ *, *::before, *::after { box-sizing: border-box; /* Width and height now include padding and border */ } /* Demo: Without border-box (the default, content-box) */ .box-content { box-sizing: content-box; width: 200px; padding: 20px; border: 4px solid #2563eb; background: #f0f4ff; margin-bottom: 16px; /* The real rendered width will be: 200px (content) + 40px (padding) + 8px (border) = 248px */ } /* Demo: With border-box */ .box-border { box-sizing: border-box; width: 200px; padding: 20px; border: 4px solid #16a34a; background: #e7faed; /* The rendered width will be exactly 200px, since padding and border are included in the width */ }

With border-box, you avoid the classic issue where adding padding or a border makes your boxes overflow their parent or break your layout. It’s now a standard best practice. You can even say that Chris Coyier has deemed February 1 “International box-sizing Awareness Day” which totally should be a real thing.

7. How would you go about making an image responsive in CSS? (Medium)

This is a deceptively hard question because responsive images is a topic big enough for an entire guide. The classic approach is to ensure that photos never exceed the width of their container. For most cases, that means setting a max-width on the image element and ensuring it maintains its proportions:

/* 1. Make images responsive to their container width */ img { max-width: 100%; /* Prevents the image from overflowing its parent */ height: auto; /* Maintains aspect ratio */ display: block; /* Removes bottom whitespace that inline images have */ }

For images that need to maintain a specific aspect ratio (like a 16:9 video thumbnail), you can use the padding-bottom trick:

/* 2. Maintain a specific aspect ratio (e.g., 16:9) using the padding-bottom trick */ .responsive-img-container { position: relative; /* Needed for absolutely positioning the img */ width: 100%; /* Full width of the parent container */ padding-bottom: 56.25%; /* 16:9 aspect ratio (9/16 = 0.5625) */ overflow: hidden; /* Ensures image doesn’t overflow container */ } .responsive-img-container img { position: absolute; /* Take the image out of the normal flow */ top: 0; left: 0; width: 100%; /* Stretch to fill container */ height: 100%; /* Stretch to fill container */ object-fit: cover; /* Ensure the image covers the area, cropping if needed */ }

Modern CSS also has the aspect-ratio property for this:

/* 3. Use the aspect-ratio property for a cleaner approach (modern browsers) */ .aspect-ratio-img { aspect-ratio: 16 / 9; /* Maintain 16:9 ratio automatically */ width: 100%; height: auto; display: block; }

Responsive images often use the HTML srcset attribute and the <picture> element as well for high-DPI and various screen sizes. There’s an entire CSS-Tricks guide on those features. And, of course, there are performance considerations to take into account because the goal is to serve the best image format and size to the right device.

8. How would you make CSS more performant? (Hard)

CSS performance is crucial for delivering fast and smooth experiences, especially on large-scale websites or applications. Poor CSS practices can slow down page loads, increase rendering times, and make maintenance harder. There are several strategies you can use to keep your CSS efficient and your site responsive.

At the same time, CSS is often not the source of performance bottlenecks. It certainly contributes to it, but performance is a more nuanced field where many factors most certainly influence performance than CSS.

1. Minimize your bundle size

Large CSS files slow down initial page loads. Removing unused CSS (also called “dead code elimination”) can significantly reduce file size. Tools like PurgeCSSUnCSS, or the built-in features of frameworks like Next.js and Tailwind can scan your HTML/JSX and only keep styles that are used.

2. Split and lazy-load CSS

Instead of shipping all CSS at once, split your styles by page or feature (“code splitting”). Modern bundlers (such as webpack and Vite) and frameworks (like React, Vue, and Next.js) support the dynamic import() feature, allowing only the CSS required for the current route or component to be loaded.

// Dynamically load styles when the page loads import("./styles/page.css");

This technique improves “first paint” times and reduces bandwidth, especially for users who never visit certain pages.

3. Use simple, shallow selectors

Browsers read CSS from right to left and evaluate deeply nested or complex selectors more slowly. For best performance, use flat selectors like .btn instead of something like .header nav ul li a.active.

4. Minify and compress CSS

Before deploying, always minify your CSS using tools like cssnano or clean-css. Gzip or Brotli compression (handled by your server or CDN) will further shrink the payload sent to users.

5. Use critical CSS (or not!)

Critical CSS refers to inlining the minimal CSS required for above-the-fold content in the initial HTML. This allows the browser to render the visible part of the page immediately, while loading the rest of the CSS asynchronously.

I’d say this is a nice-to-have sort of thing, as it is a fragile and difficult strategy to implement and maintain.

6. Reduce the use of expensive properties

Specific CSS properties, such as heavy box shadows, filters, or animations on significant elements, can cause “repaints” and slow down rendering. Use these effects thoughtfully, and prefer transform and opacity for animating elements — the browser’s compositor can often optimize these.

7. Avoid !important and overly specific selectors

Frequent use of !important and particular selectors can make your CSS hard to override and debug, leading to more duplicated or conflicting rules.

8. Optimize unused CSS

Let’s face it. As a site is iterated, CSS often becomes larger, not smaller. Styles that were relevant at one point are superseded by new ones without fully replacing the older styles, often for fear of introducing unexpected changes in unknown places.

We have lots and lots of tools for detecting and removing unused CSS. There are limitations and possible trade-offs, of course, so your mileage may vary.

There there’s the case of UI kits or component libraries that import numerous unused styles. It’s easy (and maybe even tempting) to use all of the styles provided by a framework, but try importing only what you need, or use tree-shaking to strip unused parts. Many frameworks allow you to configure exactly what you need, like Bootstrap does.

10. Audit CSS regularly

Modern browser DevTools (like Chrome’s Coverage tab, Performance panel, and Rendering panel) let you see which styles are used on a page, helping you identify and remove dead code.

There are online tools as well, like the Specificity VisualizerCSS Specificity Graph Generator, and CSS Stats. You can find more information on these and more in “Tools for Auditing CSS”.

9. What are the pros and cons of CSS-in-JS vs. external CSS imports, and which would you choose? (Hard)

CSS-in-JS may not be the hot topic it was a few years go, but you’re still very likely to see it pop up in an interview. It’s not so much your duty to rail for or against it, but demonstrate your understanding of the concept and how it compares to external CSS imports.

Here’s how I would break it out.

CSS-in-JS (like styled-components, Emotion, or Stitches) ProsConsStyles are scoped to components, preventing unwanted side effects.Adds runtime overhead and may increase JS bundle size.Dynamic styling based on component state or props.Styles may not appear immediately on server-rendered pages without extra setup.Easy to maintain styles close to your component logic.It can be harder to debug in the browser inspector. External CSS imports (classic .css files, global or CSS Modules): ProsConsCSS is loaded by the browser in parallel, allowing for faster rendering.Risk of style collision in global CSS.Easier to cache and split CSS for large projects.Less dynamic—harder to do conditional styles based on state.Great for global themes, resets, or utility classes.

In practice, most modern teams use a combination of global styles and resets in CSS files, along with component-level styles using CSS-in-JS or CSS Modules.

10. Can you build this layout in CSS? (Hard)

You’ll almost always be asked to build layouts on the fly.

Remember, a question like this is a great opportunity because there’s more than one way to solve it. In this case, we’re looking at a pretty classic “Holy Grail” layout, something Geoff has written about before and demonstrated various ways to go about it using CSS Grid.

You could go with a Flexbox approach as well:

CodePen Embed Fallback

It would be easy to fall into the trap of finding the “best” solution, but this perhaps is one case where demonstrating how to think like a front-end web developer is equally, if not more, important than coming up with a single definitive solution.

Conclusion

These are merely example of the sort of core CSS questions you’re likely to encounter in front-end interviews, along with practical examples and the reasoning behind each approach. If you’re comfortable answering these in depth and can code out the examples under time pressure, you’ll be well-prepared.

For more front-end interview questions, consider exploring frontendlead.com, which helps you prepare for front-end interviews across top tech companies. If you have additional topics you’d like to see covered or encounter tricky interview questions, please feel free to post them in the comments — I’d love to see them.

And, of course, best of luck in your interviews!

How to Prepare for CSS-Specific Interview Questions originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

Dynamic Context for AI Agents

LukeW - Wed, 08/06/2025 - 2:00pm

For AI applications, context is king. So context management, and thereby context engineering, is critical to getting accurate answers to questions, keeping AI agents on task, and more. But context is also hard earned and fragile, which is why we launched templates in AgentDB.

When an AI agent decides it needs to make use of a database, it needs to go through a multi-step process of understanding. It usually takes 3-7 calls before an agent understands enough about a database's structure to accomplish something meaningful with it. That's a lot of time and tokens spent on understanding. Worse still, this discovery tax gets paid repeatedly. Every new agent session starts from zero, relearning the same database semantics that previous agents already figured out.

Templates in AgentDB tackle this by giving AI agents the context they need upfront, rather than forcing them to discover it through trial and error. Templates provide two key pieces of information about a database upfront: a semantic description and structural definition.

The semantic description explains why the database exists and how it should be used. It includes mappings for enumerated values and other domain-specific knowledge. Think of it as the database's user manual written for AI agents. The structural component uses migration schemas to define the database layout. This gives agents immediate understanding of tables, relationships, and data types without needing to query the system architecture.

With AgentDB templates, agents requests like "give me a list of my to-dos" (to-do database) or "create a new opportunity for this customer" (CRM database) work immediately.

Once you've defined a template, it works for any database that follows that pattern. So one template can provide the context an AI agent needs for any number of databases with the same intent. Like a tot-do list database for every user to keep with an earlier example.

But static instructions for AI agents only go so far. These are thinking machines after all. So AgentDB templates can evolve with on use. For example, a template can be dynamically updated with specific queries that worked well. This creates a feedback loop where templates become more effective over time, learning from real-world usage to provide better guidance to future AI interactions.

AgentDB templates are provided to AI agents as an MCP server which also supports raw SQL access. So AI agents can make use of a database effectively right away and still experiment through querying. AgentDB templates are another example of designing software for AI systems rather than humans because they're different "users".

Bringing Back Parallax With Scroll-Driven CSS Animations

Css Tricks - Wed, 08/06/2025 - 3:39am

For a period in the 2010s, parallax was a guaranteed way to make your website “cool”. Indeed, Chris Coyier was writing about it as far back as 2008.

For those unfamiliar with the concept, parallax is a pattern in which different elements of a webpage move at varying speeds as the user scrolls, creating a three-dimensional, layered appearance. A true parallax effect was once only achievable using JavaScript. However, scroll-driven animations have now given us a CSS-only solution, which is free from the main-thread blocking that can plague JavaScript animations.

Parallax may have become a little cliché, but I think it’s worth revisiting with this new CSS feature.

Note: Scroll-driven animations are available on Chrome, Edge, Opera, and Firefox (behind a feature flag) at the time of writing. Use a supported browser when following this tutorial.

Starting code

In this example, we will apply parallax animations to the background and icons within the three “hero” sections of a universe-themed webpage. We’ll start with some lightly styled markup featuring alternating hero and text sections while including some space-related nonsense as placeholder content.

CodePen Embed Fallback Adding initial animations

Let’s add an animation to the background pattern within each hero section to modify the background position.

@keyframes parallax { from { background-position: bottom 0px center; } to { background-position: bottom -400px center; } } section.hero { /* previous code */ + animation: parallax 3s linear; }

Here we use the keyframes CSS rule to create a start and end position for the background. Then we attach this animation to each of our hero sections using the animation property.

By default, CSS animations are duration-based and run when the specified selector is loaded in the DOM. If you refresh your browser, you will see the animation running for three seconds as soon as the page loads.

We do not want our animation to be triggered immediately. Instead, we intend to use the page’s scroll position as a reference to calculate the animation’s progress.

Scroll-driven animations provide two new animation timeline CSS functions. These additions, view() and scroll(), tell the browser what to reference when calculating the progress of a CSS animation. We will use the view() function later, but for now, let’s focus on scroll(). The scroll progress timeline couples the progression of an animation to the user’s scroll position within a scroll container. Parameters can be included to change the scroll axis and container element, but these are not necessary for our implementation.

Let’s use a scroll progress timeline for our animation:

section.hero { /* previous code */ - animation: parallax 3s linear; + animation: parallax linear; + animation-timeline: scroll(); }

If you refresh the page, you will notice that as you scroll down, the position of the background of each hero section also changes. If you scroll back up, the animation reverses. As a bonus, this CSS animation is handled off the main thread and thus is not subject to blocking by any JavaScript that may be running.

Using the view progress timeline

Now let’s add a new parallax layer by animating the header text and icons within each hero section. This way, the background patterns, headers, and main page content will all appear to scroll at different speeds. We will initially use the scroll() CSS function for the animation timeline here as well.

@keyframes float { from { top: 25%; } to { top: 50%; } } .hero-content { /* previous code */ + position: absolute; + top: 25%; + animation: float linear; + animation-timeline: scroll(); }

That’s not quite right. The animation for the sections further down the page is nearly done by the time they come into view. Luckily, the view animation timeline solves this problem. By setting the animation-timeline property to view(), our animation progresses based on the position of the subject within the scrollport, which is the part of the container that is visible when scrolling. Like the scroll animation timeline, scrolling in reverse will also reverse the animation.

Let’s try changing our animation timeline property for the hero text:

.hero-content { /* previous code */ - animation-timeline: scroll(); + animation-timeline: view(); }

That looks pretty good, but there is a problem with the header content flashing into the view when scrolling back up the document. This is because the view timeline is calculated based on the original, pre-animation positioning of the subject element.

We can solve this by adding an inset parameter to the view() function. This adjusts the size of the container in which the animation will take place. According to MDN’s documentation, the “inset is used to determine whether the element is in view which determines the length of the animation timeline. In other words, the animation lasts as long as the element is in the inset-adjusted view.”

So, by using a negative value, we make the container larger than the window and trigger the animation to start a little before and end a little after the subject is visible. This accounts for the fact that the subject moves during the animation.

- animation-timeline: view(); + animation-timeline: view(-100px);

Now both the text and background animate smoothly at different speeds.

CodePen Embed Fallback Adjusting animations using animation ranges

So far, we have employed both scroll and view progress timelines. Let’s look at another way to adjust the start and end timing of the animations using the animation-range property. It can be used to modify where along the timeline the animation will start and end.

We’ll start by adding a view() timeline animation to the #spaceship emoji:

@keyframes launch { from { transform: translate(-100px, 200px); } to { transform: translate(100px, -100px); } } #spaceship { animation: launch; animation-timeline: view(); }

Again, we see the emoji returning to its 0% position once its original unanimated position is outside of the scrollport.

As discussed before, animations are based on the original pre-animation position of the subject. Previously, we solved this by adding an inset parameter to the view() function. We can also adjust the animation range and tell our animation to continue beyond 100% of the animation timeline without having to manipulate the inset of the view timeline itself.

#spaceship { animation: launch; animation-timeline: view(); + animation-range: 0% 120%; }

Now the animation continues until we have scrolled an extra 20% beyond the calculated scroll timeline’s normal endpoint.

Let’s say that we want to add an animation to the #comet emoji, but we don’t want it to start animating until it has passed 4rem from the bottom of the scrollport:

@keyframes rotate { from { transform: rotate(0deg) translateX(100px); } to { transform: rotate(-70deg) translateX(0px); } } #comet { animation: rotate linear; transform-origin: center 125px; animation-timeline: view(); animation-range: 4rem 120%; }

Here we see the “delayed” animation in action:

We can also combine animation ranges to run completely different animations at different points within the same timeline! Let’s illustrate this by combining animation ranges for the #satellite icon at the top of the page. The result is that the first animation runs until the icon passes 80% of the scrollport, then the second animation takes over for the final 20%.

@keyframes orbit-in { 0% { transform: rotate(200deg); } 100% { transform: rotate(0deg); } } @keyframes orbit-out { 0% { transform: translate(0px, 0px); } 100% { transform: translate(-50px, -15px); } } #satellite { animation: orbit-in linear, orbit-out ease; animation-timeline: view(); animation-range: 0% 80%, 80% 110%; } Fallbacks and accessibility

Our webpage features numerous moving elements that may cause discomfort for some users. Let’s consider accessibility for motion sensitivities and incorporate the prefers-reduced-motion CSS media feature.

There are two possible values: no-preference, and reduce. If we want to fine-tune the webpage with animations disabled by default and then enhance each selector with animations and associated styles, then we can use no-preference to enable them.

@media (prefers-reduced-motion: no-preference) { .my-selector { position: relative; top: 25%; animation: cool-animation linear; animation-timeline: scroll(); } }

For us, however, the webpage content and images will still all be visible if we disable all animations simultaneously. This can be done concisely using the reduce option. It’s important to note that this sort of blanket approach works for our situation, but you should always consider the impact on your specific users when implementing accessibility features.

@media (prefers-reduced-motion: reduce) { .my-selector { animation: none !important; } }

In addition to considering accessibility, we should also take into account that scroll-driven animations are not supported by all browsers at the time of writing. If we care a lot about users seeing our animations, we can add a polyfill (direct link) to extend this functionality to currently unsupported browsers. This, however, will force the animation to run on the main thread.

Alternatively, we could decide that performance is important enough to skip the animations on unsupported browsers, thereby keeping the main thread clear. In this case, we can use the @supports selector and include the styles only on supported browsers.

Here is the final code with everything, including the polyfill and reduced motion fallback:

CodePen Embed Fallback Conclusion

There we go, we just re-created a classic web effect with scroll-driven animations using scroll and view progress timelines. We also discussed some of the parameters that can be used to adjust animation behavior. Whether or not parallax is your thing, I like the idea that we can use a modern approach that is capable of doing what we could before… only better with a dash of progressive enhancement.

More information

Bringing Back Parallax With Scroll-Driven CSS Animations originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

Wed, 12/31/1969 - 2:00pm
Syndicate content
©2003 - Present Akamai Design & Development.