惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Martin Fowler
Martin Fowler
L
LINUX DO - 最新话题
P
Proofpoint News Feed
Cyberwarzone
Cyberwarzone
Know Your Adversary
Know Your Adversary
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
L
Lohrmann on Cybersecurity
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Security Latest
Security Latest
T
The Exploit Database - CXSecurity.com
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
P
Privacy & Cybersecurity Law Blog
K
Kaspersky official blog
The Last Watchdog
The Last Watchdog
Webroot Blog
Webroot Blog
Scott Helme
Scott Helme
T
Threat Research - Cisco Blogs
C
Cyber Attacks, Cyber Crime and Cyber Security
WordPress大学
WordPress大学
L
LINUX DO - 热门话题
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - Franky
V
Visual Studio Blog
O
OpenAI News
AI
AI
Hacker News: Ask HN
Hacker News: Ask HN
V2EX - 技术
V2EX - 技术
GbyAI
GbyAI
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Simon Willison's Weblog
Simon Willison's Weblog
S
Schneier on Security
Spread Privacy
Spread Privacy
Y
Y Combinator Blog
I
InfoQ
H
Hackread – Cybersecurity News, Data Breaches, AI and More
T
Threatpost
C
Cybersecurity and Infrastructure Security Agency CISA
F
Fortinet All Blogs
C
CERT Recently Published Vulnerability Notes
T
The Blog of Author Tim Ferriss
C
Check Point Blog
Apple Machine Learning Research
Apple Machine Learning Research
有赞技术团队
有赞技术团队
人人都是产品经理
人人都是产品经理
N
News and Events Feed by Topic
Project Zero
Project Zero
小众软件
小众软件
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
B
Blog
G
Google Developers Blog

CSS Articles by Temani Afif

Get Ready For the Powerful CSS border-shape Property! | CSS-Tricks Let’s Play With Gap Decorations! How to Control Infinite CSS Animations (Part 2 of 2) How to Control Infinite CSS Animations (Part 1 of 2) Two Circles, One Arrow, and Anchor Positioning Making a Responsive Pyramidal Grid With Modern CSS | CSS-Tricks How to Create a CSS-only Elastic Text Effect Making Complex CSS Shapes Using shape() | CSS-Tricks Responsive Hexagon Grid Using Modern CSS | CSS-Tricks Responsive List of Avatars Using Modern CSS (Part 2) | CSS-Tricks Responsive List of Avatars Using Modern CSS (Part 1) | CSS-Tricks Perfectly Pointed Tooltips: To The Corners Perfectly Pointed Tooltips: All Four Sides Perfectly Pointed Tooltips: A Foundation Sequential linear() Animation With N Elements | CSS-Tricks Infinite Marquee Animation using Modern CSS Better CSS Shapes Using shape() — Part 4: Close and Move | CSS-Tricks Drawing CSS Shapes using corner-shape Better CSS Shapes Using shape() — Part 3: Curves | CSS-Tricks Better CSS Shapes Using shape() — Part 2: More on Arcs | CSS-Tricks Better CSS Shapes Using shape() — Part 1: Lines and Arcs | CSS-Tricks Creating Blob Shapes using clip-path: shape() Creating Flower Shapes using clip-path: shape() Custom progress element using the attr() function A CSS-Only Star Rating Component and More! (Part 2) | CSS-Tricks A CSS-Only Star Rating Component and More! (Part 1) | CSS-Tricks How to Create Wavy Boxes Using CSS Full-Bleed Layout with Modern CSS Fancy Menu Navigation Using Anchor Positioning | CSS-Tricks How to Create a Zig-Zag Box Using CSS How to Create Zig-Zag CSS Loaders Using One Element Custom Progress Element Using Anchor Positioning & Scroll-Driven Animations How to Create Filling CSS Loaders Using One Element How to Create Curved-Edge and Rounded-Edge Shapes Using CSS CSS Tricks That Use Only One Gradient | CSS-Tricks How to create Shapes with Inner Curves using CSS Mask Custom Range Slider Using Anchor Positioning & Scroll-Driven Animations How to Get the Width/Height of Any Element in Only CSS How Keyboard Navigation Works in a CSS Game How To Create Cut-Out Shapes using The clip-path property The Modern Guide For Making CSS Shapes — Smashing Magazine css-shape.com: The Ultimate Collection of CSS-only Shapes ⚡️ Sliding 3D Image Frames In CSS — Smashing Magazine CSS Tricks To Master The clip-path Property Creating Wavy Circles with Fancy Animations in CSS Modern CSS Tooltips And Speech Bubbles (Part 2) — Smashing Magazine Do you need a Tooltip or a Speech Bubble? I have created 100 using CSS 😲 Modern CSS Tooltips And Speech Bubbles (Part 1) — Smashing Magazine Creating Flower Shapes using CSS Mask & Trigonometric Functions CSS Shapes: The Triangle The Complex But Awesome CSS border-image Property — Smashing Magazine CSS Tricks to add 3D Effects to your Text CSS Responsive Multi-Line Ribbon Shapes (Part 2) — Smashing Magazine CSS Responsive Multi-Line Ribbon Shapes (Part 1) — Smashing Magazine I have made 100+ CSS-only Ribbon Shapes | The Perfect Collection 🎀 How to create a CSS-only infinite scroll animation Re-Creating The Pop-Out Hover Effect With Modern CSS (Part 2) — Smashing Magazine Re-Creating The Pop-Out Hover Effect With Modern CSS (Part 1) — Smashing Magazine How to Create CSS Ribbon Shapes with a Single Element CSS Shapes: The Ribbon Revealing Images With CSS Mask Animations — Smashing Magazine css-loaders.com: The Biggest Collection of Loading Animations (more than 500 🤯) How To Define An Array Of Colors With CSS — Smashing Magazine CSS effects on images II Shines, Perspective, And Rotations: Fancy CSS 3D Effects For Images — Smashing Magazine What's your Lucky CSS Pattern? Check It Now! How to Add a CSS Reveal Animation to Your Images Modern Layouts using CSS Grid I created 100+ unique CSS patterns | The best collection 🤩 How to Create a Custom Range Slider Using CSS CSS Shapes: The Heart CSS Shapes: Polygon & Starburst A Text Reveal Animation using CSS CSS Tip: learn CSS the easy way! How to build a CSS-only accordion How to create Breadcrumb Navigation with CSS Different Ways to Get CSS Gradient Shadows | CSS-Tricks A CSS-only responsive Stepper component A Fancy Hover Effect For Your Avatar | CSS-Tricks How to make a zoom effect using CSS Creating a Custom Cursor using CSS CSS Infinite 3D Sliders | CSS-Tricks CSS Infinite Slider Flipping Through Polaroid Images | CSS-Tricks How to create a responsive sidebar menu using CSS CSS Infinite and Circular Rotating Image Slider | CSS-Tricks Making Static Noise From a Weird CSS Gradient Bug | CSS-Tricks CSS Grid and Custom Shapes, Part 3 | CSS-Tricks Fancy Image Decorations: Outlines and Complex Animations | CSS-Tricks Fancy Image Decorations: Masks and Advanced Hover Effects | CSS-Tricks Fancy Image Decorations: Single Element Magic | CSS-Tricks How to create an infinite image slider using CSS How to Create Wavy Shapes & Patterns in CSS | CSS-Tricks How I Made a Pure CSS Puzzle Game | CSS-Tricks How to create a Tooltip/Speech Bubble using CSS CSS Grid and Custom Shapes, Part 2 | CSS-Tricks CSS Grid and Custom Shapes, Part 1 | CSS-Tricks Zooming Images in a Grid Layout | CSS-Tricks How to create a CSS-only loader with one element Exploring CSS Grid’s Implicit Grid and Auto-Placement Powers | CSS-Tricks How to create background pattern using CSS & conic-gradient
Image Fragmentation Effect With CSS Masks and Custom Properties | CSS-Tricks
Temani Afif · 2021-03-23 · via CSS Articles by Temani Afif

Geoff shared this idea of a checkerboard where the tiles disappear one-by-one to reveal an image. In it, an element has a background image, then a CSS Grid layout holds the “tiles” that go from a filled background color to transparent, revealing the image. A light touch of SCSS staggers the animation.

I have a similar idea, but with a different approach. Instead of revealing the image, let’s start with it fully revealed, then let it disappear one tile at a time, as if it’s floating away in tiny fragments.

Here’s a working demo of the result. No JavaScript handling, no SVG trickery. Only a single <img> and some SCSS magic.

Cool, right? Sure, but here’s the rub. You’re going to have to view this in Chrome, Edge or Opera because those are the only browsers with support for @property at the moment and that’s a key component to this idea. We won’t let that stop us because this is a great opportunity to get our hands wet with cool CSS features, like masks and animating linear gradients with the help of @property.

Masking things

Masking is sometimes hard to conceptualize and often gets confused with clipping. The bottom line: masks are images. When an image is applied as mask to an element, any transparent parts of the image allow us see right through the element. Any opaque parts will make the element fully visible.

Masks work the same way as opacity, but on different portions of the same element. That’s different from clipping, which is a path where everything outside the path is simply hidden. The advantages of masking is that we can have as many mask layers as we want on the same element — similar to how we can chain multiple images on background-image.

And since masks are images, we get to use CSS gradients to make them. Let’s take an easy example to better understand the trick.

img {
  mask:
    linear-gradient(rgba(0,0,0,0.8) 0 0) left,  /* 1 */
    linear-gradient(rgba(0,0,0,0.5) 0 0) right; /* 2 */
  mask-size: 50% 100%;
  mask-repeat: no-repeat;
}

Here, we’re defining two mask layers on an image. They are both a solid color but the alpha transparency values are different. The above syntax may look strange but it’s a simplified way of writing linear-gradient(rgba(0,0,0,0.8), rgba(0,0,0,0.8)).

It’s worth noting that the color we use is irrelevant since the default mask-mode is alpha. The alpha value is the only relevant thing. Our gradient can be linear-gradient(rgba(X,Y,Z,0.8) 0 0) where X, Y and Z are random values.

Each mask layer is equal to 50% 100% (or half width and full height of the image). One mask covers the left and the other covers the right. At the end, we have two non-overlapping masks covering the whole area of the image and, as we discussed earlier, each one has a differently defined alpha transparency value.

We’re looking at two mask layers created with two linear gradients. The first gradient, left, has an alpha value of 0.8. The second gradient, right, has an alpha value of 0.5. The first gradient is more opaque meaning more of the image shows through. The second gradient is more transparent meaning more of the of background shows through.

Animating linear gradients

What we want to do is apply an animation to the linear gradient alpha values of our mask to create a transparency animation. Later on, we’ll make these into asynchronous animations that will create the fragmentation effect.

Animating gradients is something we’ve been unable to do in CSS. That is, until we got limited support for @property. Jhey Tompkins did a deep dive into the awesome animating powers of @property, demonstrating how it can be used to transition gradients. Again, you’ll want to view this in Chrome or another Blink-powered browser:

In short, @property lets us create custom CSS properties where we’re able to define the syntax by specifying a type. Let’s create two properties, --c-0 and--c-1 , that take a number with an initial value of 1.

@property --c-0 {
   syntax: "<number>";
   initial-value: 1;
   inherits: false;
}
@property --c-1 {
   syntax: "<number>";
   initial-value: 1;
   inherits: false;
}

Those properties are going to represent the alpha values in our CSS mask. And since they both default to fully opaque (i.e. 1 ), the entire image shows through the mask. Here’s how we can rewrite the mask using the custom properties:

/* Omitting the @property blocks above for brevity */

img {
  mask:
    linear-gradient(rgba(0,0,0,var(--c-0)) 0 0) left,  /* 1 */
    linear-gradient(rgba(0,0,0,var(--c-1)) 0 0) right; /* 2 */
  mask-size: 50% 100%;
  mask-repeat: no-repeat;
  transition: --c-0 0.5s, --c-1 0.3s 0.4s;
}

img:hover {
  --c-0:0;
  --c-1:0;
}

All we’re doing here is applying a different transition duration and delay for each custom variable. Go ahead and hover the image. The first gradient of the mask will fade out to an alpha value of 0 to make the image totally see through, followed but the second gradient.

More masking!

So far, we’ve only been working with two linear gradients on our mask and two custom properties. To create a tiling or fragmentation effect, we’ll need lots more tiles, and that means lots more gradients and a lot of custom properties!

SCSS makes this a fairly trivial task, so that’s what we’re turning to for writing styles from here on out. As we saw in the first example, we have a kind of matrix of tiles. We can think of those as rows and columns, so let’s define two SCSS variables, $x and $y to represent them.

Custom properties

We’re going to need @property definitions for each one. No one wants to write all those out by hand, though, so let’s allow SCSS do the heavy lifting for us by running our properties through a loop:

@for $i from 0 through ($x - 1) {
  @for $j from 0 through ($y - 1) {
    @property --c-#{$i}-#{$j} {
      syntax: "<number>";
      initial-value: 1;
      inherits: false;
    }
  }
}

Then we make all of them go to 0 on hover:

img:hover {
  @for $i from 0 through ($x - 1) {
    @for $j from 0 through ($y - 1) {
      --c-#{$i}-#{$j}: 0;
    }
  }
}

Gradients

We’re going to write a @mixin that generates them for us:

@mixin image() {
  $all_t: (); // Transition
  $all_m: (); // Mask
  @for $i from 0 through ($x - 1) {
    @for $j from 0 through ($y - 1) {
      $all_t: append($all_t, --c-#{$i}-#{$j} transition($i,$j), comma);
      $all_m: append($all_m, linear-gradient(rgba(0,0,0,var(--c-#{$i}-#{$j})) 0 0) calc(#{$i}*100%/(#{$x} - 1)) calc(#{$j}*100%/(#{$y} - 1)), comma);
    }
  }
  transition: $all_t;
  mask: $all_m;
}

All our mask layers equally-sized, so we only need one property for this, relying on the $x and $y variables and calc():

mask-size: calc(100%/#{$x}) calc(100%/#{$y})

You may have noticed this line as well:

$all_t: append($all_t, --c-#{$i}-#{$j} transition($i,$j), comma);

Within the same mixing, we’re also generating the transition property that contains all the previously defined custom properties.

Finally, we generate a different duration/delay for each property, thanks to the random() function in SCSS.

@function transition($i,$j) {
  @return $s*random()+s $s*random()+s;
}

Now all we have to do is to adjust the $x and $y variables to control the granularity of our fragmentation.

Playing with the animations

We can also change the random configuration to consider different kind of animations.

In the code above, I defined the transition() function like below:

// Uncomment one to use it
@function transition($i,$j) {
  // @return (($s*($i+$j))/($x+$y))+s (($s*($i+$j))/($x+$y))+s; /* diagonal */
  // @return (($s*$i)/$x)+s (($s*$j)/$y)+s; /* left to right */
  // @return (($s*$j)/$y)+s (($s*$i)/$x)+s; /* top to bottom */
  // @return  ($s*random())+s (($s*$j)/$y)+s; /* top to bottom random */
  @return  ($s*random())+s (($s*$i)/$y)+s; /* left to right random */
  // @return  ($s*random())+s (($s*($i+$j))/($x+$y))+s; /* diagonal random */
  // @return ($s*random())+s ($s*random())+s; /* full random*/
}

By adjusting the formula, we can get different kinds of animation. Simply uncomment the one you want to use. This list is non-exhaustive — we can have any combination by considering more forumlas. (I’ll let you imagine what’s possible if we add advanced math functions, like sin(), sqrt(), etc.)

Playing with the gradients

We can still play around with our code by adjusting the gradient so that, instead of animating the alpha value, we animate the color stops. Our gradient will look like this:

linear-gradient(white var(--c-#{$i}-#{$j}),transparent 0)

Then we animate the variable from 100% to 0%. And, hey, we don’t have to stick with linear gradients. Why not radial?

Like the transition, we can define any kind of gradient we want — the combinations are infinite!

Playing with the overlap

Let’s introduce another variable to control the overlap between our gradient masks. This variable will set the mask-size like this:

calc(#{$o}*100%/#{$x}) calc(#{$o}*100%/#{$y})

There is no overlap if it’s equal to 1. If it’s bigger, then we do get an overlap. This allows us to make even more kinds of animations:

That’s it!

All we have to do is to find the perfect combination between variables and formulas to create astonishing and crazy image fragmentation effects.