Breathe SVG

Playing with SVGs is fun. Making them by hand and optimizing them, even more so.

The “Brent Logan” with the embedded heart in this site’s heading is an SVG. The heart at the bottom of each post is an SVG. This “breathing” circle is an SVG.

I’m amazed how small SVGs can be. This circle, including the animation, is less than 240 characters. That’s smaller than a tweet.

Here’s the code:

<svg xmlns="" viewBox="0 0 2 2"><circle cx="1" cy="1" r="1" fill="#08c" style="animation:b 9s infinite"/><style>@keyframes b {0%,to{transform-origin:center;transform:scale(.2)}50%{transform:scale(1)}}</style></svg>

I started this exercise animating the heart to “breathe.” I wanted something to watch and synchronize my breathing with to relax and destress. I knew SVG would be a quick way to get there. So I modified the “beating heart” SVG I already had.

Here’s the modified “breathing heart” code:

<svg viewBox="0 0 24 22"><path stroke="#c23" stroke-linecap="round" stroke-width="13" d="M6.6 6.6q1 3 5 6 4-3 5-6" style="animation:b 9s infinite"/><style>@keyframes b{0%,to{transform-origin:center;transform:scale(.2)}50%{transform:scale(1)}</style></svg>

Although it’s only 290 characters, I knew I could go smaller, hence, the breathing circle.

Along the way, I learned interesting things about defaults, browser prefixing, and CSS animation. Good times!

Update. I got the breathing circle down to 147 characters! That’s barely larger than an old-style tweet.

<svg xmlns="" viewBox="-4 -4 8 8"><circle/><style>circle{r:4;animation:b 9s infinite}@keyframes b{50%{r:1}}</style></svg>

Yeah, I did lose a little along the way: the circle is now black and the smaller size changed slightly.

Using what I learned on the breathing circle, I was able to get the breathing heart down to 232 characters. That’s smaller than the blue breathing circle at the top of this post!

<svg xmlns="" viewBox="-12 -10 24 22"><path d="M-5-3q1 3 5 6 4-3 5-6"/><style>svg{animation:b 9s infinite;stroke:#c23;stroke-width:13;stroke-linecap:round}@keyframes b{50%{transform:scale(.2)}</style></svg>

I kept the heart’s color as-is!

Update 2. I kept reading that the xmlns namespace attribute wasn’t necessary for an SVG that’s embedded directly within an HTML document, but I couldn’t make it happen in WordPress without the SVG code getting munged. That is, until I tried putting it in an HTML sidebar widget. Only 112 characters!

<svg viewbox="-4 -4 8 8"><circle/><style>circle{r:4;animation:b 9s infinite}@keyframes b{50%{r:1}}</style></svg>

Interestingly, the success is not universal. It seems to work everywhere except Firefox which complains about r as an invalid property. It’s not interpreting it as an SVG. I also discovered that uBlock Origin notices its initial size is zero pixels and blocks it as a potential web tracker.


My blog now has a heartbeat — I it!

For those that are interested in the technical details, read on. The rest of you can stop right here.

tl;dr. In the header and footer, the graphic is a background SVG with embedded CSS scaling the heart element. The standalone hearts also are an SVG, this time with external CSS. In both cases, the CSS controls scaling.

First, I created a PNG of the text and heart with a screen capture from Keynote. Then I used an online PNG to SVG converter, the result of which I edited with a text editor to embed the CSS that animates the heart element. The embedded CSS is based on the hovering heartbeat animation CodePen by Joseph Emmerich. I modified the CSS to add transform-origin: 50% 50% immediately before each transform: scale() style to prevent the heart from moving when its scale changes. Finally, I used image replacement on the title text.

So far, I’ve tested it only on MacOS browsers. It works on WebKit-based browsers (Chrome, Opera, Brave, and Safari), but not Firefox. I still need to test on Windows browsers, and probably add a fallback static PNG for browsers that don’t support background SVGs.

Update. Since creating my first heading image, I created others with a lighter font and decreasing the frequency of animation.

Brent Logan

Update 2. Any modern browser now supports background SVGs.

Update 3 (1 Mar 2019). I’ve again changed the appearance of my site, so I have a new header image to match.

Brent Logan