Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Motion Blur Effects #11134

Open
yashrajbharti opened this issue Nov 1, 2024 · 6 comments
Open

Motion Blur Effects #11134

yashrajbharti opened this issue Nov 1, 2024 · 6 comments

Comments

@yashrajbharti
Copy link

yashrajbharti commented Nov 1, 2024

Why

Current CSS blur capabilities apply uniformly across entire elements, which limits the potential for directionally, progressively, and partially blurred effects directly in CSS. Achieving realistic motion effects, like motion blur, or specific directional blurs, which add depth and context, is only feasible through design tools such as Figma and Photoshop. As a UX Engineer with experience in both design and development, I see a need to expand CSS blur capabilities to enhance design fidelity on the web.

Motivation

In a recent conversation with Google DevRel @argyleink, he emphasized the value of adding a directional blur feature in CSS. This would allow for effects currently only available in SVG to be more accessible within CSS, promoting consistency across web platforms and design tools.

Feature Breakdown

1. Motion Blur:

  • Description: Simulates real-world motion by blurring, similar to motion graphic tools like Photoshop's motion blur.
  • Use Cases: Adds realism in animations, especially for fast-moving elements like vehicles or UI components.
  • Proposed Syntax:
.blur-layer {
  motion-blur: 10px, -30deg; /* Shorthand for motion blur */
  /* Long-form properties */
  motion-blur-distance: 10px;
  motion-blur-angle: -30deg;
}
  • Values:
    motion-blur: none | auto | inherit | initial; where auto applies a default subtle blur, none disables the effect, and inherit follows the parent element.

  • Example from Photoshop:

Motion Blur Photoshop
Motion Blur Effect

2. Horizontal and Vertical Blur:

  • Description: Applies blur along a single axis, which is useful for directional emphasis or to simulate movement.
  • Use Cases: Perfect for images that depict motion in a single direction, like trains or passing scenery.
  • Proposed Syntax:
.horizontal-blur {
  motion-blur: linear(20px, 0deg); /* Horizontal blur */
}
.vertical-blur {
  motion-blur: linear(20px, 90deg); /* Vertical blur */
}

This syntax not only limits blurring in horizontal or vertical direction, but any direction and has a similar syntax to linear-gradient(). This is different from the motion-blur: <distance> <angle> in a few ways.

The distinction between motion-blur: 10px, -30deg; and motion-blur: linear(10px, -30deg); is crucial for understanding how each type of blur affects visual elements. The first syntax, motion-blur: 10px, -30deg;, creates a uniform blur effect that smudges an element over a distance of 10 pixels, resulting in a softened appearance that conveys a sense of motion without a specific directional focus. In contrast, the second syntax, motion-blur: linear(10px, -30deg);, applies a directional blur that not only blurs the element but also simulates a speed-based movement effect by squeezing the blur along the specified angle of -30 degrees. This distinction allows designers to choose between a generalized motion effect and a more dynamic, directional blur that enhances the realism of animations, providing greater control over how motion is visually represented in web design.

  • Horizontal blur example:

Horizontal Blur

  • Vertical blur example:

Vertical Blur

3. Radial/Zoom Blur

  • Description: Applies a radial blur that starts from a focal point and blurs outward, mimicking zoom motion.
  • Use Cases: Useful for scenarios where focus is centered, such as for elements meant to draw user attention to the middle.
  • Proposed Syntax:
.radial-blur {
  motion-blur: radial(10px at center); /* Radial blur with adjustable intensity */
}
  • Examples:
    Zoom Blur
    Radial Blur

4. Progressive Blur

  • Description: Blurs progressively in a specified direction, creating a gradient-like blur effect that can simulate depth or movement in a single direction. This is possible using a progressive blur plugin in Figma but lacks as a feature in CSS.
  • Use Cases: Useful for elements that need a gradual visual hierarchy, like background transitions.
  • Proposed Syntax:
.progressive-blur {
  motion-blur: progressive(10px, to bottom); /* Blurs progressively from top to bottom */
}

Progressive Blur

Syntax Summary for Motion Blur Properties

1. Motion Blur:

motion-blur: 10px, -30deg; /* Shorthand motion blur */
motion-blur-distance: 10px; /* Long-form for distance */
motion-blur-angle: -30deg; /* Long-form for angle */

2. Horizontal and Vertical Blur:

.horizontal-blur {
  motion-blur: linear(20px, 0deg);
}
.vertical-blur {
  motion-blur: linear(20px, 90deg);
}

3. Radial Blur:

motion-blur: radial(10px at center);

4. Progressive Blur:

motion-blur: progressive(10px, to bottom);

This syntax aims to provide greater control over how motion blur is visually represented in web design. However, it may need changes as I am still figuring out how to incorporate all aspects of the amount of blurriness to apply as a value, blur distance, blur angle, the amount of squish in directional blur, and the starting point in progressive blur.

@argyleink
Copy link
Contributor

I really like this proposal!

2015 is when I learned SVG could do x or y blur effects from SVG filters(demo). I think this proposal should move as much into CSS as possible and detach itself from the SVG dependency.

I want that progressive motion blur right now 🙂 I've tried emulating it before with today's blur filters and gradients/masks, but never matched the effect. Great examples, and a solid syntax proposal imo.

It's also a great complimentary proposal to #3837. This "motion blur effects" proposal offers specific functions, which give great control but would need manual transitions/keyframes in order to animate; while proposal #3837 is automatic and adapts blur amounts to the distance | difference pixels incur during animation.

@smfr
Copy link
Contributor

smfr commented Nov 2, 2024

This should be a filter function: filter: motion-blur(45deg, 10px 20px) or something.

@Monknow
Copy link

Monknow commented Nov 3, 2024

I really like this idea, but adding it as part of the syntax of the blur() function makes more sense. Maybe something like

  • filter: blur(20px, 0deg, linear);
  • filter: blur(10px, at center, radial);
  • filter: blur(10px, to bottom, progressive);

The keywords "at center" and "to bottom" would have a numeric equivalent like linear-gradient() and radial-gradient() do?

@yashrajbharti
Copy link
Author

yashrajbharti commented Nov 17, 2024

I created a Progressive Motion Blur visualiser that illustrates the concept further and shows my proposed motion-blur CSS property in action by simulating the blur effect using HTML Canvas API.

The code can be seen here:
Progressive Motion Blur | Github Repo
And here,
Progressive Motion Blur | Codepen

The proposed syntax looks like this:

filter: motion-blur(<Angle>, <Offset-X>, <Offset-Y>, <Initial-Blur-Value>, <Incremental-Value>, progressive);

Further, I thought more about each of the Instance parameters and the values they might represent, here it is:

Parameter Description Type Default Allowed Values
direction The angle or keyword specifying the direction of the blur effect. string/int "to right" See the Direction Keywords section.
offsetX The horizontal offset where the blur starts. number 0 0 - 1 (relative to canvas width)
offsetY The vertical offset where the blur starts. number 0 0 - 1 (relative to canvas height)
value The initial blur value in pixels. number 0 Any positive number.
increment The incremental blur value applied progressively along the direction. number 0.02 Any positive number.

No Blur Progressive Motion Blur of 0.02 Progressive Motion Blur of 0.045 Progressive Motion Blur of 0.045 with x-offset 0.6

The examples showcase: No Blur effect, Progressive Motion Blur of 0.02, Progressive Motion Blur of 0.045 and Progressive Motion Blur of 0.045 with x-offset 0.6 respectively. The direction for the effect is to right or 0deg.

Also, another use case of my suggested CSS Property is that Progressive Motion Blur can also be used to create Partial Blur effects in a case where when only offset and blur values are provided, without incremental changes.

More details are on the README

I tested the visualiser on Chrome. It's known to not work in Safari due to safari lacking support for ctx.filter Canvas Filters | Caniuse

I’m open to suggestions! The goal of this tool is to support the draft and provide a visual reference for how progressive motion blur might work in CSS. If you spot anything I may have missed or have ideas for enhancement, I’d love to hear it!

@oczki
Copy link

oczki commented Dec 3, 2024

I like the idea!

Progressive blur

For years I wanted to create progressive/gradual blur in CSS to simulate the tilt-shift camera effect, or reflections of a matte surface in CSS art.

My previous approach—an overlay with hundreds of divs with increasing blur value—was quite heavy on resources or even completely crashed mobile browsers:

So, having a progressive blur filter would be very helpful to achieve a similar result without significant performance hit.

I'm wondering whether putting progressive blur under "motion blur" umbrella is semantically correct. In my mind, it isn't related to motion, as I've only seen progressive blur in static contexts, like the aforementioned tilt-shift photography, matte reflections, or soft shadows (umbra, penumbra) cast by objects lit by a large light source.

I'm also wondering about the increment parameter. I made the CodePens above so I'm aware what it does, but this parameter is very technical and is usually a rather small value (like 0.02 and 0.045 in your examples). I think that programmers would be more interested in controlling start+end blur radius, instead of start+increment. This would be a more intuitive behavior in my opinion—e.g. I want the blur to progress from 0px to 8px, so that's what I define in the function and don't care about the resulting increment.

Similarly with its offsets: I think a start and end offset would be useful, kind of defining gradient stops.

Radial blur

Some image editors (e.g. Photopea) split radial blur into zoom blur (movement towards the center) and spin blur (rotation around the center). If CSS were to get zoom blur and motion blur, I think spin blur would be a good addition to the overall package.

  • Zoom blur
  • Spin blur

For zoom blur, I'd like to clarify whether the blur would be constant alongside the radius, or maybe it should be progressive as well. A constant zoom blur might look weird in the center and don't really sell the effect. If you look closely at the pictures you posted, you can see that the center is less blurry than the edges. As a result, I'd suggest treating zoom blur similarly to progressive blur, with start+end blur values and start+end offsets.

Summary

Since these blur types (linear, radial, progressive) require a different set of parameters, I would suggest against putting them under one filter: blur(), only distinguished by the last parameter linear, radial, progressive. Instead, I believe using the approach from gradients would be much easier to work with, understand, and parse.

My suggestion would be:

  • No change to the old Gaussian blurfilter: blur(radius);
    • filter: blur(10px);
  • Motion blur (linear)filter: linear-blur(radius, angle);
    • filter: linear-blur(10px);
    • filter: linear-blur(10px, to right);
    • filter: linear-blur(10px, 45deg);
  • Motion blur (zoom)filter: zoom-blur(radius-start and radius-end, position, offset-start and offset-end);
    • filter: zoom-blur(10px);
      • constant zoom blur at the center
    • filter: zoom-blur(0px 20px, circle at 10% 10%);
      • natural-looking zoom blur, growing from 0px in the origin to 20px at the end
    • filter: zoom-blur(0px 20px, ellipse at right 8%, 2rem 8rem);
      • no blur in the origin point, at 2rem starts to grow, at 8rem reaches 20px, stays at 20px till the end
  • Spin blurfilter: spin-blur(radius, position);
    • filter: spin-blur(10px);
    • filter: spin-blur(10px, ellipse at right 8%);
  • Progressive blurfilter: progressive-blur(radius-start and radius-end, angle, offset-start and offset-end);
    • filter: progressive-blur(0px 10px);
    • filter: progressive-blur(2px 10px, 45deg);
    • filter: progressive-blur(2px 10px, 45deg, 2rem);
      • 2px blur at the start, 2rem later the blur increases, and reaches 10px at the end
    • filter: progressive-blur(2px 10px, 45deg, 2rem 8rem);
      • 2px blur at the start, 2rem later the blur increases, reaches 10px at 8rem, stays at 10px till the end

All of the above would also apply to backdrop-filter, of course.

@yashrajbharti
Copy link
Author

yashrajbharti commented Dec 10, 2024

Thanks! I recreated the progressive motion blur with start and end values instead of the increment!
Progressive Motion Blur V2 | Codepen

The proposed (new) syntax looks like this:

filter: motion-blur(<Angle>, <Offset-X>, <Offset-Y>, <Initial-Blur-Value>, <Final-Blur-Value>, progressive);

or

filter: progressive-blur(<Angle>, <Offset-X>, <Offset-Y>, <Initial-Blur-Value>, <Final-Blur-Value>);

could be a better option!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants