
Using SVG as image placeholders - FriedPickles
https://medium.com/@jmperezperez/using-svg-as-placeholders-more-image-loading-techniques-bed1b810ab2c
======
fogleman
(Developer of Primitive here.)

Love seeing people use my software in different ways! If this looks
interesting to you, try it out:

[https://primitive.lol/](https://primitive.lol/)

[https://github.com/fogleman/primitive](https://github.com/fogleman/primitive)

Also, I made a Twitter bot that posts samples every 30 minutes based on
"interesting" Flickr photos using randomized Primitive settings:

[https://twitter.com/PrimitivePic](https://twitter.com/PrimitivePic)

~~~
santaclaus
Aren't you the guy who writes all the graphics stuff in Go too? How do you
find time to do all this???

~~~
fogleman
What do you do with all of your time? :)

~~~
artificial
Why Hacker News of course! Thanks for sharing.

------
nathan_long
Clever, but I'd love to see browser support for FLIF make this kind of thing
irrelevant.

> FLIF is lossless, but can still be used in low-bandwidth situations, since
> only the first part of a file is needed for a reasonable preview of the
> image.

> A FLIF image can be loaded in different ‘variations’ from the same source
> file, by loading the file only partially. This makes it a very appropriate
> file format for responsive web design.

The loading video on
[http://flif.info/index.html](http://flif.info/index.html) makes this clear.

~~~
mcphage
> browser support for FLIF make this kind of thing irrelevant

I'm not sure it would. The nice thing about a lot of these SVG options (or
even the smaller images as well), is that they can be embedded into pages. So
not only do you see the image faster, you also reduce the number of remote
file fetches. FLIF sounds like you'd still have to hit another server to see
anything, even if the thing you see would display before it finishes loading.

~~~
nathan_long
> The nice thing about a lot of these SVG options (or even the smaller images
> as well), is that they can be embedded into pages

That's a good point. Though presumably you could embed FLIF data into HTML
using a data URI - [https://css-tricks.com/data-uris/](https://css-
tricks.com/data-uris/)

~~~
ant6n
Can a data uri be used to store 10% of a file in HTML, but then get the rest
of a file? I mean you don't want to include the whole file.

~~~
nathan_long
You should be able to encode the first 10% of a file as a data URI, yes.

Maybe you could use something like `srcset` to say "and also load the higher-
quality verion from the server"?
[https://responsiveimages.org/](https://responsiveimages.org/)

~~~
BHSPitMonkey
I think they mean, could you inline the first 10%, and then lazy-load the
other 90% (taking advantage of the FLIF decoder's progressive rendering).
Which I would have to imagine is a "no" (you would have to swap your 10%
placeholder with a whole 100% remote version).

~~~
nathan_long
Currently, browsers don't support FLIF at all. If they ever do support it,
what you're suggesting could be an excellent feature to add.

------
vortico
The animation is really fun.

Maybe I am unusual, but I have never in my life been annoyed at image load
time, even in the dial-up days. I just simply open a new tab or window and
continue reading an article or writing code if loading takes too long. But
when websites start adding "progressive" placeholders that don't decrease the
load time but increase the CPU, that's what annoys me since they prevent
multitasked work from being done. If I don't care about the images on the
page, I'll continue scrolling, but when my scrolling becomes laggy while an
image placeholder is being rendered, it's just unnecessary.

So think carefully if you want to take over the resources of your users'
computers, which trades visuals for feel. "Feeling" your website (interacting
with it) is more important than its appearance at all points in the loading
sequence.

------
cabalamat
Am I the only person who finds it ironic that a web page about keeping web
pages small comes with multiple megabytes of Javascript?

It doesn't need it, folks. It's a static blog page.

~~~
limeblack
I'm on mobile right now and therefore it is difficult to look at source but
wouldn't the JavaScript be cached in most scenarios while the images would be
unique per page? On a side note I have no JavaScripts on my own blogs.

~~~
lllr_finger
Besides uncached views (I'm guessing a decent amount of the traffic from HN
for this submission would be) you also have to consider parse/eval time. Look
at the flame charts in Chrome Dev tools for some of your favorite sites and
probably see a few that take almost a second to parse/eval cached JavaScript.
It will be even slower for mobile users.

Just because it can be cached doesn't mean it's free or even necessary.

------
fenwick67
This is the kind of thing that seems really neat (I love computer generated
art) but ultimately the user experience isn't any better than just a solid
rectangle, and you're sending like 1kb more per image to show the placeholder.

~~~
AnkhMorporkian
I disagree. If you have a user on a very slow connection on an image heavy
site, the user experience will be enhanced significantly. Depending on how you
implement it, you might even save them bandwidth. No interesting content for
them in the current viewport and they scroll past the placeholders/go to the
next page? Cancel the XHR requests you made for the full-size
thumbnails/images and start anew.

~~~
rocky1138
I agree with GP. Personally, I hate websites that show a blurry version of an
image before the final one loads. It plays with my eyes. I have to look away
and peek to see if it's done before I can read on.

I wish there was a way to disable this functionality.

~~~
AnkhMorporkian
I didn't mean to refer to blurred images, but the unblurred outline SVGs in
this article. I think the blurred ones are somewhat pointless too. The
unblurred versions give you actual information as to what the image is. For
instance, the sneakers image; if I didn't care about sneakers, I'd be likely
to just scroll past it. In the blurred version, I might not be able to tell
that they're sneakers.

~~~
jmmcd
Interesting: I didn't see any images of sneakers. I saw the Golden Gate
bridge, and a vague shot of a woman. Are they serving a different set of
images (and example js) to different readers?

~~~
AnkhMorporkian
It was in the GIF of the Gatsby 3 implementation in the embedded tweet. Here's
a direct link to the tweet to save you some time:

[https://twitter.com/nystudio107/status/920673966091534338?re...](https://twitter.com/nystudio107/status/920673966091534338?ref_src=twsrc%5Etfw&ref_url=https%3A%2F%2Fmedium.freecodecamp.org%2Fmedia%2F1773750892f5339bc189f993979325e4%3FpostId%3Dbed1b810ab2c)

Edit: Maybe they're not sneakers, but they're shoes. I just wear loafers, I
really have no idea what any shoe types are called.

------
rcarmo
I love the visual effect, but I have to wonder how much CPU/GPU is entailed in
rendering 10-50 triangles, blurring them and rendering the result to the page
canvas vs. loading a pre-blurred image (that might be a "tiny" progressive
JPEG), so I'd probably try to do this server-side first

(edit for clarity: my site currently generates <12Kb blurred placeholders from
high-def photos and only loads visible images to be more mobile-friendly, and
I worry about client-side rendering impacting battery life).

~~~
pbhjpbhj
JPEG has a thumbnail facility built-in I think, did you try using a pre-
created thumbnail scaled up? Or just progressive images?

~~~
rcarmo
I generate blurred thumbnails from my photos, and then output progressive
JPEGs at 80% quality (which is low enough for my purposes and provides a
smooth output)

Code is here:

[https://github.com/rcarmo/sushy/blob/master/sushy/utils.hy#L...](https://github.com/rcarmo/sushy/blob/master/sushy/utils.hy#L179)

The thumbnails you refer to are part of EXIF data, partially designed to allow
digital cameras to render previews inside the camera itself in more resource-
constrained times.

------
robbrown451
I'd like to see some analysis of the psychological side of this. I'm not
convinced these sorts of previews/placeholders are a positive thing, I find
most of them rather distracting. The SVG approach is fine as a novelty, but to
assume that this is the best approach from a user point of view is quite a big
assumption. My intuition is that the hard edges of SVG are more distracting
(attracting your eyes to something that isn't going to give them meaningful
information), but that a blurred image messes with your eyes a bit more. I
wouldn't really like either of them to be used on the majority of sites.

I prefer something very subtle to show that there is an image that is supposed
to be there. If it is going to show a single color rectangle, I prefer it be
translucent so as to attract even less attention.

~~~
askafriend
Anecdata: In a newsfeed-type product at our company, we implemented content
placeholders that communicate loading state instead of a traditional loading
spinner. This reduced user drop off significantly, and bought us some time to
work on the real problem under the hood which was latency.

Aside from my anecdote, there are many blog posts and experiment results out
there that suggests that this works, and it works well.

~~~
robbrown451
What kind of placeholders were they?

Also I have suspicions about what you are measuring being 100% correlated with
"better user experience." Lack of user drop off CAN indicate a better user
experience, but the concept of "click bait" illustrates that you can gain
short term increases in attention in ways that both decrease user experience
and can contribute to driving away users in the long term. I'm not saying this
sort of thing is the same as click bait, but still. I'm sure that in theory,
you could put lots of things in those placeholder spots that will increase the
number of people that wait for the page to load, but may drive away users in
the long term. (e.g. blurry nudes)

------
nightcracker
A while back I made something similar, using Voronoi diagrams to approximate
an image:
[https://codegolf.stackexchange.com/a/50345/4162](https://codegolf.stackexchange.com/a/50345/4162)

Although that was just for fun, not to create image previews or anything of
the sort.

~~~
teej
What went into your decision making process for using Poisson disc sampling?
Did you try other sampling methods? I'd love to know anything else you can
share about how the preprocessing works.

~~~
nightcracker
Honestly, I was just messing around, tried this, and it worked. I used an ad-
hoc modification of Poisson disc sampling I thought of myself to make certain
areas denser / less dense. The preprocessing is also really ad-hoc, just by
looking through functions found in scikit-image to form a heuristic that
seemed appropriate.

------
dwb
How have people come to the conclusion that displaying a low-information
version of the image to be loaded as a placeholder results in a quicker
perceived load? To me all these effects just look rubbish and distracting,
with no benefit at all – certainly not the perception of speed. It's not like
I can ever understand what the image really is before it's fully loaded
anyway, with our without fancy placeholder.

~~~
spurgu
Then use it only for images below the fold?

~~~
hawski
Loading images as soon as they are within viewport is already too late. You
want to load them before user gets there. So you could just not mess up with
native browser loading in the first place. Because all those requests and
client side calculations will add up.

When you have image heavy content please load an image when I'm one or two
page heights before the image. This way when I get there it will already be
there. You could then just use regular single background placeholders, because
I (and I would believe that you also) never intend to see them in the first
place.

------
dlbucci
Really cool use of SVG. I think the 10 shapes method sans the blur would
produce the coolest placeholder images. There's also a pretty impressive level
of detail in the 100 shape images. I might have to look into adding something
like this into one of my own sites!

~~~
WorldMaker
Yeah, I like the impressionist feel of the low shapes. To me I like that it
gives just enough of an impression of the image that is loading that you
aren't too worried if an image is slow to load or fails to load that the gist
still comes across, but is also still rough enough that it gives the
indication that something may still be loading.

------
minimaxir
Another fun thing to do with using SVG-as-images in the browser is easy
animation of the SVG, using Primitive (for example) as noted in the article to
convert an image into SVG shapes, plus a tool like Vivus
([https://maxwellito.github.io/vivus/](https://maxwellito.github.io/vivus/))
or Snap.svg ([http://snapsvg.io](http://snapsvg.io)) to animate each shape of
the SVG.

Here’s a demo I made using Primitive + Vivus:
[http://minimaxir.com/2016/12/primitive/](http://minimaxir.com/2016/12/primitive/)

~~~
baybal2
SVG animation is amazing, but as a person who made work with in-browser
animation and visualization my breadwinner, I can say that usage of JS for
that is a huuuuuge downside

Effectively, you have to rewrite a big part of actionscript functionality into
your browser to do really simple things

It is greatly regrettable than browsermakers have thrown out all declarative
animation features, and never thought of improving on them.

~~~
derefr
Is “declarative SVG animation scripting” really a primitive API you need the
browser to support directly? “Rewriting a big part of Actionscript
functionality” seems like the job of a JS animation framework, not the
browser. Like the ones that animation tools that previously compiled to Flash
(e.g. Adobe Animate itself) use.

~~~
baybal2
JS animations that can approach flash level quality are hard to do.

It is like saying that you don't need native video support, but you use JS to
interpolate initial image.

~~~
derefr
The latter is false because the APIs for image manipulation don't give you
features like hardware video-compression-codec decoding, and so you just can't
really drive a <canvas> fast enough using JS to draw video on it.

The JS graphics+SVG APIs, however, _do_ have all the right primitives exposed
to let you do flash-level animation. It's not a matter of incapability; it's
just a matter of nobody having coded the right framework, or the right
framework (i.e. the one Animate uses) being proprietary and without an open-
source attempt to clone it.

That doesn't suggest browser vendors should step in and put the capability
into the browser, any more than the inability to do realtime 3D without a
framework like three.js or a game engine like Unity's HTML5+WebAssembly
engine, suggests that browsers should create a common, native game-engine-like
API.

------
stuaxo
I'm definitely a fan of this, though I wonder how small 1 bit gifs or pngs
would be for these placeholder silhouette images would be?

There are probably more efficient ways of storing the vectors than SVG too,
which would help the compression - it would be interesting to see how small
these could get.

~~~
abritinthebay
There are none that display cross browser however. Which is an issue.

~~~
vardump
Which current browsers you have in mind that don't support GIFs or Javascript
+ SVG (or canvas)?

~~~
abritinthebay
Gifs don’t support vectors and the comment was talking about a more efficient
format than SVG.

So what on earth are you talking about?

------
lifthrasiir
Once upon a time Facebook had a similar idea for their app [1] (similar to the
OP's use case, because the preview photo was to be included to the initial
response). It makes use of the stock JPEG decoder but with the fixed Huffman
tree and size to meet the 200-byte size limit. A careful implementation may
also work in the Web even without JavaScript.

[1] [https://code.facebook.com/posts/991252547593574/the-
technolo...](https://code.facebook.com/posts/991252547593574/the-technology-
behind-preview-photos/)

------
baybal2
A real game changing technique!

Why? To use progressive JPG, you have to pre-recode (if you don't have money
to dish out for FPGA to recode on the fly) and store recoded images. With
this, you don't have to alter the original image.

My favorite method was to use img tag with blur, you programmatically add
image, then you wait when, say 10% of this it is loaded, and abort the
request. It will stay that way. When you need to fully load it, you start
loading, look for progress events, and set blur accordingly.

~~~
romaniv
_> To use progressive JPG, you have to pre-recode (if you don't have money to
dish out for FPGA to recode on the fly) and store recoded images._

Not sure why progressive JPG isn't the default. It's not any larger.

~~~
DamonHD
The rules of thumb seem to be that (a) for JPEGs under 10kB progressive may
actually be larger and (b) for mobile devices the extra effort (CPU, memory)
of progressive decode may be significant eg in taking time away from other
parts of page rendering.

------
Tolika
As stated in the article, generating the SVG to use as a placeholder can be
very expensive.

I, myself fiddled with the idea in one of my side-projects and ended up using
the technique where I save the dominant colors from an image, which I’m using
to create a CSS gradient as the placeholder. The effect can be seen on
[https://epicpxls.com](https://epicpxls.com)

------
baybal2
I wonder, how many users here know about progressive jpeg, and about the trick
with partially loading progressive jpeg file?

~~~
cisanti
What is the trick? I do know progressive images and use them, others argue its
bad ux seeing the shitty version first.

~~~
baybal2
You create Image objects from images loaded with xhr that are, say, loaded
only 10%, then you blur it with SVG or native CSS filters

------
mncolinlee
For small icons and images, this is fine and actually pretty cool. However,
the rasterization cost of SVG into large images can be significant on mobile
device CPUs. It won't speed things up much if the device is rasterizing a lot.
That should be taken into account if you're mobile first or building a mobile
app.

------
kylemathews
If you want to see this in action in Gatsby, checkout [https://using-gatsby-
image.gatsbyjs.org/traced-svg/](https://using-gatsby-
image.gatsbyjs.org/traced-svg/)

It's super easy to integrate this into your site w/ our Image component &
GraphQL fragment.

See the source code for the page:
[https://github.com/gatsbyjs/gatsby/blob/master/examples/usin...](https://github.com/gatsbyjs/gatsby/blob/master/examples/using-
gatsby-image/src/pages/traced-svg.js)

And component documentation [https://www.gatsbyjs.org/packages/gatsby-
image/](https://www.gatsbyjs.org/packages/gatsby-image/)

------
jankovicsandras
This looks interesting. Here's a shameless plug if somebody needs tracing:

ImageTracer is a simple raster image tracer and vectorizer that outputs SVG,
100% free, Public Domain.

Available in JavaScript (works both in the browser and with Node.js),
"desktop" Java and "Android" Java:

[https://github.com/jankovicsandras/imagetracerjs](https://github.com/jankovicsandras/imagetracerjs)

[https://github.com/jankovicsandras/imagetracerjava](https://github.com/jankovicsandras/imagetracerjava)

[https://github.com/jankovicsandras/imagetracerandroid](https://github.com/jankovicsandras/imagetracerandroid)

------
peteretep
Reading through the comments I'm clearly in the minority, but:

For many of these I like the SVG as much as the full image, and start to
wonder if the preview/placeholder makes having the actual image irrelevant.

------
ww520
I think the silhouette version is the best in transitioning from the summary
to the full detail.

------
frandroid
This is an interesting technique for stills; I'd be curious to see it applied
to video...

~~~
fogleman
It's been done! This one gets progressively more detailed:

[https://www.youtube.com/watch?v=PyAkgS6Xl1Q](https://www.youtube.com/watch?v=PyAkgS6Xl1Q)

Here's one someone else did:
[https://vimeo.com/210854333](https://vimeo.com/210854333)

------
IshKebab
Are those SVGs actually smaller than JPEGs included using data URLs?

~~~
dmitriid
> Actually, the code for the SVG with 10 shapes is really small, around 1030
> bytes, which goes down to ~640 bytes when passing the output through SVGO.

> The images generated with 100 shapes are larger, as expected, weighting ~5kB
> after SVGO (8kB before).

Looking at images that randomly appear on my hard drive:

\- 1KB PNG image is a tiny image, 45x30 pixels. Just the Base64 part of it's
data uri version is 1476 characters in length

\- A two-color 152x30px PNG image containing simple text and a logo is already
3KB. It's base64 is 3344 characters in length

I don't have any small JPEGs though. The smallest I have is a selfie, 960x960
pixels. It's 79KB in size.

My guess is that you probably can produce a tiny JPEG/PNG that would beat SVG,
but you'd have to play around with a lot of settings for it: reduce quality
etc.

------
antod
Reminds me of that old mid 90s fractal image format that never took off. When
you zoomed in, the photos started turning into shapes of colour blocks rather
than raster pixels.

------
pastelsky
Is it just me or does anyone else think LQIP on medium are annoying? They
become sharp after waiting for a long time and at times never load at all.

------
rubberduckllc
Looks interesting. Any interest in building a SaaS model on top of this?

------
hasenj
Am I the only one who found the thing awkward and offputting?

