1

So you can get pixelation in CSS by doing the following:

  • Set background-image to a very small image (say 50px or 100px).
  • Set image-rendering: pixelated on the element.

That will give you the pixelated look.

Now I would like to animate this, by replacing the "very small image" with a large image after it finishes downloading by the browser:

let img = new Image()
img.src = largeVersion
img.onload = function(){
  // set css background-image to the new image perhaps, not sure...      
}

The problem is two-fold.

  1. I want to have the background-image using background-size: cover so it properly fills the container element. So you can't use background-size in any pixelation animation.
  2. transform: scale(0.1) (to get close to the original pixelation size) doesn't work because it scales the whole element.

I would like to do something like this: animate transform: scale(x) to go from 50px pixelated image to 2000px unpixelated image, over 0.3 or 0.5 seconds. But that doesn't work. I thought maybe using background-size, but that doesn't work either because of the constraint.

Wondering if there is any way to accomplish this.

I have seen this which does pixelation using canvas. Wondering if there is no other solution that works without using JS/canvas.

<style>
  div {
    background-size: cover;
    background-repeat: no-repeat;
    background-position: center center;
  }
</style>
<div style='background-image: url(/100px.jpg)'></div>
Lance
  • 75,200
  • 93
  • 289
  • 503
  • a little confused, are you trying to animate from 1 background-image (50px pixelated image) to a new background-image (2000px unpixelated image) of the same element? Or are these 2 different DOM elements? Can you add the HTML? – zgood Jun 04 '19 at 18:28
  • I am trying to take 1 HTML element and swap out it's background-image with the big image. Then I was thinking of starting the big image off scaled small, so you could animate the scaling, and the pixelation would take care of itself. But I'm not sure that works. – Lance Jun 04 '19 at 18:29
  • something similar to this maybe? https://jsfiddle.net/hbw7pnet/1/ – zgood Jun 04 '19 at 18:46
  • No, I don't want to scale (or animate the scaling of) the actual image like in that jsfiddle. I was using the image scaling idea to scale the bitmap so you draw a 50px image but then scale it to 2000px to get pixelation. – Lance Jun 04 '19 at 18:49

1 Answers1

4

You can do pixelation with an svg filter. You can then animate the filter. to use the filter on a div background you just do filter: url(#filterid)

put together it looks like this:

#myDiv::before{
content:"";
position:absolute;
top:0;
left:0;
width:100%;
height:100%;
filter:url(#pixelate);
background-size:cover;
background-image:url(https://images.unsplash.com/photo-1475724017904-b712052c192a?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=2850&q=80)

}

#myDiv {
  position:relative;
  width:350px;
  height:250px;
}

.inside {
  position: relative;
}
<div id="myDiv"> <div class="inside"><h1>Hello</h1></div> </div>
<svg>
  <filter id="pixelate" x="0" y="0">
    <feFlood x="4" y="4" height="1" width="1" />
    <feComposite id="composite1" width="10" height="10" />
    <feTile result="a" />
    <feComposite in="SourceGraphic" in2="a" operator="in" />
    <feMorphology id="morphology" operator="dilate" radius="5" />
  </filter>

  <animate xlink:href="#composite1" id="anim-width" 
    attributeName="width" from="40" to="10" dur=".8s"
    fill="freeze" />  
  <animate xlink:href="#composite1" id="anim-height" 
    attributeName="height" from="40" to="10" dur=".8s"
    fill="freeze" />
  <animate xlink:href="#morphology" id="anim-radius" 
    attributeName="radius" from="20" to="5" dur=".8s"
    fill="freeze"/>
</svg>

Notice I had to create a inner div and apply the background on a pseudo-element ::before but "soon" this will become unnecessary, when the support of backdrop-filter improves.

references:

Pixelate svg effect: https://codesandbox.io/s/km3opvn6yv

Animate an svg filter: https://codepen.io/chriscoyier/pen/dPRVqL

backdrop-filter: https://developer.mozilla.org/en-US/docs/Web/CSS/backdrop-filter

Tiago Coelho
  • 5,023
  • 10
  • 17