Contents
It started from this tweet by a game developer mentioning game libraries should always include a 1×1 transparent PNG image. Well, I don’t know much about game development or why it’s needed, but, I know a thing or two about such files.
I replied with two data URLs: one for a transparent PNG, but also one for a transparent GIF, which is shorter, and would likely work just as well. My post somehow got a lot of attention. Who knew people needed transparent pixels so much? (Or maybe some just found sharing such a file as a data URL embedded in a single tweet was ingenious. I didn’t ask.)
I was not wrong in giving that… but I woke up the night after at 2 AM and somehow my 30 years of Web development experience barged in and made me think, “Wait… no… those URLs are wrong!” Oh no. Here I was realising I copied those URLs from some old notes when I was toying with image files and data URLs before coming up with the correct ones. I was spreading misinformation. Soon, the Community Notes will come after me, for sure!
Then again, I’m not sure anyone has tried them yet. And they should remember, as Homer Simpson said, “Don’t trust anyone over 30!”
While my reply on there is still warm, it is time for me to be transparent about my mistake.
But first…
A bit of history
In Web development back in the 90s, we used to call 1×1 transparent image files “spacers.”
In those days, us web developers didn’t have the fancy CSS we have today that lets us do everything from rounded corners to 3D. We often relied on <table>s to render layouts: we would flatten layers of an image we edited in something like Photoshop or Macromedia Fireworks (RIP), and then slice it into cells of images and text. Doing so was the best we could do to make our layouts pixel-perfect, while the multiple files allowed faster parallel downloads over the slower connections of the day. For the transparent empty parts of the layout, to avoid waste with multiple files, we usually filled them with a 1×1 transparent image, scaled to the size of its cell.
That did a pretty good job, but we didn’t stop there. For maximum optimisation, people would obsess on making the smallest transparent pixel file possible, down to what could be shaved off its headers and colour palette. Any byte shaved off meant a faster website, both in transfer and rendering. (Also, we didn’t have data URLs back then, so even small files couldn’t just be embedded in the HTML code—they were always external, requiring more data transfer, like HTTP headers.)
People focused on GIF files and its then-new transparent ability as defined in the CompuServe GIF89a format, as PNG was nascent. Still today, GIF spacers still win in file size, as even the small PNG file has more overhead.
Finally the Internet settled one the Spacer GIF. With its 43 bytes, it is still the smallest widely compatible and standards-respecting transparent 1×1 GIF image in common use today.
Making the perfect smallest spacer was an achievement from which we all benefited. If all this work in making empty areas right doesn’t convince you how much negative space in design matters, I don’t know what will.
Spacers today?
While we no longer use spacers for sizing layouts, they are still of use.
They’re used as sentinels in config defaults, API fallbacks, and tests, to name a few examples.
They’re also found as placeholders in <canvas>, WebGL, loading states, UI skeletons… and, I assume, as blank textures in game engines.
I personally have them on some pages to swap out large images that are out of view while scrolling, to improve memory and graphics performance.
Yes, rest assured, this 90s relic still has its practical uses today!
The spacer files
My favourite terminal image tool, ImageMagick, is what I’ll use not only to generate spacer files later, but also to review them.
Before I hand you actual transparent spacer files that will work, let’s review the URLs I gave:…
The URLs in my reply
I can’t remember how I came up with those a long time ago. From my source code of various websites, it seems I never actually used them. But in any case, let’s just have a look at what they are:
1×1 white pixel
data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==
By the way, if you need help on how to convert the base64 data in the URL into an actual file, you simply copy the data part after base64, open a terminal, and pipe it in the base64 command:
echo R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw== | base64 -d pixel.gif
If you open that, you’ll see a 1×1 pixel, yes, but it is white; not transparent. Then again, it’s a bit hard to see the pixel or to know if it’s transparent or not, so you can always list the colours with ImageMagick:
magick pixel.gif -colorspace RGB -unique-colors txt:
# ImageMagick pixel enumeration: 1,1,0,255,rgb
0,0: (255,255,255) #FFFFFF rgb(255,255,255)
There. Just one colour, white, no alpha channel.
You may still find it useful, but just keep in mind it is not transparent.
Broken PNG
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAAAAAA6fptVAAAAC0lEQVR42mP8/xcAAwMCAO7+2d4AAAAASUVORK5CYII=
That one was a broken PNG. It’s structurally invalid—not simply “non-transparent”—which makes it unreliable.
Not sure where I got that one before either. Maybe it worked somewhere a long time ago and I just forgot? Anyway. With the same base64 tricks as earlier, I can confirm any image viewer that the file is corrupted. ImageMagick reports the same:
magick: IDAT: incorrect data check `pixel.png' @ warning/png.c/MagickPNGWarningHandler/1531.
magick: IDAT: CRC error `pixel.png' @ error/png.c/MagickPNGError/1305.
So, don’t use that.
The Internet’s old-school favourite
As they say, Spacergif.org is “home of the Internet’s spacer.gif.”
You can download it with the link above. Or, if you need to embed it, using my own file2dataurl script, I downloaded the small file in the terminal using wget and turned it into a data URL for you:
wget https://img.spacergif.org/spacer.gif
file2dataurl spacer.gif
data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEAAAEALAAAAAABAAEAAAICTAEAOw==
ImageMagick confirms its transparent:
# ImageMagick pixel enumeration: 1,1,0,255,rgba
0,0: (255,255,255,0) #FFFFFF00 rgba(255,255,255,0)
Smaller alternatives
User bryc on Stack Overflow experimented a lot with different ways to shave some bytes off the files.
35 bytes
The smallest size they came up with was 35 bytes:
data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEAAAAALAAAAAABAAEAAAIBAAA=
But beware, it may be unreadable in some browsers. Sometimes it may work and then stop working in a future update. Use it at your own risk. YMMV. Although even ImageMagick can read it:
0,0: (0,0,0,0) #00000000 rgba(0,0,0,0)
41 bytes
Another one they made is just 2 bytes fewer than the 43-byte one most of us use today:
data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAAAAAAALAAAAAABAAEAAAIBAAA=
They mentioned it works in all browsers but may break in other parsers. So if you want to use that somehow in a game library, maybe it’s best to avoid it and go with the safest one with the best compatibility.
ImageMagick reported the file as being opaque; not transparent. In this case, the GIF Graphic Control Extension (GCE) exists, but the transparency flag itself is off—meaning no palette index is actually treated as transparent. Something browsers forgive this and will render it as “invisible,” which ImageMagick correctly does not.
42 bytes
Digging in my collection of snippets, I found the details of a 42-byte file:
data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
Huh? Who knows how I came up with that one or where I found it… Again, something I cannot recreate with ImageMagick.
(Guess I’ll update my snippets after this. The link above points to the version of the file I found today.)
Making your own spacer files
ImageMagick carries its name well: it does magic with images. So you too can use it at home to make your own small spacer files!
I also use image_optim to optimise the image data for smaller files. It’s an old Ruby wrapper for other tools including gifsicle for GIF, and optipng and oxipng for PNG. To illustrate, I’ll use the more direct tools to show you how the files get reduced in size step by step.
1×1 white GIF image
We already have a white pixel from earlier, but let’s make a fresh one:
magick -size 1x1 xc:white -depth 1 pixel.gif # 43 B
gifsicle --optimize=3 --interlace --no-extensions --no-app-extensions --no-comments --no-names --same-delay --same-loopcount --no-warnings -o pixel.gif pixel.gif # 35 B
We started from 43 bytes down to 35:
data:image/gif;base64,R0lGODdhAQABAPAAAP///wAAACwAAAAAAQABAEACAkQBADs=
1×1 transparent PNG image
Let’s compare GIF to PNG output sizes for a moment:
magick -size 1x1 xc:none -depth 1 png8:pixel.png # 308 B
optipng -strip all -i0 -o 6 -quiet pixel.png # 95 B
oxipng --strip all -i0 -o 3 --quiet pixel.png # 71 B
advpng --recompress -4 --quiet pixel.png # 71 B
As I mentioned earlier, PNG has quite some overhead, which is fine for large images, but here… we initially had 308 bytes! Down to 71 after optimisation. Still 65% bigger than the smallest transparent pixel GIF!
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAADklEQVR42gEDAPz/AAAAAAMAAeQuSDsAAAAASUVORK5CYII=
1x1 transparent GIF image
Now for our pièce de transparence, let’s make our own rival to the earlier spacer.gif:
magick -size 1x1 xc:none -depth 1 pixel.gif
Like the Internet’s favourite spacer, ours is 43 bytes. We didn’t even need to optimise it. You can try, if you want, but you’ll see the output will stay the same:
gifsicle --optimize=3 --interlace --no-extensions --no-app-extensions --no-comments --no-names --same-delay --same-loopcount --no-warnings -o pixel.gif pixel.gif # Still 43 bytes
However, the data URL is slightly different:
data:image/gif;base64,R0lGODlhAQABAPAAAAAAAAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==
GIF allows multiple valid encodings for the same visual result (palette order, LZW codes, metadata), so byte-identical output is not guaranteed across tools. And as far as I know, it doesn’t need to. ImageMagick confirms it is a bona fide transparent pixel:
# ImageMagick pixel enumeration: 1,1,0,255,rgba
0,0: (0,0,0,0) #00000000 rgba(0,0,0,0)
If you can’t make it somehow, here’s one you can just get from me:
Download 1×1 Transparent GIF Spacer
Deconstructing the data
Okay, we’re done with the spacer. But just out of curiosity… What does it actually contain?
I know many of you want to hate on AI right now, but hey, it’s pretty decent at deconstructing this kind of thing for you. Aren’t you the least bit curious about how the data is structured in those 43 bytes we just made?
ChatGPT may not work well with the actual image file, let’s dump it in hexadecimal format:
xxd pixel.gif
00000000: 4749 4638 3961 0100 0100 f000 0000 0000 GIF89a..........
00000010: 0000 0021 f904 0500 0000 002c 0000 0000 ...!.......,....
00000020: 0100 0100 4002 0244 0100 3b ....@..D..;
Cool but wow… that’s a lot of tokens for just a simple dump of such a small file. Let’s make it more machine-friendly by just outputting the hexadecimal data:
xxd -p pixel.gif
47494638396101000100f0000000000000000021f90405000000002c0000
0000010001004002024401003b
There. Clean and simple.
So here’s what ChatGPT said about it:
47 49 46 38 39 61 GIF89a
01 00 01 00 Logical screen: 1×1
f0 GCT present, size = 16 entries
00 Background index
00 Aspect ratio
00 00 00 ... Global Color Table (padded)
21 f9 04 Graphic Control Extension
05 Packed fields (transparency ON + disposal)
00 00 Delay
00 Transparent color index = 0
00 Block terminator
2c Image Descriptor
00 00 00 00 Left, top
01 00 01 00 Width, height = 1×1
40 Local color table flag set
02 LZW min code size
02 Sub-block length = 2
44 01 LZW data (2 bytes)
00 Block terminator
3b Trailer
Cool. Feel free to compare with the compression example on Wikipedia. Not knowledge we’ll use on the daily, but still… It’s like we’re doing archeology on a data format older than 35 years! Just to think transparency in GIF files was introduced the same year than Tim Berners-Lee proposed the World Wide Web.
What about other formats?
Well, you’ve seen the good and the bad, so now let’s look at the ugly. Before we end, here’s a quick comparison of different transparent 1×1 pixel file formats with a few extra ones you shouldn’t even consider:
| Format | Transparent | Typical size (1×1) | Notes |
|---|---|---|---|
| GIF89a | Yes | 43 bytes | Smallest widely compatible, easy to generate |
| GIF89a | Yes | 42 bytes | Spec-legal, likely hand-optimized |
| GIF89a | No (See note) | 41 bytes | Sometimes “invisible” in forgiving browsers |
| PNG8 | Yes | ~65–75 bytes | Chunk/CRC overhead |
| PNG32 | Yes | 90+ bytes | Never worth it for a spacer |
| SVG | Yes | Variable | Come on… A vector file in XML format for a 1×1 pixel? |
Note: The 41-byte GIF is visually deceptive, not true transparency.
If you want more transparent pixels to compare, Wikipedia has more than a dozen! Even they can’t seem to be able to pick a single one.
There you have it. A single pixel carrying 30 years of baggage.
Now go paint the town… transparent!
(It’s time I go share this on that thread of mine from earlier.)
