United States Flag SVG Image

Feeling patriotic during the election count, I decided to handcraft an SVG of the United States flag. How hard could it be? Red background, white stripes, blue canton, and white stars. Wikipedia lists the specifications.

Creating the stars was a challenge, but I used a spreadsheet to calculate the vertices’ coordinates, which I then cut and pasted into an SVG path. From there, it was creating the backgrounds and placing the stars. Easy peasy.

Here’s the image and its brute force code:

US Flag
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 190 100">
  <symbol id="star" width="6.477" height="6.477" viewBox="-3.2385 -3.2385 6.477 6.477">
    <path fill="#fff" stroke-width="0" d="M0.000 -3.080, 0.691 -0.952, 2.929 -0.952, 1.119 0.364, 1.810 2.492, 0.000 1.176, -1.810 2.492, -1.119 0.364, -2.929 -0.952, -0.691 -0.952, 0.000 -3.080" />

  <rect width="190" height="100" fill="#C1133D" />

  <rect y="7.69" width="190" height="7.69" fill="#fff" />
  <rect y="23.07" width="190" height="7.69" fill="#fff" />
  <rect y="38.45" width="190" height="7.69" fill="#fff" />
  <rect y="53.83" width="190" height="7.69" fill="#fff" />
  <rect y="69.21" width="190" height="7.69" fill="#fff" />
  <rect y="84.59" width="190" height="7.69" fill="#fff" />

  <rect width="76" height="53.85" fill="#002663" />

  <use href="#star" x="3.0915" y="2.1415" />
  <use href="#star" x="15.7515" y="2.1415" />
  <use href="#star" x="28.4115" y="2.1415" />
  <use href="#star" x="41.0715" y="2.1415" />
  <use href="#star" x="53.7315" y="2.1415" />
  <use href="#star" x="66.3915" y="2.1415" />

  <use href="#star" x="9.4215" y="7.5215" />
  <use href="#star" x="22.0815" y="7.5215" />
  <use href="#star" x="34.7415" y="7.5215" />
  <use href="#star" x="47.4015" y="7.5215" />
  <use href="#star" x="60.0615" y="7.5215" />

  <use href="#star" x="3.0915" y="12.9015" />
  <use href="#star" x="15.7515" y="12.9015" />
  <use href="#star" x="28.4115" y="12.9015" />
  <use href="#star" x="41.0715" y="12.9015" />
  <use href="#star" x="53.7315" y="12.9015" />
  <use href="#star" x="66.3915" y="12.9015" />

  <use href="#star" x="9.4215" y="18.2815" />
  <use href="#star" x="22.0815" y="18.2815" />
  <use href="#star" x="34.7415" y="18.2815" />
  <use href="#star" x="47.4015" y="18.2815" />
  <use href="#star" x="60.0615" y="18.2815" />

  <use href="#star" x="3.0915" y="23.6615" />
  <use href="#star" x="15.7515" y="23.6615" />
  <use href="#star" x="28.4115" y="23.6615" />
  <use href="#star" x="41.0715" y="23.6615" />
  <use href="#star" x="53.7315" y="23.6615" />
  <use href="#star" x="66.3915" y="23.6615" />

  <use href="#star" x="9.4215" y="29.0415" />
  <use href="#star" x="22.0815" y="29.0415" />
  <use href="#star" x="34.7415" y="29.0415" />
  <use href="#star" x="47.4015" y="29.0415" />
  <use href="#star" x="60.0615" y="29.0415" />

  <use href="#star" x="3.0915" y="34.4215" />
  <use href="#star" x="15.7515" y="34.4215" />
  <use href="#star" x="28.4115" y="34.4215" />
  <use href="#star" x="41.0715" y="34.4215" />
  <use href="#star" x="53.7315" y="34.4215" />
  <use href="#star" x="66.3915" y="34.4215" />

  <use href="#star" x="9.4215" y="39.8015" />
  <use href="#star" x="22.0815" y="39.8015" />
  <use href="#star" x="34.7415" y="39.8015" />
  <use href="#star" x="47.4015" y="39.8015" />
  <use href="#star" x="60.0615" y="39.8015" />

  <use href="#star" x="3.0915" y="45.1815" />
  <use href="#star" x="15.7515" y="45.1815" />
  <use href="#star" x="28.4115" y="45.1815" />
  <use href="#star" x="41.0715" y="45.1815" />
  <use href="#star" x="53.7315" y="45.1815" />
  <use href="#star" x="66.3915" y="45.1815" />

Then it was time to optimize.

  • Correct the size of the stars
  • Better, more realistic, colors
  • Use of g and use to decrease file size

Here’s the resulting image and its code:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 190 100">
  <symbol id="star" width="6.477" height="6.477">
    <path fill="#e3ded4" d="M3.2385 0.1585, 3.9300 2.2867, 6.1678 2.2867, 4.3574 3.6020, 5.0489 5.7303, 3.2385 4.4150, 1.4281 5.7303, 2.1196 3.6020, 0.3092 2.2867, 2.5470 2.2867" />

  <rect width="190" height="100" fill="#9b1c2c" />

  <g id="two_white_stripes">
    <rect id="white_stripe" y="7.6923" width="190" height="7.6923" fill="#e3ded4" />
    <use href="#white_stripe" y="15.3846" />
  <use href="#two_white_stripes" y="30.7692" />
  <use href="#two_white_stripes" y="61.5384" />

  <rect width="76" height="53.8461" fill="#33335f" />

  <g id="four_rows">
    <g id="two_rows">
      <g id="long_row">
        <g id="five_stars">
          <g id="two_stars">
            <use id="first_row_star" href="#star" x="3.0915" y="2.1415" />
            <use href="#first_row_star" x="12.66" />
          <use href="#two_stars" x="25.32" />
          <use href="#first_row_star" x="50.64" />
        <use href="#first_row_star" x="63.3" />
      <use href="#five_stars" x="6.33" y="5.38" />
    <use href="#two_rows" y="10.76" />
  <use href="#four_rows" y="21.52" />
  <use href="#long_row" y="43.04" />

Finally, judicious use of SVGOMG to:

  • Eliminate whitespace
  • Convert shapes to paths
  • Decrease unnecessary precision
  • Shorten ID names
  • A bunch of other stuff

Seriously, if you’re into optimizing SVGs and you’re not using something like SVGOMG, you’re working too hard.

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 190 100"><symbol id="c" width="6.48" height="6.48"><path fill="#e3ded4" d="M3.24.16l.69 2.13h2.24L4.36 3.6l.69 2.13-1.81-1.32-1.81 1.32.69-2.13L.31 2.3h2.24"/></symbol><path fill="#9b1c2c" d="M0 0h190v100H0z"/><g id="b"><path id="a" fill="#e3ded4" d="M0 7.69h190v7.69H0z"/><use href="#a" y="15.38"/></g><use href="#b" y="30.77"/><use href="#b" y="61.54"/><path fill="#33335f" d="M0 0h76v53.84H0z"/><g id="h"><g id="g"><g id="i"><g id="f"><g id="e"><use id="d" href="#c" x="3.09" y="2.14"/><use href="#d" x="12.66"/></g><use href="#e" x="25.32"/><use href="#d" x="50.64"/></g><use href="#d" x="63.3"/></g><use href="#f" x="6.33" y="5.38"/></g><use href="#g" y="10.76"/></g><use href="#h" y="21.52"/><use href="#i" y="43.04"/></svg>

Only 783 bytes! Not bad, considering my first version is 3.08k.

Feel free to download and use without limitations.

Update. Code is never done, and this is no exception. Looking at another flag’s SVG code, I realized that I could eliminate the decimal point with appropriate scaling.

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 19000 10000">
  <symbol id="star" width="648" height="648">
    <path fill="#e3ded4" d="M324 16, 393 229, 617 229, 436 360, 505 573, 324 442, 143 573, 212 360, 31 229, 255 229" />
  <rect width="19000" height="10000" fill="#9b1c2c" />
  <g id="two_white_stripes">
    <rect id="white_stripe" y="769" width="19000" height="769" fill="#e3ded4" />
    <use href="#white_stripe" y="1538" />
  <use href="#two_white_stripes" y="3077" />
  <use href="#two_white_stripes" y="6154" />
  <rect width="7600" height="5384" fill="#33335f" />
  <g id="four_rows">
    <g id="two_rows">
      <g id="long_row">
        <g id="five_stars">
          <g id="two_stars">
            <use id="first_row_star" href="#star" x="309" y="214" />
            <use href="#first_row_star" x="1266" />
          <use href="#two_stars" x="2532" />
          <use href="#first_row_star" x="5064" />
        <use href="#first_row_star" x="6330" />
      <use href="#five_stars" x="633" y="538" />
    <use href="#two_rows" y="1076" />
  <use href="#four_rows" y="2152" />
  <use href="#long_row" y="4304" />

The resulting SVGOMG-optimized code is 738 bytes small!

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 19000 10000"><symbol id="c"><path fill="#e3ded4" d="M324 16l69 213h224L436 360l69 213-181-131-181 131 69-213L31 229h224"/></symbol><path fill="#9b1c2c" d="M0 0h19000v10000H0z"/><g id="b"><path id="a" fill="#e3ded4" d="M0 769h19000v769H0z"/><use href="#a" y="1538"/></g><use href="#b" y="3077"/><use href="#b" y="6154"/><path fill="#33335f" d="M0 0h7600v5384H0z"/><g id="h"><g id="g"><g id="i"><g id="f"><g id="e"><use id="d" href="#c" x="309" y="214"/><use href="#d" x="1266"/></g><use href="#e" x="2532"/><use href="#d" x="5064"/></g><use href="#d" x="6330"/></g><use href="#f" x="633" y="538"/></g><use href="#g" y="1076"/></g><use href="#h" y="2152"/><use href="#i" y="4304"/></svg>

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="http://www.w3.org/2000/svg" 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="http://www.w3.org/2000/svg" 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="http://www.w3.org/2000/svg" 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

Update 4. I continue to update the heading to match my ever-changing theme.

Brent Logan