CSS flags
How I made this
I was inspired by Josh Comeau’s article on animating flags. His technique was only for flags made of horizontal stripes, but I figured I could make it work for more complicated designs.
Comeau and I have used LGBT+ flags, both to illustrate the CSS techniques and to show support for Pride.
Waving animation
Josh Comeau divided the flag into vertical strips and moved the strips up and down with a CSS animation. Each strip moves at different times to create the over-all wave.
The left side is tethered to an invisible flagpole. The distance each strip moves is calculated from its index (its position in the sequence from left to right), so the left-most strip doesn’t move at all and the right-most strip is the one that moves the farthest.
I have copied Comeau’s animation code, with minor differences:
- I added an
animation-play-state
property to toggle between playing and paused. - Comeau has versions where the flag is and isn’t tethered to a flagpole.
- What he calls “billow”, I call “wave amplitude” (describing the whole flag) or “displacement” (describing a strip), because I’m a nerd.
Also, Comeau doesn’t let the number of strips go below 3, but I allow you to go down to 1. The effect is that if there’s only one strip, there’s no movement at all, since the left-most strip is always against the flagpole. You simply see the flag as a static rectangle.
Gradients
I have drawn a flagpole (and ground, and sky) to give the flag some visual context. But the main difference between Comeau’s flag animations and mine is that my flags don’t have to be horizontal stripes.
In Comeau’s version, each strip was filled with a vertical linear gradient, with hard stops between colours to give the flag proper stripes. This works perfectly for flags that consist only of horizontal stripes; his three examples were the Philadelphia eight-stripe rainbow, the transgender flag, and the pansexual flag.
But I was wondering whether I could make it work for any flag that can be made out of CSS gradients, or indeed any rectangular flag.
So I put the same background-image
property on each strip, but I use the background-size
and background-position
properties to make each strip into the correct segment of the flag.
The image itself is composed of at least one gradient (depending on the flag), with linear, radial, and conical gradients overlaid in front of each other to produce the flag’s design.
This technique of overlaying gradients means that the flag can now have stripes in different directions (as in a cross), or chevrons (as in the progressive pride flag), or circles (as in the intersex flag).
UK flag
I can almost do the entire UK flag, but the diagonal red stripes are impossible to recreate purely with gradients. Those stripes are supposed to be of constant width (of 4% of the horizontal width of the flag), and offset so that they’re each on the anti-clockwise side of the white diagonal stripes that they lie on front of.
The best I can do is either to use two linear gradients, which makes the widths of the stripes constant but makes the offsets of two of the four red diagonals wrong; or use one conical gradient, which makes the offset okay but the stripes wedge-shaped. Another problem with the conical gradient is that, in the absense of trigonometric functions, I can create the gradient for one aspect ratio only (5:3 or 1.67). (Trigonometry is coming to CSS, but not yet widely supported.)
To get around these limitations, I can use the background-image
property with the URL of an image file, instead of gradients.
So I found an SVG version of the flag on Wikimedia Commons and made it one of my flag options too.
(I then found its aspect ratio wouldn’t change from 5:3, so I set preserveAspectRatio="none"
on its <svg>
element.)
It’s kinda cheating to call it a CSS flag. But it’s an option. 🇬🇧
Controls
Josh Comeau had controls on his flag demos, such as for the design of flag (rainbow or trans), the number of strips (or segments) to divide the flag into, and the amplitude of the wave (the amount of billow).
CSS variables (custom properties) make these factors easy to manage.
I added more controls to really show off the CSS variables. Adapting flags to look decent in different aspect ratios was a little extra challenge.
Pixel gaps
If you’re seeing thin gaps between strips, try adjusting the size or aspect ratio of the flag, or the number of strips. Or switch to a Chromium browser (such as Opera or Chrome), since Chromium seems to render the strips better than Firefox or Safari. (It’s a rounding error.)
Similarly, the ring on the intersex-inclusive progress flag changes thickness when the flag’s aspect ratio changes, unless you’re in Chromium. This is another rounding error.
And for the Irish flag, if the number of strips is a multiple of three, all strips should be a solid colour. Chromium does this nicely; Firefox and Safari aren’t perfect. That’s actually the only reason I included a flag with vertical stripes. (Although I really like the shades of green and orange.)
Flag choice
I’ve picked several LGBT+ flags, to show off different gradients and combinations thereof. (And also to celebrate Pride, of course! I published this on the day of my city’s Pride 2023 events.)
I also have the flags of England, Scotland, and the UK, since the latter flag is made up of the other two flags (plus Northern Ireland’s diagonal stripes). Unfortunately I couldn’t get those diagonal stripes correct.
And Ireland’s in here so I could see some plain vertical stripes. Then I added Wales as well, or rather St David’s flag. I would have done the official flag, but the dragon doesn’t lend itself to gradients.
Colours are mostly taken from files on Wikimedia Commons, but I have not copied all of the colours and measurements exactly. I tweaked some of the rainbow colours, for example.
But anyway, happy Pride! It’s always a good time to elevate queer voices, celebrate our achievements, and defend our rights to live as our gender and to love who we love. 🏳️🌈
Flag design credits
- Eight-stripe rainbow flag
- Gilbert Baker, 1978
- Bisexual flag
- Michael Page, 1998
- Transgender flag
- Monica Helms, 1999
- Asexual flag
- Asexual Visibility and Education Network, 2010
- Pansexual flag
- Tumblr blog PansexualFlag, 2010
- Intersex flag
- Morgan Carpenter, 2013
- Nonbinary flag
- Kye Rowan, 2014
- Progressive pride flag
- Daniel Quasar, 2018
- Intersex-inclusive progressive pride flag
- Valentino Vecchietti, 2021