How to Recreate the Banksy Artwork Shredder Using CSS Grid
On Friday, Banksy pranked the world again by shredding “Girl With Balloon” immediately after it fetched $1.4 million in auction. While everyone debates if the artwork has gone up or down in value because of this, I thought it would be fun to recreate the effect in CodePen.IO using CSS Grid. You can check out the outcome of my one hour freestyle session on
I wasn’t shy to create a bunch of elements on this rough solution so I piled on a series of divs
mostly positioned absolute and then centered the parent element #piece
in the middle of the page.
<div id="piece"> <div id="window"> <div id="painting"> <div id="shredded"> <div class="shred"></div> <div class="shred"></div> <div class="shred"></div> <div class="shred"></div> <div class="shred"></div> <div class="shred"></div> <div class="shred"></div> <div class="shred"></div> <div class="shred"></div> <div class="shred"></div> <div class="shred"></div> </div> <div id="original"></div> </div> </div> <div id="frame"></div></div>
Directly within #piece
are two divs: #window
and #frame
. #frame
is simply a 100% x 100% artwork frame image we’ll position on top of everything. The #window
is positioned below and is also centered within the #piece.
This #window
holds our #painting
div which includes both the #original
and #shredded
image. The real magic occurs within #shredded
.shred
divs which we’ll use a combination of background-image
and CSS grid to create shredded versions of our artwork image. Each .shred
positions the background slightly to the left.#shredded{ background: url(ARTWORK_URL); bottom: 0; display: grid; grid-column-gap: 3px; grid-template-columns: repeat(11, 1fr);
position: absolute;}
#shredded .shred:nth-child(1){ background-position: 0% 0%; }#shredded .shred:nth-child(2){ background-position: 10% 0%; }#shredded .shred:nth-child(3){ background-position: 20% 0%; }#shredded .shred:nth-child(4){ background-position: 30% 0%; }#shredded .shred:nth-child(5){ background-position: 40% 0%; }#shredded .shred:nth-child(6){ background-position: 50% 0%; }#shredded .shred:nth-child(7){ background-position: 60% 0%; }#shredded .shred:nth-child(8){ background-position: 70% 0%; }#shredded .shred:nth-child(9){ background-position: 80% 0%; }#shredded .shred:nth-child(10){ background-position: 90% 0%; }#shredded .shred:nth-child(11){ background-position: 100% 0%; }
My hacky solution then slides the entire #painting
down using translateY
while also resizing the #original
artwork’s height to 0. Since the #original
div is positioned on top of #shredded
and #shredded
is positioned to the bottom, subtracting it’s height reveals the shredded image below. You can very easily accomplish these animations directly in CSS. However, I decided to throw in Anime.JS so I had a bit more control on stopping and resetting the animation since I knew I was going to add the ability to change the image. Here’s how Anime.JS makes easy work of the animations:
anime({ targets: '#original', height: 0, duration: 100000, easing: 'linear'})
anime({ targets: '#painting', translateY: '100%' duration: 100000, easing: 'linear'})
And that’s about it. You can dig into the rest of the CodePen to see how I wired up the ability to change the image using Vue and Blue Imp’s excellent Javascript Load Image library.
This was a one hour hack so I’m sure readers will have a much more elegant solution in mind. Did someone say linear gradients? I would love to hear how you would do it and what sort of enhancements you might make. Happy shredding!