<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Bjango Articles</title><link>https://bjango.com/articles/</link><description>Articles about design, code, music, and Bjango</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Mon, 05 May 2025 19:47:26 +1000</lastBuildDate><atom:link href="https://bjango.com/rss/articles.xml" rel="self" type="application/rss+xml"/><item><title>The vocal effects of Daft Punk</title><link>https://bjango.com/articles/daftpunkvocaleffects/</link><pubDate>Mon, 05 May 2025 19:47:26 +1000</pubDate><guid>https://bjango.com/articles/daftpunkvocaleffects/</guid><description>&lt;p&gt;Daft Punk have used a wide variety of vocal effects in their songs. A May 2001 interview in Remix magazine provided a rare insight from Daft Punk themselves on the topic.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/daftpunkvocaleffects/daft-punk-3.jpg" alt="A photo of Daft Punk in a field on a sunny day."&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://web.archive.org/web/20060103075925/http://remixmag.com/mag/remix_robopop/"&gt;“People always ask us what vocoder we use, but every one of our vocal tracks uses a different vocoder effect. We have the old Roland one [an SVC-350], Auto-Tune, and a DigiTech Vocalist.”&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The quote delivers some vital clues, but it’s incomplete, covering only their first two albums. There’s no mention of using a talk box, despite Around The World almost certainly using one. The quote makes it sound like the DigiTech Vocalist is a vocoder, but it’s not. And for that matter, which DigiTech Vocalist model? There are around 30 pieces of hardware in DigiTech’s Vocalist series, and quite a few of them were around before Discovery’s release in 2001.&lt;/p&gt;
&lt;p&gt;I’ve read comments suggesting the DigiTech Vocalist models with the “EX” suffix are special, but nobody seems to know why, and nobody has published a direct comparison to prove or disprove the theory. I decided to take on the challenge, and run the tests myself. Here’s a fraction of the Vocalist units I ended up buying.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/daftpunkvocaleffects/digitech-vocalist-family.jpg" alt="A photo of lots of DigiTech Vocalist models."&gt;&lt;/p&gt;
&lt;p&gt;Why are there duplicates of the same model? Why is there a Korg ih in that photo? Before this article gets sidetracked with tests and some honestly quite interesting corporate partnerships, mergers, and lawsuits, here is a list of every Daft Punk album song containing robot-like vocal effects, and my guess on which piece of kit was used for the vocals.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Album&lt;/th&gt;
&lt;th&gt;Song&lt;/th&gt;
&lt;th&gt;Effects&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Homework&lt;/td&gt;
&lt;td&gt;WDPK 83.7 FM&lt;/td&gt;
&lt;td&gt;Roland SVC-350&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Homework&lt;/td&gt;
&lt;td&gt;Around The World&lt;/td&gt;
&lt;td&gt;Talk box&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Homework&lt;/td&gt;
&lt;td&gt;Teachers&lt;/td&gt;
&lt;td&gt;Ensoniq DP/4+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Homework&lt;/td&gt;
&lt;td&gt;Oh Yeah&lt;/td&gt;
&lt;td&gt;Ensoniq DP/4+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Discovery&lt;/td&gt;
&lt;td&gt;One More Time&lt;/td&gt;
&lt;td&gt;Auto-Tune&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Discovery&lt;/td&gt;
&lt;td&gt;Digital Love&lt;/td&gt;
&lt;td&gt;DigiTech Vocalist&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Discovery&lt;/td&gt;
&lt;td&gt;Harder, Better, Faster, Stronger&lt;/td&gt;
&lt;td&gt;DigiTech Talker&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Discovery&lt;/td&gt;
&lt;td&gt;Something About Us&lt;/td&gt;
&lt;td&gt;DigiTech Vocalist&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Human After All&lt;/td&gt;
&lt;td&gt;Human After All&lt;/td&gt;
&lt;td&gt;DigiTech Talker&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Human After All&lt;/td&gt;
&lt;td&gt;The Prime Time Of Your Life&lt;/td&gt;
&lt;td&gt;DigiTech Talker&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Human After All&lt;/td&gt;
&lt;td&gt;Robot Rock&lt;/td&gt;
&lt;td&gt;DigiTech Talker&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Human After All&lt;/td&gt;
&lt;td&gt;Make Love&lt;/td&gt;
&lt;td&gt;DigiTech Talker&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Human After All&lt;/td&gt;
&lt;td&gt;The Brainwasher&lt;/td&gt;
&lt;td&gt;Tremolo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Human After All&lt;/td&gt;
&lt;td&gt;Television Rules The Nation&lt;/td&gt;
&lt;td&gt;DigiTech Talker&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Human After All&lt;/td&gt;
&lt;td&gt;Technologic&lt;/td&gt;
&lt;td&gt;Ensoniq DP/4+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Human After All&lt;/td&gt;
&lt;td&gt;Emotion&lt;/td&gt;
&lt;td&gt;Roland SVC-350&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Random Access Memories&lt;/td&gt;
&lt;td&gt;Give Life Back To Music&lt;/td&gt;
&lt;td&gt;Talker and VSM201&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Random Access Memories&lt;/td&gt;
&lt;td&gt;The Game Of Love&lt;/td&gt;
&lt;td&gt;Sennheiser VSM201&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Random Access Memories&lt;/td&gt;
&lt;td&gt;Within&lt;/td&gt;
&lt;td&gt;Sennheiser VSM201&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Random Access Memories&lt;/td&gt;
&lt;td&gt;Instant Crush&lt;/td&gt;
&lt;td&gt;Auto-Tune and VSM201&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Random Access Memories&lt;/td&gt;
&lt;td&gt;Lose Yourself To Dance&lt;/td&gt;
&lt;td&gt;Talker and VSM201&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Random Access Memories&lt;/td&gt;
&lt;td&gt;Touch&lt;/td&gt;
&lt;td&gt;Sennheiser VSM201&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Random Access Memories&lt;/td&gt;
&lt;td&gt;Get Lucky&lt;/td&gt;
&lt;td&gt;DigiTech Talker&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Random Access Memories&lt;/td&gt;
&lt;td&gt;Beyond&lt;/td&gt;
&lt;td&gt;Sennheiser VSM201&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Random Access Memories&lt;/td&gt;
&lt;td&gt;Fragments Of Time&lt;/td&gt;
&lt;td&gt;Framptone Talk Box&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Random Access Memories&lt;/td&gt;
&lt;td&gt;Doin’ It Right&lt;/td&gt;
&lt;td&gt;Sennheiser VSM201&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="homework-notes-20-january-1997"&gt;Homework notes (20 January 1997)&lt;/h3&gt;
&lt;p&gt;There aren’t many robot vocal effects on Homework, but there is a lot of pitch shifting, likely provided by Daft Punk’s Ensoniq DP/4+, a digital multi-effects unit that can do a variety of things. I don’t believe Daft Punk used the vocoder on the Ensoniq DP/4+ for Homework or any of their other albums. The Remix magazine quote says Ensoniq DP/4, but a &lt;a href="https://i.redd.it/te31d8kbt2e11.jpg"&gt;gear list in another interview&lt;/a&gt; says DP/4+. It doesn’t matter which model was used, as the pitch shifting and vocoder sound the same on both units.&lt;/p&gt;
&lt;h3 id="discovery-notes-12-march-2001"&gt;Discovery notes (12 March 2001)&lt;/h3&gt;
&lt;p&gt;One More Time sounds like Auto-Tune in combination with a Mu-Tron Phasor or Moogerfooger. Harder, Better, Faster, Stronger uses a DigiTech Talker vocoder. Given the DigiTech Talker was used extensively for Human After All, maybe it was one of the last songs recorded for Discovery? The DigiTech Talker wasn’t mentioned in the May 2001 interview, despite its apparent use on Discovery. Harder, Better, Faster, Stronger uses the NuVo program on the Talker. NuVo includes the original voice for sibilant sounds. I believe it is the only Daft Punk song to use that setting on the Talker — their other songs use the TalkBox program.&lt;/p&gt;
&lt;h3 id="human-after-all-notes-14-march-2005"&gt;Human After All notes (14 March 2005)&lt;/h3&gt;
&lt;p&gt;DigiTech Talker and DigiTech Synth Wah are all over the entire album. But, did they use a DigiTech Synth Wah, or DigiTech Bass Synth Wah? They’re very similar pedals. The tremolo effect on The Brainwasher could have been done many ways. Maybe it was just an LFO modulating the amplitude on their Roland S-760 sampler? Maybe it was a guitar pedal? It’s an easy effect that can be achieved many different ways.&lt;/p&gt;
&lt;h3 id="random-access-memories-notes-17-may-2013"&gt;Random Access Memories notes (17 May 2013)&lt;/h3&gt;
&lt;p&gt;In Lose Yourself To Dance, the “everybody’s dancing on the floor” vocals sound very crunchy and DigiTech Talker-like. The vocoded vocals in Touch sound like a Sennheiser VSM201 switched to unvoiced, or using white noise as the vocoder’s carrier. Instant Crush could be Auto-Tune or some other kind of harmoniser. It sounds like Instant Crush constains some Sennheiser VSM201 chord layers in places. Fragments Of Time uses a talk box for a synth solo. The 2013 demo of Infinity Repeating sounds like Julian Casablancas recorded multiple harmonies, rather than using a harmoniser or other vocal effect.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="talk-boxes"&gt;Talk boxes&lt;/h3&gt;
&lt;p&gt;Daft Punk’s vocal effects can be broadly split into three categories: Talk boxes, vocoders, and harmonisers. They all sound vaguely similar and robot-like, and you could be forgiven for confusing them, but they’re extremely different techniques and technologies.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/daftpunkvocaleffects/heil-talk-box.jpg" alt="A photo of a Heil Talk Box."&gt;&lt;/p&gt;
&lt;p&gt;Talk boxes are relatively simple devices — they’re a speaker in a sealed box with a small opening. One end of a hose is fitted to the opening, and the other end is placed into the performer’s mouth, blasting noise towards their throat. The performer can pretend to speak, shaping and filtering the sound coming out of the tube with their vocal tract. A microphone is then needed to record the resulting sound. A keyboard or guitar is typically connected to the talk box unit as the sound source for the speaker. This lets the keyboard or guitar sound like it’s singing. If you’ve heard &lt;a href="https://www.youtube.com/watch?v=UlAa0dc-E4w"&gt;Chromeo&lt;/a&gt;, 2Pac’s &lt;a href="https://www.youtube.com/watch?v=J7_bMdYfSws"&gt;California Love&lt;/a&gt;, Peter Frampton’s &lt;a href="https://youtu.be/y7rFYbMhcG8?feature=shared&amp;amp;t=349"&gt;Do You Feel Like We Do&lt;/a&gt;, or Bon Jovi’s &lt;a href="https://www.youtube.com/watch?v=lDK9QqIzhwk"&gt;Livin’ On A Prayer&lt;/a&gt; before, you’ve heard a talk box.&lt;/p&gt;
&lt;p&gt;I can confirm firing loud sounds into your mouth while holding a tube with your teeth is a bit uncomfortable. In terms of vocal effects used by Daft Punk, I think talk box might be the least used and least interesting, in terms of hunting down the exact hardware used. Talk boxes are simple devices and typically all sound similar. The sound source and performance play a bigger role in the result than the hardware itself.&lt;/p&gt;
&lt;p&gt;Also, there aren’t many talk boxes on the market. &lt;a href="https://gearspace.com/board/showpost.php?p=8914255&amp;amp;postcount=31"&gt;Daft Punk may have used a Heil Talk Box&lt;/a&gt;, a Rocktron Banshee, a home made talk box, or something else. The MXR M222 Talk Box is probably the best option if you’re looking to buy a talk box today, because it has a built in amplifier. The MXR wasn’t around when &lt;a href="https://www.youtube.com/watch?v=K0HSD_i2DvA"&gt;Around The World&lt;/a&gt; was created though, so that’s not the unit they used.&lt;/p&gt;
&lt;p&gt;Daft Punk’s early albums extensively used a Roland Juno-106, so it’s likely that was the sound source for the talk box used on Around The World. It sounds like a sawtooth wave with the filters open.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/daftpunkvocaleffects/daft-punk-juno-106.jpg" alt="A photo of Thomas Bangalter playing a Roland Juno-106 and Roland TR-909."&gt;&lt;/p&gt;
&lt;p&gt;Even though they’ve been around in a commercial form since the mid 70s, talk boxes aren’t the first device to use human vocal tracts to create robotic sounds — the &lt;a href="https://www.youtube.com/watch?v=kH-krlgo2e8"&gt;Sonovox&lt;/a&gt; from 1939 takes that prize.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="vocoders"&gt;Vocoders&lt;/h3&gt;
&lt;p&gt;Vocoders are a bit like an electronic version of a talk box. Vocoders take two audio inputs — often a voice and a synth — and combine them by filtering the synth with the voice’s frequency response. The filtering is usually done by splitting the signal into frequency bands. The volume of each voice band sets the volume of the repective synth band. More bands usually means a higher quality and more intelligible result. I’ve been calling the inputs “voice” and “synth”, but they’re often referred to as the modulator and carrier. The modulator’s frequency response shapes the carrier.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/daftpunkvocaleffects/vocoders.jpg" alt="A photo of vocoders, including a DigiTech Talker and Ultimate VoIS."&gt;&lt;/p&gt;
&lt;p&gt;Vocoders can be analogue or digital. Good analogue vocoders are physically big and very expensive, due to their complexity, especially if they have lots of frequency bands. They’re also a specialty effect, and therefore usually not mass produced.&lt;/p&gt;
&lt;p&gt;The peak for high-end analogue vocoders was the 1970s — the EMS Vocoder 5000 was released in 1976, the Bode/Moog Vocoder in 1977, and the Sennheiser VSM201 in 1977. It’s hard to know exactly how many Sennheiser VSM201s were built, but the highest serial number I’ve seen is 40. The photo below is of the unit with serial number 21. Why should we care about that serial number? It’s the &lt;a href="https://reverb.com/au/item/72543188-1977-sennheiser-vsm201-vocoder-20-band-analog-voice-synthesizer-rare-vocal-microphone-mic-effect-synth-used-by-daft-punk"&gt;exact unit Daft Punk used&lt;/a&gt; on Random Access Memories, rented from &lt;a href="https://audiorents.com/?s=VSM-201"&gt;Audio Rents in Los Angeles&lt;/a&gt; for the sessions. Serial number 21 was sold, but Audio Rents have another VSM201, if you’re keen on renting one.&lt;/p&gt;
&lt;p&gt;It’s also possible two Sennheiser VSM201s were used on Random Access Memories, because Daft Punk &lt;a href="https://www.soundonsound.com/people/recording-random-access-memories-daft-punk"&gt;recorded a lot of the vocoded vocals in their own studio in Paris&lt;/a&gt;, prior to the LA sessions.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/daftpunkvocaleffects/sennheiser-vsm201.jpg" alt="A photo of a Sennheiser VSM201 with the serial number 21."&gt;&lt;/p&gt;
&lt;p&gt;The best modern analogue vocoder I’ve heard, by far, is the &lt;a href="https://vocoder.hoerold.com/Ultimate-VoIS.html"&gt;Dromedary Ultimate VoIS&lt;/a&gt;. It shares a lot of similarities with the Sennheiser VSM201, including accurate voiced/unvoiced detection, silence bridging, and other features. It’s a fraction of the price of a vintage vocoder, and still in production. If you’re looking for a high-end vocoder, it is the one to get.&lt;/p&gt;
&lt;p&gt;What about vocoders used by Daft Punk prior to Random Access Memories? It’s incredibly likely Daft Punk used a DigiTech Talker on &lt;a href="https://www.youtube.com/watch?v=gAjR4_CbPpQ"&gt;Harder, Better, Faster, Stronger&lt;/a&gt; and many of the songs on Human After All. The DigiTech Talker is a digital vocoder, sold as a guitar pedal.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/daftpunkvocaleffects/digitech-talker.jpg" alt="A photo of a DigiTech Talker."&gt;&lt;/p&gt;
&lt;p&gt;I said “incredibly likely”, because there’s another vocoder that sounds eerily similar. That’s no coincidence — even though the Talker has DigiTech’s name on the front of the pedal, it was designed and manufactured by IVL Technologies in Canada. IVL also teamed up with Electrix to build the Warp Factory vocoder, which sounds very similar, but not identical. It’s pretty clear they’re running the same algorithm.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/daftpunkvocaleffects/warp-factory.jpg" alt="A photo of an Electrix Warp Factory."&gt;&lt;/p&gt;
&lt;p&gt;IVL specialises in vocal effects and voice processing. They’re still around, but known under a different name — in 2000, TC Helicon was formed as a joint venture between TC Electronic and IVL Technologies. TC Group, the parent company of TC Electronic, took full ownership of TC Helicon in 2005. And finally, Music Tribe (Behringer) purchased TC Group in 2015.&lt;/p&gt;
&lt;p&gt;TC Helicon still make a vocoder guitar pedal called the &lt;a href="https://www.tc-helicon.com/tchelicon/product?modelCode=0726-AAP"&gt;Talkbox Synth&lt;/a&gt;. Sadly, it sounds nothing like the DigiTech Talker. It’s pretty good, but it doesn’t have the crunchy Daft Punk sound. Also, it has a terrible name. It’s not a talk box at all. It’s a vocoder. The DigiTech Talker has a similar naming issue — one of the settings is called “talk box”, and it’s also a vocoder. The recurring theme when researching this article was finding out about IVL/TC Helicon’s incorrectly named products and features.&lt;/p&gt;
&lt;p&gt;Here’s a list of some vocoders, including the models being discussed. Many of these vocoders were used on well known songs. A MAM VF-11 was used on Intergalactic by Beastie Boys. Roland VP-330s were used on In The Air Tonight by Phil Collins, Radio Ga Ga by Queen, and I Just Called to Say I Love You by Stevie Wonder. A Korg DVP-1 was used by Air for lots of their songs, including Kelly Watch The Stars. As well as being used by Daft Punk, Sennheiser VSM201s have been used by Herbie Hancock, Giorgio Moroder, and Aphex Twin.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Year&lt;/th&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Bands&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1976&lt;/td&gt;
&lt;td&gt;EMS Vocoder 5000&lt;/td&gt;
&lt;td&gt;22&lt;/td&gt;
&lt;td&gt;Analogue&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1977&lt;/td&gt;
&lt;td&gt;EMS Vocoder 2000&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;Analogue&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1977&lt;/td&gt;
&lt;td&gt;EMS Vocoder 3000&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;Analogue&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1977&lt;/td&gt;
&lt;td&gt;Bøde/Moog Vocoder&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;Analogue&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1977&lt;/td&gt;
&lt;td&gt;Sennheiser VSM201&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;Analogue&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1978&lt;/td&gt;
&lt;td&gt;Korg VC-10&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;Analogue&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1979&lt;/td&gt;
&lt;td&gt;Roland SVC-350&lt;/td&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;td&gt;Analogue&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1979&lt;/td&gt;
&lt;td&gt;Roland VP-330&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;Analogue&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1986&lt;/td&gt;
&lt;td&gt;Korg DVP-1&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;Digital&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1997&lt;/td&gt;
&lt;td&gt;DigiTech Talker&lt;/td&gt;
&lt;td&gt;24 (order)&lt;/td&gt;
&lt;td&gt;Digital, linear predictive coding&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1999&lt;/td&gt;
&lt;td&gt;Eletrix Warp Factory&lt;/td&gt;
&lt;td&gt;1 to 24 (order)&lt;/td&gt;
&lt;td&gt;Digital, similar to DigiTech Talker&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2000&lt;/td&gt;
&lt;td&gt;MAM VF-11&lt;/td&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;td&gt;Analogue&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2000&lt;/td&gt;
&lt;td&gt;Next! Vox 11&lt;/td&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;td&gt;Identical to MAM VF-11&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2000&lt;/td&gt;
&lt;td&gt;FAT Procoder PCP330&lt;/td&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;td&gt;Identical to MAM VF-11&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2002&lt;/td&gt;
&lt;td&gt;Alesis ModFx Metavox&lt;/td&gt;
&lt;td&gt;38&lt;/td&gt;
&lt;td&gt;Digital&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2017&lt;/td&gt;
&lt;td&gt;TC Helicon Talkbox Synth&lt;/td&gt;
&lt;td&gt;?&lt;/td&gt;
&lt;td&gt;Digital&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2019&lt;/td&gt;
&lt;td&gt;Behringer VC340&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;Analogue, Roland VP-330 clone&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2018&lt;/td&gt;
&lt;td&gt;Electro-Harmonix V256&lt;/td&gt;
&lt;td&gt;8 to 256&lt;/td&gt;
&lt;td&gt;Digital&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2024&lt;/td&gt;
&lt;td&gt;Ultimate VoIS&lt;/td&gt;
&lt;td&gt;18&lt;/td&gt;
&lt;td&gt;Analogue&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2025&lt;/td&gt;
&lt;td&gt;Robot Rocket plugin&lt;/td&gt;
&lt;td&gt;1 to 48 (order)&lt;/td&gt;
&lt;td&gt;Digital, linear predictive coding&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Having more filter bands typically increases the quality of the results, but I wouldn’t consider the Metavox or V256 to be anywhere near the best in terms of intelligibility. The EMS Vocoder 5000 and Sennheiser VSM201 are often considered to be the best vocoders ever made.&lt;/p&gt;
&lt;p&gt;The DigiTech Talker, Eletrix Warp Factory, and &lt;a href="https://bjango.com/plugin/robotrocket/"&gt;Robot Rocket plugin&lt;/a&gt; use linear predictive coding (LPC), rather than bandpass filters. The value shown in the bands column for those models is the LPC order.&lt;/p&gt;
&lt;h3 id="vocoder-comparison"&gt;Vocoder comparison&lt;/h3&gt;
&lt;p&gt;If you’d like to hear many of these vocoders in action, I’ve created a &lt;a href="https://www.youtube.com/watch?v=bkTFCPQMJkc"&gt;vocoder comparison video&lt;/a&gt;. The comparison includes a Sennheiser VSM201, DigiTech Talker, the XILS 201 plugin, a Dromedary Ultimate VoIS, and many other vododers. It compares the actual models used by Daft Punk as well as software clones, and the best modern analogue vocoder.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=bkTFCPQMJkc"&gt;&lt;img src="https://bjango.com/images/articles/daftpunkvocaleffects/video-vocoders.jpg"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="harmonisers"&gt;Harmonisers&lt;/h3&gt;
&lt;p&gt;Harmonisers are very different to talk boxes and vocoders. There’s no filtering involved, and they don’t require two audio sources — they work directly with one audio signal, often a vocal, altering its pitch. Harmonisers are a digital effect.&lt;/p&gt;
&lt;p&gt;There are two main parts to the digital algorithm used by harmonisers — pitch detection, and pitch shifting. Pitch detection figures out the fundamental frequency of the signal. Once the pitch is known, lots of possibilities open up.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/daftpunkvocaleffects/digitech-vocalist-family-2.jpg" alt="A photo of several harmonizers, including two DigiTech Studio Vocalist EX modesl."&gt;&lt;/p&gt;
&lt;p&gt;If the pitch is rapidly shifted to a nearby note in the song’s key, the result sounds like &lt;a href="https://www.youtube.com/watch?v=FGBhQbmPwH8&amp;amp;t=47s"&gt;One More Time&lt;/a&gt; or &lt;a href="https://www.youtube.com/watch?v=a5uQMwRMHcs&amp;amp;t=81"&gt;Instant Crush&lt;/a&gt;. Using &lt;a href="https://www.antarestech.com"&gt;Auto-Tune&lt;/a&gt; with extreme settings is one way to achieve this effect, but it can be done with most harmonisers and is often called “hard tune”.&lt;/p&gt;
&lt;p&gt;Some harmonisers can have keyboards connected to them, and use the notes played on the keyboard to determine which note to shift the vocal to. Holding multiple keys can create harmonies. &lt;a href="https://www.youtube.com/watch?v=UYIAfiVGluk"&gt;Hide and Seek&lt;/a&gt; by Imogen Heap is a great example of this effect in action. In Hide and Seek, the original main vocal can also be heard, blended in with the harmonies.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=FxzBvqY5PP0"&gt;Digital Love&lt;/a&gt; and &lt;a href="https://www.youtube.com/watch?v=sOS9aOIXPEk"&gt;Something About Us&lt;/a&gt; were created using the same technique, where a MIDI keyboard or sequencer was used to control the pitch of the vocal. Daft Punk have said they used a DigiTech Vocalist, which is a strong indication that’s what was used for those two tracks. Both songs were released on 12 March 2001, as part of the Discovery album. Given the time required for mixing, mastering, and physical media production, I’d guess they must have used a model from before late 2000. There’s 7 DigiTech Vocalist models with MIDI pitch control that were released before then.&lt;/p&gt;
&lt;p&gt;The earlier models incorrectly call the MIDI control feature “vocoder”, and later models call it “MIDI notes mode” or “notes harmony mode”. The list below shows all the DigiTech Vocalist models with MIDI notes mode. There’s another 20 or so models that can’t be controlled via a keyboard.&lt;/p&gt;
&lt;p&gt;Interestingly, Imogen Heap also used a DigiTech Vocalist to record Hide and Seek, and has used a &lt;a href="https://youtu.be/-Scn74BnDz4?feature=shared&amp;amp;t=1983"&gt;TC Helicon VoiceLive 2&lt;/a&gt; when &lt;a href="https://www.youtube.com/watch?v=dHk2lLaDzlM"&gt;performing the song live&lt;/a&gt;. Which DigiTech Vocalist? I emailed Imogen’s team and to my surprise, they responded, confirming a DigiTech Vocalist Workstation EX was used for recording Hide and Seek.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Year&lt;/th&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Sampling&lt;/th&gt;
&lt;th&gt;Mic power&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1991&lt;/td&gt;
&lt;td&gt;Vocalist VHM5&lt;/td&gt;
&lt;td&gt;16-bit, 31.25kHz&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1993&lt;/td&gt;
&lt;td&gt;Studio Vocalist&lt;/td&gt;
&lt;td&gt;18-bit, 48kHz&lt;/td&gt;
&lt;td&gt;+48V&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1995&lt;/td&gt;
&lt;td&gt;Vocalist II&lt;/td&gt;
&lt;td&gt;16-bit, 31.25kHz&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1996&lt;/td&gt;
&lt;td&gt;MIDI Vocalist&lt;/td&gt;
&lt;td&gt;16-bit, 31.25kHz&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1996&lt;/td&gt;
&lt;td&gt;Vocalist Workstation&lt;/td&gt;
&lt;td&gt;18-bit, 48kHz&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1998&lt;/td&gt;
&lt;td&gt;Vocalist Access&lt;/td&gt;
&lt;td&gt;16-bit, 44.1kHz&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1998&lt;/td&gt;
&lt;td&gt;Studio Vocalist EX&lt;/td&gt;
&lt;td&gt;18-bit, 48kHz&lt;/td&gt;
&lt;td&gt;+48V&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2000&lt;/td&gt;
&lt;td&gt;Vocalist VR&lt;/td&gt;
&lt;td&gt;16-bit, 44.1kHz&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2001&lt;/td&gt;
&lt;td&gt;Vocalist Workstation EX&lt;/td&gt;
&lt;td&gt;18-bit, 48kHz&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2008&lt;/td&gt;
&lt;td&gt;Vocalist Live Pro&lt;/td&gt;
&lt;td&gt;24-bit, 44.1kHz&lt;/td&gt;
&lt;td&gt;+48V&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2009&lt;/td&gt;
&lt;td&gt;Vocalist VL3D&lt;/td&gt;
&lt;td&gt;24-bit, 44.1kHz&lt;/td&gt;
&lt;td&gt;+48V&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Remember IVL Technologies from earlier in the article? Their logo is on all those Vocalist models, except the Vocalist Live Pro. Yes, IVL also designed and built almost all the DigiTech Vocalist units. The Vocalist Live Pro has a different logo on the back — 3db Research. And, the Vocalist VL3D has IVL and 3db Research’s logos on it. I don’t fully understand what went down, but 3db Research was created by ex-IVL staff, and Harman International accused TC Helicon of infringing &lt;a href="https://patents.google.com/patent/US20140109751A1/en"&gt;patents relating to harmonisers&lt;/a&gt;. TC Helicon counter sued, and won.&lt;/p&gt;
&lt;p&gt;Hold up. Why is Harman involved? While IVL were busy merging with TC Group, forming TC Helicon, and being sold to Behringer, DigiTech were experiencing their own dramas — DigiTech sold to Harman International in 1990, then Samsung bought Harman in 2017. After a restructure, DigiTech ceased to exist in mid 2018. In 2022, &lt;a href="https://digitech.com/announcing-the-comeback-of-the-dod-pedals/"&gt;DigiTech was purchased and revived by Cor-Tek&lt;/a&gt;, who seem to be doing a great job. That’s why it’s possible to buy DigiTech pedals today. Unfortunately, they don’t currently sell any DigiTech Vocalists or Talkers, so you’ll have to hit the second hand market if you’re after either. &lt;a href="https://www.youtube.com/live/RkzdNmBsyxw?feature=shared&amp;amp;t=664"&gt;This JHS Pedals video has a full recap of the DOD and DigiTech history&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;IVL partnered with other companies, including Korg. The Korg ih Interactive Vocal Harmony appears to run the same algorithm as the DigiTech Vocalist series, so I purchased one of those to add to the tests. I also purchased a TC Helicon Perform VE and TC Helicon VoiceWorks. As noted above, TC Helicon is the modern incarnation of IVL, so maybe their harmonisers sound the same as the older DigiTech ones?&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Year&lt;/th&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Sampling&lt;/th&gt;
&lt;th&gt;Mic power&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1995&lt;/td&gt;
&lt;td&gt;Korg ih&lt;/td&gt;
&lt;td&gt;16-bit, 31.25kHz&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2003&lt;/td&gt;
&lt;td&gt;TC Helicon VoiceWorks&lt;/td&gt;
&lt;td&gt;24-bit, 44.1kHz or 48kHz&lt;/td&gt;
&lt;td&gt;+48V&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2017&lt;/td&gt;
&lt;td&gt;TC Helicon Perform VE&lt;/td&gt;
&lt;td&gt;24-bit, 44.1kHz&lt;/td&gt;
&lt;td&gt;+48V&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;IVL also worked with DigiTech to create the Whammy WH-1, Whammy II, and Bass Whammy pedals, which makes sense, given the Whammy is a harmoniser. Those models likely shared code and algorithms with the Vocalist line. Later versions of the DigiTech Whammy weren’t built in collaboration with IVL. The earlier IVL Whammy models are held in high regard and their prices on the used market reflect that. However, the latest model, the Whammy V, does have a “classic” mode that is supposed to replicate the earler models.&lt;/p&gt;
&lt;h3 id="ex-models"&gt;EX models&lt;/h3&gt;
&lt;p&gt;Now we have the full history of DigiTech and IVL covered, we can talk about how the “EX” models fit into the timeline. In 1998, the Studio Vocalist EX was released, becoming the new flagship Vocalist model. The main upgrades were more patch storage, more presets, and an updated algorithm with better pitch recognition.&lt;/p&gt;
&lt;p&gt;For the effect used on Digital Love and Something About Us, the improved pitch recognition would make an audible difference. But, in my tests, the difference between the non-EX and EX models is fairly subtle. Audible and better, but subtle. If I had to guess which unit Daft Punk used, my money would be on the Studio Vocalist EX, but a Vocalist Workstation or one of the other earlier models could have also been used.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/daftpunkvocaleffects/digitech-vocalist-workstation-ex.jpg" alt="A photo of a DigiTech Vocalist Workstation EX."&gt;&lt;/p&gt;
&lt;p&gt;To confuse things even further, the Vocalist Workstation can run the EX firmware, and I was able to upgrade one of my own units from firmware 1.02 to 2.02 (2.02 is the EX version, with additional presets and patch storage). A Vocalist Workstation running firmware 2.02 sounds identical to a Vocalist Workstation EX to me. The internals to the Vocalist Workstation EX are a bit different to the Vocalist Workstation, but I don’t think any of the differences relate to the audio path. The EX is also heavier, at 840 grams vs the non-EX’s 700 grams. The weight difference is due to a useless strip of metal in the EX. No, I’m not kidding.&lt;/p&gt;
&lt;p&gt;Without more evidence, it seems impossible to know which model Daft Punk used. They may have used a Vocalist VHM5, Studio Vocalist, Vocalist II, MIDI Vocalist, Vocalist Workstation, Vocalist Access, Studio Vocalist EX, or Vocalist VR. I’m not sure it matters, given how similar they all sound.&lt;/p&gt;
&lt;p&gt;If you are looking for a device to replicate the effect, a Studio Vocalist EX, Vocalist Workstation EX, or Vocalist Workstation with the EX firmware are good choices. Some of the newer TC Helicon devices, like the VoiceLive 3 Extreme, Perform VE, and Perform VG are great, too. Just be aware that only specific TC Helicon vocal effect models have MIDI notes mode. Also, the Perform VE and Perform VG have been discontinued.&lt;/p&gt;
&lt;p&gt;I would recommend against the Vocalist Live Pro or Vocalist VL3D. They don’t run IVL’s algorithm and they sound terrible. I would also recommend against getting a Korg ih — it does use IVL’s algorithm and sounds like a Vocalist Workstation, but there is a permanent chorus effect that can not be disabled.&lt;/p&gt;
&lt;h3 id="pitch-shifting"&gt;Pitch shifting&lt;/h3&gt;
&lt;p&gt;The pitch shifting effect used on Teachers, Oh Yeah, and Technologic is similar to the harmoniser effect we’ve been discussing, but there’s no pitch detection involved — the audio is just shifted without trying to make it match any specific note. It’s highly likely Daft Punk used their Ensoniq DP/4+ to achieve the pitch shifting on Homework and Discovery.&lt;/p&gt;
&lt;h3 id="harmoniser-comparison"&gt;Harmoniser comparison&lt;/h3&gt;
&lt;p&gt;If you’d like to hear many of these harmonisers in action, I’ve created a &lt;a href="https://www.youtube.com/watch?v=10o0hCybeq4"&gt;harmoniser comparison video&lt;/a&gt;, which also covers some of the modern TC Helicon models. Another interesting fact is that all the harmonisers tested use last note priority when more than one note is played at a time via MIDI.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=10o0hCybeq4"&gt;&lt;img src="https://bjango.com/images/articles/daftpunkvocaleffects/video-harmonizers.jpg"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="synth-wah-vs-bass-synth-wah"&gt;Synth Wah vs Bass Synth Wah&lt;/h3&gt;
&lt;p&gt;Human After All sounds like Human After All because of yet another DigiTech product — a digital envelope filter guitar pedal called the Synth Wah. Or, the Bass Synth Wah. It’s unclear which pedal was used, because they’re incredibly similar. Strangely, the Bass Synth Wah weights a lot more (340 vs 635 grams). I didn’t open the pedals up to find out why, but that’s a huge difference, given how alike they are. It might just be an internal metal weight, like the Vocalist Workstation EX has.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/daftpunkvocaleffects/digitech-synth-wah-bass-synth-wah.jpg" alt="A photo of DigiTech Synth Wah and DigiTech Bass Synth Wah guitar pedals."&gt;&lt;/p&gt;
&lt;p&gt;There’s 7 effect types on each pedal, selected via the rightmost knob. Daft Punk favoured “filter 1” and “filter 2”. Here’s a list of the songs on Human After All, and the effect they probably used.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Song&lt;/th&gt;
&lt;th&gt;Effect number&lt;/th&gt;
&lt;th&gt;Effect type&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Human After All&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;Filter 2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The Prime Time Of Your Life&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;Filter 2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Steam Machine&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;Filter 1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The Brainwasher&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;Filter 2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Television Rules The Nation&lt;/td&gt;
&lt;td&gt;2 and 6&lt;/td&gt;
&lt;td&gt;Env Down and Filter 2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Technologic&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;Filter 2&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;If &lt;a href="https://www.youtube.com/watch?v=YKaN7a19jLc"&gt;Television Rules The Nation&lt;/a&gt; does in fact use “env down”, then that’s a vital clue — the Synth Wah has “env down”, but the Bass Synth Wah does not. The pedals share effect types 3, 4, 5, and 6, but 1, 2, and 7 are different. It was the Synth Wah after all.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="memory-tapes"&gt;Memory tapes&lt;/h3&gt;
&lt;p&gt;In May 2023, Daft Punk released a “Memory Tapes” documentary series with interviews and footage from the Random Access Memories studio sessions. Those videos provided a rare glimpse of the equipment used by Daft Punk.&lt;/p&gt;
&lt;p&gt;Episode 1 features Julian Casablancas, and &lt;a href="https://youtu.be/Hxa-5BZXsto?feature=shared&amp;amp;t=97"&gt;at 1m 30s, what appears to be a DigiTech Synth Wah&lt;/a&gt; can be seen on top of a rack. In the following shot, it sounds like Julian is playing guitar through the DigiTech Synth Wah.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/daftpunkvocaleffects/daft-punk-memory-tapes-synth-wah.jpg" alt="A still image from the “Memory Tapes” documentary, showing a DigiTech Synth Wah."&gt;&lt;/p&gt;
&lt;p&gt;Episode 8 features Paul Williams, and &lt;a href="https://youtu.be/K1ZTngbyBrc?feature=shared&amp;amp;t=260"&gt;at 4m 20s, DigiTech Talker and Keeley Electronics Framptone Talk Box&lt;/a&gt; can be clearly seen at the bottom of the frame. That likely means a Framptone Talk Box was the talk box used on Fragments Of Time. The Framptone Talk Box was released in 2004, which means it was impossible for it to be the talk box used on Around The World.&lt;/p&gt;
&lt;p&gt;The video also helps confirm the use of a DigiTech Talker on Random Access Memories. I think this also might be the only time a Talker has been seen in a studio video of Daft Punk?&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/daftpunkvocaleffects/daft-punk-memory-tapes-talker.jpg" alt="A still image from the “Memory Tapes” documentary, showing a DigiTech Talker and Keeley Electronics Framptone Talk Box."&gt;&lt;/p&gt;
&lt;p&gt;While we’re identifying equipment used, a very dark and grainy shot from &lt;a href="https://www.youtube.com/watch?v=ltzRYcetZtY"&gt;Thomas Bangalter’s talk box session on 113’s Fout la Merde&lt;/a&gt; shows a talk box and synth being used. We can’t see the actual talk box unit, but the synth appears to be an &lt;a href="https://www.vintagesynth.com/arp/odyssey-1"&gt;ARP Odyssey MK II&lt;/a&gt; — the distinctive bend and vibrato buttons, the red LED, the number of keys, and the white octave switch provide all the clues needed.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/daftpunkvocaleffects/daft-punk-thomas-talk-box.jpg" alt="A still image from Thomas Bangalter’s talkbox session on 113’s Fout la Merde."&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="credits"&gt;Credits&lt;/h3&gt;
&lt;p&gt;These amazing people helped make this article and the related videos a reality: Vocals performed by &lt;a href="https://www.fiverr.com/soloheadmusic"&gt;Solohead&lt;/a&gt;. Sennheiser VSM201 vocoder recording by &lt;a href="https://www.youtube.com/@TalhaVocoding"&gt;Talha Vocoding&lt;/a&gt;. Ensoniq DP/4+ vocoder recording by &lt;a href="https://www.youtube.com/@_floeter"&gt;@_floeter&lt;/a&gt;. DigiTech Studio Vocalist recording by Spencer D. Carson. Technical guidance, repairs, and EPROM programming by Cam Sanderson. Thanks also to &lt;a href="https://thedaftpunkhistorian.weebly.com"&gt;The Daft Punk Historian&lt;/a&gt;, who sent me a link to Memory Tapes, and the time stamp showing the Talker and Framptone Talk Box.&lt;/p&gt;
&lt;p&gt;Keep living the gold and the silver dream.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/daftpunkvocaleffects/daft-punk-2.jpg" alt="A photo of Daft Punk in front of Eiffel Tower at night."&gt;&lt;/p&gt;</description></item><item><title>Matching drop shadows across CSS, Android, iOS, Figma, and Sketch</title><link>https://bjango.com/articles/matchingdropshadows/</link><pubDate>Sat, 22 Mar 2025 00:00:00 +1100</pubDate><guid>https://bjango.com/articles/matchingdropshadows/</guid><description>&lt;p&gt;If you’ve ever tried to implement consistent shadows across multiple platforms and design tools, you may have noticed that they don’t look the same. Thankfully, it is possible to get them all to match.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/matchingdropshadows/comparison-same-value.png" alt="A comparison of three rectangles with shadows. The shadows do not look the same."&gt;&lt;/p&gt;
&lt;p&gt;The image above shows the same drop shadow values, rendered by CSS on the web, Android, and iOS. It’s a dark and extreme shadow, to make the differences more pronounced. The shadows are black, with no X offset, 24px Y offset, and a 24px blur radius. I’ve used “px” when noting the values, but when building each test app to generate the images for this article, I used the platform’s equivalent unit — dp on Android, and points on iOS.&lt;/p&gt;
&lt;p&gt;The CSS and Android examples may look the same, but they’re slightly different. The image below demonstrates that the Android shadow is slightly blurrier. Please note that the Android shadows in this article are generated with &lt;code&gt;setShadowLayer&lt;/code&gt;, rather than Material elevation.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/matchingdropshadows/comparison-web-android.gif" alt="A rectangle with a shadow, switching between CSS and Android’s rendering."&gt;&lt;/p&gt;
&lt;h3 id="safari-vs-firefox-vs-chrome"&gt;Safari vs Firefox vs Chrome&lt;/h3&gt;
&lt;p&gt;We’ve been discussing CSS drop shadows without being specific about which CSS property, browser, and rendering engine is being used. That’s okay though — I used Safari for most of the screenshots, but box-shadow looks effectively the same across Safari, Firefox, and Chrome.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/matchingdropshadows/comparison-web.gif" alt="A rectangle with a shadow, switching between Safari, Firefox, and Chrome’s rendering."&gt;&lt;/p&gt;
&lt;h3 id="css-vs-figma-vs-sketch"&gt;CSS vs Figma vs Sketch&lt;/h3&gt;
&lt;p&gt;In other good news, drop shadows match across CSS, Sketch, and Figma. Please note that background blurs are a different story. We’re only comparing drop shadows in this article.&lt;/p&gt;
&lt;h3 id="blur-is-to-blame"&gt;Blur is to blame&lt;/h3&gt;
&lt;p&gt;There’s quite a few properties to describe a drop shadow. Thankfully, the position offsets and colour all behave the same across the platforms and design tools being measured. The only difference is how the blur radius is handled.&lt;/p&gt;
&lt;p&gt;I’ve previously investigated &lt;a href="https://bjango.com/articles/blurradiuscomparison/"&gt;how blurs are rendered across different design tools&lt;/a&gt; and CSS, but I missed something important. By re-stacking the various blur tests in a different order, a pattern emerges. There’s three distinct sizes, roughly 1×, 2× and 3× scales. The drop shadows all fall into the 1× and 2× scale factors.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/matchingdropshadows/stacked-results-painted-2.png" alt="A table showing how wide various blurs are."&gt;&lt;/p&gt;
&lt;h3 id="scale-factors"&gt;Scale factors&lt;/h3&gt;
&lt;p&gt;The CSS spec defines the blur to be &lt;a href="https://www.w3.org/TR/css-backgrounds-3/#shadow-blur"&gt;a standard deviation equal to half the blur radius&lt;/a&gt;, which would make the 2× scaled blurs a standard deviation equal to the blur radius. That was the hint needed to figure out a precise scale for converting CSS drop shadow blurs to iOS — the iOS blur radius is twice as big, so scaling a CSS blur radius by 0.5× gets them looking the same.&lt;/p&gt;
&lt;p&gt;The Android blur radius scale factor isn’t quite as straight forward. Android uses Skia for a lot of its rendering, and the &lt;a href="https://github.com/google/skia/blob/de4799f97cd0b4bd971d016ed179f8c854ef4c29/src/core/SkBlurMask.cpp#L28-L39"&gt;source code mentions scaling the blur by 1 / sqrt(3)&lt;/a&gt; because “Safari does the same”, and that “it actually should be 1”. Those comments are quite old, and Safari has since changed to be in line with the CSS spec. That means Android’s shadows don’t match CSS, because of Safari. Wild.&lt;/p&gt;
&lt;p&gt;Huge thanks to &lt;a href="https://kitgrose.com"&gt;Kit Grose&lt;/a&gt; for finding the Skia code comment while reviewing a draft of this article.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/matchingdropshadows/comparison-scaled.png" alt="A comparison of three rectangles with shadows. The shadows match."&gt;&lt;/p&gt;
&lt;p&gt;Posterising the results shows how well they now line up. A perfect match is impossible, due to differences in rendering methods and code, but I do feel like this is good enough.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/matchingdropshadows/comparison-posterised.png" alt="A comparison of three rectangles with shadows. The shadows match. The image has been processed to make it more obvious."&gt;&lt;/p&gt;
&lt;p&gt;Here’s all the blur radius scale factors to convert to and from the various platforms and design tools.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Source&lt;/th&gt;
&lt;th&gt;Destination&lt;/th&gt;
&lt;th&gt;Formula&lt;/th&gt;
&lt;th&gt;Scale factor&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;CSS, Sketch, or Figma&lt;/td&gt;
&lt;td&gt;Android&lt;/td&gt;
&lt;td&gt;sqrt(3) / 2&lt;/td&gt;
&lt;td&gt;0.866×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CSS, Sketch, or Figma&lt;/td&gt;
&lt;td&gt;iOS&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;0.5×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Android&lt;/td&gt;
&lt;td&gt;CSS, Sketch, or Figma&lt;/td&gt;
&lt;td&gt;1 / sqrt(3) × 2&lt;/td&gt;
&lt;td&gt;1.155×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Android&lt;/td&gt;
&lt;td&gt;iOS&lt;/td&gt;
&lt;td&gt;1 / sqrt(3)&lt;/td&gt;
&lt;td&gt;0.577×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;iOS&lt;/td&gt;
&lt;td&gt;CSS, Sketch, or Figma&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;2.0×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;iOS&lt;/td&gt;
&lt;td&gt;Android&lt;/td&gt;
&lt;td&gt;sqrt(3)&lt;/td&gt;
&lt;td&gt;1.732×&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;This research was conducted so &lt;a href="https://bjango.com/mac/pinwheel/"&gt;Pinwheel&lt;/a&gt; could include the correct scale factor when exporting Android and iOS code for shadows and shadow sets.&lt;/p&gt;</description></item><item><title>Two decades of Bjango</title><link>https://bjango.com/articles/twodecades/</link><pubDate>Wed, 12 Mar 2025 22:00:00 +1100</pubDate><guid>https://bjango.com/articles/twodecades/</guid><description>&lt;p&gt;Bjango turns 20 years old this month. The exact day we started is a little fuzzy, so we don’t have a specific date to celebrate. In the beginning, Bjango was just a couple of friends making free OS X Dashboard widgets. We started working on those widgets prior to OS X 10.4 Tiger’s release on 29 April 2005, so my best guess is we started working together some time in March 2005.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/twodecades/bjango-widgets.png" alt="A screenshot of the iStat Pro and iStat Nano OS X Dashboard Widgets."&gt;&lt;/p&gt;
&lt;p&gt;After releasing a few successful widgets, we moved on to what we really wanted to create — full Mac apps. iStat Menus 1.0 was released May 2007, and has seen constant updates since. I can’t believe we’ve been working on iStat Menus for almost 18 years.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/twodecades/istat-menus-icon-evolution.png" alt="The evolution of the iStat Menus app icon from version 1 to version 7."&gt;&lt;/p&gt;
&lt;p&gt;Bjango is a little older and bigger now, but I feel like our passion is as strong as ever. We love making great software. We’ve been self-funded since day one. We care about privacy. And, most of all, we’re immensely grateful to everyone who’s supported us on this adventure.&lt;/p&gt;
&lt;p&gt;Thank you, from the bottom of our hearts.&lt;/p&gt;</description></item><item><title>Design systems need a colour space</title><link>https://bjango.com/articles/designsystemcolourspace/</link><pubDate>Mon, 10 Mar 2025 18:30:00 +1100</pubDate><guid>https://bjango.com/articles/designsystemcolourspace/</guid><description>&lt;p&gt;Imagine walking into a shoe store and asking for size 10 sneakers. You may end up with shoes that fit, but “size 10” isn’t descriptive enough to be sure — the US, UK, EU, Australia, and Japan all have different shoe sizing systems. To ensure you get shoes that fit, it’d be wise to be more specific and ask for “size 10 US” or “size 10 EU”.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/designsystemcolourspace/header.png" alt="A grid of blocks forming a gradient from white on the left to dark grey on the right. Some of the blocks are bright colours."&gt;&lt;/p&gt;
&lt;p&gt;Colours are similar. Specifying “#ff0000” or “rgb(255, 0, 0)” as a colour in your design system is like asking for sneakers without specifying the sizing system — to get the colour you’re after, a value and a colour space is needed. “#ff0000 in sRGB” and “#ff0000 in Display P3” are quite different things. They’re both bright red, but the Display P3 red is far more intense.&lt;/p&gt;
&lt;p&gt;The two most common colour spaces for software design are sRGB and Display P3. If your design system doesn’t specify a colour space and you’re unsure what to use, you may be already working in sRGB, because that’s the default for CSS and in Figma. If that’s the case, adding “all colours specified as sRGB” somewhere in your design system documentation is a great first step, and an easy initial fix.&lt;/p&gt;
&lt;p&gt;Supplying a colour space will probably &lt;a href="https://github.com/design-tokens/community-group/pull/147/files#r1826462271"&gt;become required in the next update&lt;/a&gt; to the Design Tokens Community Group JSON format. &lt;a href="https://www.radix-ui.com/colors"&gt;Radix 3&lt;/a&gt; has switched to Display P3 and now includes a colour space. &lt;a href="https://tailwindcss.com/blog/tailwindcss-v4#modernized-p3-color-palette"&gt;Tailwind CSS version 4&lt;/a&gt; has also recently switched to Display P3, with a more vivid colour palette, and colours specified as OKLCH. Tailwind’s new colours are shown below. The colours with a white border around them can not be achieved using sRGB.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/designsystemcolourspace/tailwind-v4-display-p3.png" alt="A grid showing all the colours in Tailwind CSS version 4."&gt;&lt;/p&gt;
&lt;p&gt;Software developers and designers have been able to ignore colour spaces for a long time, but it’s about to become required knowledge.&lt;/p&gt;
&lt;h3 id="display-p3-is-the-future"&gt;Display P3 is the future&lt;/h3&gt;
&lt;p&gt;For brand new design systems, it’s worth considering Display P3. Display P3 is wider gamut than sRGB, which is just a fancy way to say some of the colours in Display P3 can not be represented in sRGB. Display P3 has more vivid reds and greens. Blue is a little more vivid. However, all colours within sRGB’s gamut can be represented by Display P3. That also means you can convert sRGB values into Display P3 values, while maintaining the same appearance.&lt;/p&gt;
&lt;p&gt;The image below compares pure red, pure green, and pure blue in sRGB to Display P3. If you’re viewing this page on a device that can show Display P3 colours, it should be possible to see the differences. That’s the main pitch for using Display P3 rather than sRGB — more vivid colours are possible. It’s good!&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/designsystemcolourspace/srgb-vs-display-p3.png" alt="Six large blocks of colour are shown. Pure red, green, and blue in sRGB. And, pure red, green, and blue in Display P3."&gt;&lt;/p&gt;
&lt;p&gt;All major platforms have had great support for Display P3 for some time.
In Apple’s current lineup, the only phone, iPad or Mac that doesn’t have a Display P3 screen is the base model iPad. Practically all Android devices with OLED screens are Display P3. If colours are specified in Display P3 and viewed on a non-Display P3 device, the closest colour is shown.&lt;/p&gt;
&lt;p&gt;There aren’t many downsides in using Display P3 colours today, and a lot of upsides.&lt;/p&gt;
&lt;h3 id="goodbye-hex-hello-color"&gt;Goodbye hex, hello color()&lt;/h3&gt;
&lt;p&gt;Many design systems use hex values to represent colours. As far as I’m aware, there’s currently no way to provide a colour space with a hex value in CSS. That’s okay though — the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/color"&gt;color() function&lt;/a&gt; includes a parameter for the colour space. &lt;code&gt;color(display-p3 1 0 0)&lt;/code&gt; is bright red in Display P3. In fact, &lt;code&gt;color(1 0 0)&lt;/code&gt; is not allowed. A colour space must be provided. Are you noticing a trend? Colour spaces will be required in the future.&lt;/p&gt;
&lt;p&gt;The same red can be specified in SwiftUI with &lt;code&gt;Color(.displayP3, red: 1, green: 0, blue: 0, opacity: 1)&lt;/code&gt;. And, for Android, &lt;code&gt;Color(0xFFFF0000, ColorSpaces.DisplayP3)&lt;/code&gt; will do a similar job.&lt;/p&gt;
&lt;h3 id="oklch"&gt;OKLCH&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/oklch"&gt;OKLCH&lt;/a&gt; is a colour space with a very wide gamut. The “LCH” portion stands for lightness, chroma, and hue. OKLCH’s main benefit is consistent perceptual lightness as the hue changes. This can make editing and blending more predicable and pleasant. These qualities are why OKLCH has been adopted by Tailwind and other design systems.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/designsystemcolourspace/oklch-vs-hsl.png" alt="Two grids of coloured blocks compare OKLCH to HSL. They show hue on the X axis and lightness on the Y axis."&gt;&lt;/p&gt;
&lt;p&gt;There are a couple of caveats to be aware of when working in OKLCH.&lt;/p&gt;
&lt;p&gt;OKLCH has an extremely wide gamut, which means it is easy to specify colours that are outside Display P3. Those colours can not be displayed correctly on any current consumer hardware, which means you can’t trust what you’re seeing, unless you are also clamping your OKLCH colours to the Display P3 colour space.&lt;/p&gt;
&lt;p&gt;OKLCH is also often used as a colour space for blending. This can look nice when interpolating between colours with very similar hue values. However, when there’s a large hue difference, the middle may pass through unexpected or unwanted colours. In that instance, the solution is to use &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/oklab"&gt;OKLAB&lt;/a&gt; or some other colour space for blending.&lt;/p&gt;
&lt;p&gt;The example below shows what happens when the end colours of a gradient have different hues, and OKLCH sweeps through unwanted colours.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/designsystemcolourspace/interpolation-types.png" alt="A Pinwheel document set up to demonstrate the difference between colour space aware linear blending, standard linear blending, OKLCH blending, and OKLAB blending."&gt;&lt;/p&gt;
&lt;p&gt;OKLCH should be seen as a useful colour space, but it is not a panacea, and there are many situations where using it will produce worse results.&lt;/p&gt;
&lt;h3 id="deploying-colours"&gt;Deploying colours&lt;/h3&gt;
&lt;p&gt;I like to separate colour creation from deployment, because they have different needs. When creating colours, the properties of certain colour spaces can be incredibly helpful, like using OKLCH for blending.&lt;/p&gt;
&lt;p&gt;However, that doesn’t mean the colour values used in production need to be in the same colour space or format. The goal for production code is usually to be as compact and compatible as possible. If the resulting colour looks identical, it doesn’t matter if the values are specified as RGBA, or some other format.&lt;/p&gt;
&lt;p&gt;We created &lt;a href="https://bjango.com/mac/pinwheel/"&gt;Pinwheel&lt;/a&gt; to help with a lot of the concepts mentioned in this article — it can edit and blend colours in OKLCH and OKLAB, clamp those to Display P3, help with contrast testing, and also generate code in many formats.&lt;/p&gt;</description></item><item><title>Blur radius comparison</title><link>https://bjango.com/articles/blurradiuscomparison/</link><pubDate>Thu, 11 Jan 2024 00:00:00 +0000</pubDate><guid>https://bjango.com/articles/blurradiuscomparison/</guid><description>&lt;p&gt;The most common type of blur used on the web and in design tools is Gaussian blur. There’s many ways to describe how blurry the blur is, and implementations vary so much that a blur in one app may be a completely different size to the blur in another app.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/blurradiuscomparison/blur-radius-ui.png" alt="Screenshots of the various blur size controls in Figma, Sketch, Illustrator, and Photoshop"&gt;&lt;/p&gt;
&lt;p&gt;Sometimes there’s even inconsistency across different features in the same app. This makes it very difficult to convert blur size from design to production, or when moving values between or within design tools. A blur of 50 pixels in one place may not be the same as a blur of 50 pixels somewhere else. It’s difficult to know what these values represent. Some may correspond to a kernel radius or kernel diameter, others might be the radius at a specific place in the Gaussian function.&lt;/p&gt;
&lt;p&gt;There was a time when CSS box-shadow was inconsistent across browsers, but the spec was tightened up and the blur amount is now considered to be &lt;a href="https://www.w3.org/TR/css-backgrounds-3/#shadow-blur"&gt;a standard deviation equal to half the blur radius&lt;/a&gt;. It doesn’t matter if that description makes sense, just know that it enables consistency.&lt;/p&gt;
&lt;p&gt;It’s possible to measure how large a blur is by creating a rectangle, blurring it, then comparing the edge of the blur to other implementations.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/blurradiuscomparison/test-area.png" alt="A white blurry rectangle on a black background with a small section of the edge highlighted"&gt;&lt;/p&gt;
&lt;p&gt;The image below is a portion of the edge of a blurred rectangle, for each blur type. Stacking them like this shows the relative size differences.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/blurradiuscomparison/stacked-results.png" alt="White to black gradients representing each blur type"&gt;&lt;/p&gt;
&lt;h3 id="observations"&gt;Observations&lt;/h3&gt;
&lt;p&gt;Colouring the pure black and pure white regions red, indicating 50% grey in blue, and marking a distance from 50% grey (plus and minus 35%) in purple helps analyse the results and measure sizes.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/blurradiuscomparison/stacked-results-painted.png" alt="White to black gradients representing each blur type, with coloured annotations"&gt;&lt;/p&gt;
&lt;p&gt;All the CSS box-shadows are essentially identical, likely due to the CSS specification including information on how to treat blur radius. There’s subtle differences, but I’m going to consider them to be identical.&lt;/p&gt;
&lt;p&gt;The SVG feGaussianBlur examples are offset. I wonder if this is due to gamma or colourspace correction? I didn’t get time to check. All browsers had lower quality SVG blurs than their CSS counterparts, especially in darker regions. Once again, it might be due to additional gamma processing. This may actually make the SVG blur the most correct, even though it’s the odd one out.&lt;/p&gt;
&lt;p&gt;Figma is the closest match to CSS box-shadow, and all three blurs within Figma are identical. I think those are good choices. Figma requires at least a 0.2% fill for background blurs to function. Figma’s blurs have added noise, and the noise is biased to make the result one 8-bit value darker. The noise repeats every 256×256px. I’m not sure why their background blur never reaches black, given the others do.&lt;/p&gt;
&lt;p&gt;It was surprising to see such a wide range of sizes within Illustrator, Photoshop, and Sketch. There doesn’t seem to be any reason for it, either — Photoshop’s drop shadow is the smallest blur in Photoshop, but Illustrator’s drop shadow is the largest blur in Illustrator. I can’t see any consistency in the decisions.&lt;/p&gt;
&lt;h3 id="scale-factors"&gt;Scale factors&lt;/h3&gt;
&lt;p&gt;It’s now possible to work out the relative scale factors of the various blurs, to be able to convert and visually match them. I’ve used CSS box-shadow as the baseline. Multiplying by the scale factor converts to the radius needed to match CSS box-shadow. Please note that these scale factors are just approximates, but they should be reasonably close. Also, differences in blur rendering could mean things look different anyway.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Blur type&lt;/th&gt;
&lt;th&gt;Scale factor compared to CSS box-shadow&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;CSS box-shadow (Safari)&lt;/td&gt;
&lt;td&gt;1.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CSS box-shadow (Firefox)&lt;/td&gt;
&lt;td&gt;1.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CSS box-shadow (Chrome)&lt;/td&gt;
&lt;td&gt;1.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CSS filter: blur (Safari)&lt;/td&gt;
&lt;td&gt;0.510204&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CSS filter: blur (Firefox)&lt;/td&gt;
&lt;td&gt;0.495050&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CSS filter: blur (Chrome)&lt;/td&gt;
&lt;td&gt;0.495050&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SVG fe (Safari)&lt;/td&gt;
&lt;td&gt;0.423729&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SVG fe (Firefox)&lt;/td&gt;
&lt;td&gt;0.427350&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SVG fe (Chrome)&lt;/td&gt;
&lt;td&gt;0.406504&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Figma background blur&lt;/td&gt;
&lt;td&gt;1.136364&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Figma drop shadow&lt;/td&gt;
&lt;td&gt;1.136364&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Figma layer blur&lt;/td&gt;
&lt;td&gt;1.136364&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Illustrator drop shadow&lt;/td&gt;
&lt;td&gt;0.490196&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Illustrator filter blur&lt;/td&gt;
&lt;td&gt;2.083333&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Photoshop drop shadow&lt;/td&gt;
&lt;td&gt;1.136364&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Photoshop filter blur&lt;/td&gt;
&lt;td&gt;0.490196&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Photoshop shape blur&lt;/td&gt;
&lt;td&gt;0.490196&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sketch background blur&lt;/td&gt;
&lt;td&gt;0.349650&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sketch drop shadow&lt;/td&gt;
&lt;td&gt;1.041667&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sketch shape blur&lt;/td&gt;
&lt;td&gt;0.485437&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;To make Sketch’s background blur look like a 50px CSS box-shadow, a value of 17.4825 is needed (50 × 0.349650 = 17.4825). To make Sketch’s drop shadow look like a 50px CSS box-shadow, a value of 52.08335 is needed (50 × 1.041667 = 52.08335). Here’s the three Sketch blur types, scaled to the equivelent CSS box-shadow value. They now all match!&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/blurradiuscomparison/stacked-results-adjusted.png" alt="A comparison of CSS box-shadow and the blurs in Sketch"&gt;&lt;/p&gt;
&lt;p&gt;Should you bust out a calculator every time you want to copy a blur value from a design tool? Probably not, but it is worth noting that Sketch’s “Copy CSS Attributes” and “Copy SVG Code” don’t scale the blurs to match how they’ll appear in browsers. It’s something to be aware of, even if it’s not critical in all situations. Rounding the values might be the best balance of accuracy and nice CSS? 17.4825 could become 18, which might look close enough.&lt;/p&gt;
&lt;p&gt;Matching a blur from one design tool to another is also possible. Let’s say we want a 50px Photoshop filter blur to be replicated in Figma as a background blur. The formula for that is (destinationScaleFactor / sourceScaleFactor) × sourceRadius. In our case, that’s (1.136364/0.490196) × 50 = 115.9091465455. A 50px Photoshop filter blur can be matched with a 115.9px Figma background blur.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/blurradiuscomparison/stacked-results-adjusted-ps-figma.png" alt="A comparison of blurs in Photoshop and Figma"&gt;&lt;/p&gt;
&lt;h3 id="maximum-blur-size"&gt;Maximum blur size&lt;/h3&gt;
&lt;p&gt;The maximum blur size varies across different tools and features within tools. Some apps allow any value in the UI, but seem to clamp the size when rendering, which may also be zoom dependant. It’d be possible to figure out their maximum, but it’d take some time. Those are listed below as “unknown”.&lt;/p&gt;
&lt;p&gt;Sketch’s maximum background blur and shape blur size can be increased by scaling objects up, even though the UI doesn’t let you type a value over 50.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Blur type&lt;/th&gt;
&lt;th&gt;Maximum blur size&lt;/th&gt;
&lt;th&gt;Size as CSS box-shadow&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Figma background blur&lt;/td&gt;
&lt;td&gt;Unknown&lt;/td&gt;
&lt;td&gt;Unknown&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Figma drop shadow&lt;/td&gt;
&lt;td&gt;Unknown&lt;/td&gt;
&lt;td&gt;Unknown&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Figma layer blur&lt;/td&gt;
&lt;td&gt;Unknown&lt;/td&gt;
&lt;td&gt;Unknown&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Illustrator drop shadow&lt;/td&gt;
&lt;td&gt;144&lt;/td&gt;
&lt;td&gt;70.588235&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Illustrator filter blur&lt;/td&gt;
&lt;td&gt;250&lt;/td&gt;
&lt;td&gt;520.833333&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Photoshop drop shadow&lt;/td&gt;
&lt;td&gt;250&lt;/td&gt;
&lt;td&gt;284.090909&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Photoshop filter blur&lt;/td&gt;
&lt;td&gt;1000&lt;/td&gt;
&lt;td&gt;490.196078&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Photoshop shape blur&lt;/td&gt;
&lt;td&gt;1000&lt;/td&gt;
&lt;td&gt;490.196078&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sketch background blur&lt;/td&gt;
&lt;td&gt;50*&lt;/td&gt;
&lt;td&gt;17.482517&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sketch drop shadow&lt;/td&gt;
&lt;td&gt;Unknown&lt;/td&gt;
&lt;td&gt;Unknown&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sketch shape blur&lt;/td&gt;
&lt;td&gt;50*&lt;/td&gt;
&lt;td&gt;24.271845&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;</description></item><item><title>Design tool canvas handles</title><link>https://bjango.com/articles/designtoolcanvashandles/</link><pubDate>Thu, 14 Dec 2023 00:00:00 +0000</pubDate><guid>https://bjango.com/articles/designtoolcanvashandles/</guid><description>&lt;p&gt;Design tools often pack a lot of functionality around the bounding box of selected objects. Some of this functionality is represented by handles or icons, but a lot of it is hidden.&lt;/p&gt;
&lt;p&gt;This can make learning the behaviour and interacting with objects pretty tricky. The only way to know if you can perform an action is to hover near the edge of a selected shape and note cursor changes. It’s like inspecting a giant cave with a flashlight, which isn’t conducive to working quickly or confidently.&lt;/p&gt;
&lt;p&gt;As well as being hidden, interaction hit zones can also be quite small or oddly shaped, making them hard to target. Illustrator and Affinity Designer have settings to control handle sizes. I changed my Illustrator handles to be the second largest size a couple of years ago to make them easier to see in &lt;a href="https://www.youtube.com/watch?v=J_DRxMLUTrs"&gt;videos&lt;/a&gt;. After using them for a while, I ended up keeping the setting. It’s just quicker and less accident prone working with larger handles.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/designtoolcanvashandles/ui-scale.gif" alt=""&gt;&lt;/p&gt;
&lt;h3 id="interaction-hit-zones"&gt;Interaction hit zones&lt;/h3&gt;
&lt;p&gt;Here’s the object interaction hit zones for the standard transform mode for a rectangle, across various design tools. It’s also worth noting that additional features may be available via modifier keys — Sketch can rotate objects by holding the command key and dragging the corners or sides of the bounding box. That’s less discoverable, but the zones are indicated by the corner widgets, and large enough to easily grab.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/designtoolcanvashandles/handle-hit-zones.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;I’m a fan of the horizontal and vertical resizing being available for the entire side, similar to how Figma and Sketch offer the feature. I’m not sure why you wouldn’t do that, if the space isn’t being used for anything else.&lt;/p&gt;
&lt;p&gt;I don’t really like the L and C-shaped rotation hit zones, but it is nice for rotation to be available without holding a modifier key. Long and narrow zones are hard to target, especially when they’re not denoted with anything.&lt;/p&gt;
&lt;p&gt;Photoshop gets its own hit zone image, because the area for rotation extends a whopping 200pt in every direction from the shape, so it didn’t fit neatly into the previous image.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/designtoolcanvashandles/handle-hit-zones-photoshop.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;I don’t understand why Photoshop has horizontal and vertical resizing just beyond the corner resizing area. That’s possibly just a mistake?&lt;/p&gt;
&lt;p&gt;These interaction hit zones were figured out by screen recording and slowly moving the mouse around, noting cursor changes. It was a slow process, and also probably not accurate. I assumed symmetry for the handles, and didn’t test every single handle — typically just one side and one corner. I was careful and tried my best, but it’s unlikely they’re pixel perfect. The latest version of each app was used.&lt;/p&gt;
&lt;p&gt;Illustrator’s corner resize handles are especially problematic. There’s just so many tiny, oddly shaped areas packed into a small space. A short cursor move may cross many zones.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/designtoolcanvashandles/cursor-path.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Here’s a screen recording, showing the amount of times the cursor changes, due to being in a different zone. Targeting some of these areas is almost impossible.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/designtoolcanvashandles/cursor-path-ai.gif" alt=""&gt;&lt;/p&gt;
&lt;h3 id="small-objects"&gt;Small objects&lt;/h3&gt;
&lt;p&gt;When objects are small, the interaction zones get bunched up and overlap. Different apps have different ways of dealing with this. Sketch enlarges the bounding box so that all the handles are accessible. I believe &lt;a href="https://www.youtube.com/watch?v=9n5mgzqjreE"&gt;Flinto was the first&lt;/a&gt; design tool to do this, back in 2018. Figma hides the handles, letting you move, but not resize or rotate the object. Affinity Designer, Illustrator, and Photoshop just let the handles stack on top of each other.&lt;/p&gt;
&lt;p&gt;Corner radius handles are dropped when they don’t fit, in all the apps that show them.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/designtoolcanvashandles/small-handles.gif" alt=""&gt;&lt;/p&gt;
&lt;h3 id="mouse-offset-within-handles"&gt;Mouse offset within handles&lt;/h3&gt;
&lt;p&gt;Given canvas handles occupy an area, mouse clicks within a handle are unlikely to be precisely in the center. If the mouse position offset isn’t accounted for, the first frame of the drag will jump as the handle gets centered under the cursor. This looks a little jarring, and it means interacting with canvas handles isn’t as accurate. It’s a subtle, but important detail.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/designtoolcanvashandles/mouse-offset.gif" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Photoshop and Affinity Designer do account for the position where the mouse is clicked within canvas resize handles. Sketch, Figma, and Illustrator do not. The screen recording below shows what happens when grabbing and dragging the edge of a resize handle in Illustrator. Note that the mouse only moves upwards during the drag, which should expand the rectangle, but it initially shrinks when the handle centers on the mouse cursor.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/designtoolcanvashandles/mouse-offset-illustrator.gif" alt=""&gt;&lt;/p&gt;</description></item><item><title>Design tool memory usage</title><link>https://bjango.com/articles/designtoolmemory/</link><pubDate>Mon, 04 Sep 2023 00:00:00 +0000</pubDate><guid>https://bjango.com/articles/designtoolmemory/</guid><description>&lt;p&gt;How do various design tools utilise memory? What’s their baseline usage with no documents open? How does memory grow with lots of large documents open?&lt;/p&gt;
&lt;h3 id="empty-documents"&gt;Empty documents&lt;/h3&gt;
&lt;p&gt;The graph below shows what happens when Figma, Sketch, Illustrator, Photoshop, and Affinity Designer have 0, 5, 10, or 15 empty documents simultaneously open. For apps that require a document size or bit depth, I used 512×512px and 8bits per channel.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/designtoolmemory/graph-empty.png" alt="Graph showing how much memory is used by empty documents. Worst to best: Figma, Illustrator, Affinity Designer, Photoshop, Sketch."&gt;&lt;/p&gt;
&lt;p&gt;The results show a linear increase in memory usage as more documents are created. That’s what you’d expect, but it’s always good to test your assumptions. Figma’s usage is by far the highest, and Sketch’s usage is the lowest.&lt;/p&gt;
&lt;h3 id="2048-circles"&gt;2048 circles&lt;/h3&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/designtoolmemory/2048-circles.png" alt="Lots of circles in a grid"&gt;&lt;/p&gt;
&lt;p&gt;The next test involves opening an SVG with a grid of 2048 circles in it. The main purpose of this test is to check layer/object overhead. The objects themselves are simple, there’s just a lot of them.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/designtoolmemory/graph-circles.png" alt="Graph showing how much memory is used for the test document. Worst to best: Figma, Illustrator, Photoshop, Affinity Designer, Sketch."&gt;&lt;/p&gt;
&lt;p&gt;The results show linear growth for all tools again. Figma has the highest usage, and Sketch has the lowest usage, again. Figma is further from the pack this time though, using just under 7 GB when 15 copies of the test document are open.&lt;/p&gt;
&lt;h3 id="2048-points"&gt;2048 points&lt;/h3&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/designtoolmemory/2048-flower.png" alt="A flower shape with 8 petals"&gt;&lt;/p&gt;
&lt;p&gt;This time around, we’ll use an SVG containing a single path with a 2048 points. The path looks similar to the one shown above, but instead of eight petals, there’s 2048. Each petal is a bézier path segment. This test checks how optimally path data is stored.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/designtoolmemory/graph-flower.png" alt="Graph showing how much memory is used for the test document. Worst to best: Figma, Affinity Designer, Illustrator, Photoshop, Sketch."&gt;&lt;/p&gt;
&lt;p&gt;The order is similar to last time, but with Affinity Designer shifting up two positions. Figma is once again the tool using the most memory. I believe Figma loads a full copy of the application per tab, which may be part of the cause for its high memory usage. Each tab is also &lt;a href="https://help.figma.com/hc/en-us/articles/360040528173-Reduce-memory-usage-in-files"&gt;limited to 2GB of ram&lt;/a&gt;, leaving around 1.75 GB for the largest possible document. Put another way, if you purchased a Mac Studio with 192 GB of ram, you could only open documents that use less than 1% of it. This is different to the other applications tested, which have access to the Mac Studio’s full 192 GB, minus whatever the system is using. Figma simultaneously uses the most overall memory of all the tools tested, while also being the most constrained.&lt;/p&gt;
&lt;h3 id="tiger"&gt;Tiger&lt;/h3&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/designtoolmemory/tiger.png" alt="A tiger illustration"&gt;&lt;/p&gt;
&lt;p&gt;The tiger below is a common test SVG, containing around 1000 paths and many groups. This test is similar to the previous ones — open up 0, 5, 10, and 15 copies and see how much memory is used. The results below show more of the same.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/designtoolmemory/graph-tiger.png" alt="Graph showing how much memory is used for the test document. Worst to best: Figma, Illustrator, Affinity Designer, Photoshop, Sketch."&gt;&lt;/p&gt;
&lt;h3 id="300-images"&gt;300 images&lt;/h3&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/designtoolmemory/300-images.png" alt="Brightly coloured geometric images used for testing"&gt;&lt;/p&gt;
&lt;p&gt;What if we import 100, 200, and 300 images into a single document? The images used for this test were 1024×1024 each, and all unique (as seen above).&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/designtoolmemory/graph-images.png" alt="Graph showing how much memory is used for the test document. Worst to best: Photoshop, Figma, Affinity Designer, Illustrator, Sketch."&gt;&lt;/p&gt;
&lt;h3 id="moby-dick"&gt;Moby Dick&lt;/h3&gt;
&lt;p&gt;This next test is a riff on Jesse Grosjean’s &lt;a href="https://www.hogbaysoftware.com/posts/moby-dick-workout/"&gt;Moby Dick workout&lt;/a&gt;. The idea is simple — create a text box and paste the entire contents of Moby Dick into it. Then, duplicate the text box and test memory usage with 5, 10, and 15 copies.&lt;/p&gt;
&lt;p&gt;Moby Dick is around 1.3 MB. It’s a hefty chunk of text, but by no means huge, especially for modern computers.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/designtoolmemory/graph-mobydick.png" alt="Graph showing how much memory is used with multiple copies of Moby Dick pasted into a document. Figma and Sketch not shown. Illustrator, Affinity Designer, and Photoshop all about the same."&gt;&lt;/p&gt;
&lt;p&gt;The graph above looks a little empty, because Sketch and Figma both had issues with Moby Dick. Sketch froze not long after pasting the text. Figma froze for 55 seconds after pasting, then ran out of memory. Testing both apps again with a 200 KB text file gave similar results.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/designtoolmemory/figma-out-of-memory.png" alt="Figma out of memory alert"&gt;&lt;/p&gt;
&lt;p&gt;The other apps handled 15 copies of the full Moby Dick text. I didn’t test beyond that point. Note that the memory usage for each additional text box seems minimal, which is what you’d expect, given it’s just 1.3 MB of text.&lt;/p&gt;
&lt;h3 id="methodology"&gt;Methodology&lt;/h3&gt;
&lt;p&gt;Apps were freshly launched prior to each group of tests. No other large apps were open during testing. Testing was only conducted once, due to the number of tests required (normally I’d consider averaging multiple tests). Photoshop can’t open SVGs directly while maintaining vector objects, so Affinity Designer was used to convert the SVGs into PSDs for Photoshop.&lt;/p&gt;
&lt;p&gt;Tests were conducted with the latest versions of the applications, on an M1 Pro MacBook Pro with 32 GB of memory. Memory for the main application processes were used, and background processes were excluded from the results.&lt;/p&gt;
&lt;h3 id="background-processes"&gt;Background processes&lt;/h3&gt;
&lt;p&gt;All the apps tested create Open and Save Panel service and QuickLook service processes. These use around 30 MB for each app, and they stop running when the app is closed. Figma’s FigmaAgent process continues to run, even when the app is closed (it’s used for uploading your fonts to their servers). FigmaAgent uses around 10 MB on my Mac. These processes weren’t counted in the results, but they’re all small enough that they wouldn’t drastically change the graphs.&lt;/p&gt;
&lt;p&gt;Adobe does install a huge amount of background processes that run even when Photoshop and Illustrator are closed. I found 7 background processes, using around 480 MB, even with the main Creative Cloud app closed.&lt;/p&gt;</description></item><item><title>Shape builder vs pathfinder</title><link>https://bjango.com/articles/shapebuildervspathfinder/</link><pubDate>Wed, 24 May 2023 00:00:00 +0000</pubDate><guid>https://bjango.com/articles/shapebuildervspathfinder/</guid><description>&lt;p&gt;In Adobe Illustrator, the shape builder tool and the pathfinder panel can both add and and subtract segments of overlapping shapes. They’re predominantly used to create complex shapes from simple ones.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/shapebuildervspathfinder/before-after.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;The pathfinder panel was added to Illustrator in 2001, and the shape builder tool was added in 2010. Given shape builder is newer, many people assume it’s better. They’re both useful, but work in different ways.&lt;/p&gt;
&lt;p&gt;Let’s take a look at some common uses for shape builder and pathfinder, to see how they compare.&lt;/p&gt;
&lt;h3 id="round-1-interaction"&gt;Round 1: Interaction&lt;/h3&gt;
&lt;p&gt;The most striking difference between the two is the way they’re used. Shape builder is a tool that interacts directly with objects on the canvas. To unite two circles, select them, then switch to the shape builder tool and drag across all the shape segments.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/shapebuildervspathfinder/shapebuilder-merge.gif" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Holding shift lets you drag a marquee selection to choose which shape segments to unite. This can be a lot faster in some scenarios.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/shapebuildervspathfinder/shapebuilder-merge-marquee.gif" alt=""&gt;&lt;/p&gt;
&lt;p&gt;A single click on a shape segment separates it from the other shapes.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/shapebuildervspathfinder/shapebuilder-merge-click.gif" alt=""&gt;&lt;/p&gt;
&lt;p&gt;To remove shape segments, hold option or shift-option while dragging or clicking. That’s pretty much it for the shape builder tool. The stacking order of the objects doesn’t matter. In scenarios where there’s a lot of shape segments, the shape builder tool can be a bit of a hassle, but it’s a fast and easy to use way of performing destructive boolean operations once you’ve learnt how it works.&lt;/p&gt;
&lt;p&gt;The pathfinder panel contains a set of 10 actions that operate on the current selection. To unite two circles, select them, then click the unite button in the pathfinder panel. The stacking order does matter for some of the actions, like minus front and minus back. Pathfinder also often groups the result of the action, which is typically not what I want, meaning pathfinder is immediately followed by ungrouping.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/shapebuildervspathfinder/pathfinder-unite.gif" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Pathfinder can work destructively, where the resulting paths are placed on the canvas, or non-destructively, where the original paths are kept. Option-clicking the actions in the pathfinder panel changes them to be non-destructive. Shape builder always acts destructively.&lt;/p&gt;
&lt;p&gt;Shape builder and pathfinder both have a few options to control their behaviour. To open the shape builder options, double-click the shape builder icon in the tool panel, or press enter with the shape builder tool selected. To open the pathfinder options, choose Pathfinder Options from the overflow menu in the pathfinder panel.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/shapebuildervspathfinder/options.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Which is the better interaction method? I prefer working directly with the objects on the canvas. It’s a hassle to move the cursor to the pathfinder panel and back again, and the panel takes valuable screen space that would be better used for the canvas. If pathfinder could be trigged by keyboard shortcuts, that would help keep the cursor on the canvas while working. Some of pathfinder’s actions have vague names, too.&lt;/p&gt;
&lt;p&gt;Shape builder wins this round.&lt;/p&gt;
&lt;h3 id="round-2-unite-everything"&gt;Round 2: Unite everything&lt;/h3&gt;
&lt;p&gt;Uniting a few simple shapes works well with shape builder and pathfinder. But, shape builder is far less efficient when shapes have holes, like the example below. Uniting all the parts requires careful mousing with the freeform method, or lots of marquees using the marquee method. This isn’t even a complex example.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/shapebuildervspathfinder/shapebuilder-unite-everything.gif" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Holding shift to use the marquee method doesn’t help — if the marquee is dragged over everything, holes are included in the result.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/shapebuildervspathfinder/shapebuilder-unite-everything-fail.gif" alt=""&gt;&lt;/p&gt;
&lt;p&gt;The marquee method is about as slow as using the freeform shape builder method.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/shapebuildervspathfinder/shapebuilder-unite-everything-marquee.gif" alt=""&gt;&lt;/p&gt;
&lt;p&gt;In contrast, pathfinder can unite any number of shapes with a single click.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/shapebuildervspathfinder/pathfinder-unite-everything.gif" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Pathfinder wins this round.&lt;/p&gt;
&lt;h3 id="round-3-keep-one-piece"&gt;Round 3: Keep one piece&lt;/h3&gt;
&lt;p&gt;It’s common to use several shapes to construct a single piece you’d like to keep. This technique can be seen in my &lt;a href="https://bjango.com/articles/speedruncamerairis/"&gt;camera iris icon speedrun&lt;/a&gt;. To separate out a single piece with the shape builder tool, simply click the piece you’d like to keep.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/shapebuildervspathfinder/shapebuilder-keeponepiece.gif" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Pathfinder doesn’t have an action to keep a specific piece. The divide action can be used to split up all the pieces. From there, you’ll need to ungroup everything, select the pieces you don’t want, and delete them.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/shapebuildervspathfinder/pathfinder-keeponepiece.gif" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Shape builder wins this round.&lt;/p&gt;
&lt;h3 id="round-4-keep-all-pieces"&gt;Round 4: Keep all pieces&lt;/h3&gt;
&lt;p&gt;If you’d like to keep every piece, the only way to do that with shape builder is to click every single segment. I’m not aware of a way around this.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/shapebuildervspathfinder/shapebuilder-keepallpieces.gif" alt=""&gt;&lt;/p&gt;
&lt;p&gt;As mentioned previously, pathfinder’s divide does exactly what we’re after in this scenario.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/shapebuildervspathfinder/pathfinder-keepallpieces.gif" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Pathfinder wins this round.&lt;/p&gt;
&lt;h3 id="round-5-divide-at-intersections"&gt;Round 5: Divide at intersections&lt;/h3&gt;
&lt;p&gt;Sometimes several shapes are used to accurately capture a path segment needed. Other times, it can be handy to use a shape to cut lots of paths at once. This is a little different to the previous examples — this time we’re focused on the paths, not shape segments.&lt;/p&gt;
&lt;p&gt;With shape builder, it’s possible to option-click a path segment to remove it. The path segment will be cut at the nearest path intersections. This is an incredibly cool feature, and other methods for doing the same thing in Illustrator often require many steps. Pathfinder can not do this.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/shapebuildervspathfinder/shapebuilder-divideatintersections.gif" alt=""&gt;&lt;/p&gt;
&lt;p&gt;With pathfinder, the outline action creates outlines of every shape segment. This means every path segment is cut at the nearest intersections.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/shapebuildervspathfinder/pathfinder-divideatintersections.gif" alt=""&gt;&lt;/p&gt;
&lt;p&gt;This technique is used in my &lt;a href="https://bjango.com/articles/speedrunfingerprint/"&gt;fingerprint icon speedrun&lt;/a&gt;. The fingerprint icon is a good example of something that would be challenging with the shape builder tool — it’d require eight fairly careful option-clicks on the path segments that need to be removed. This is way slower than using pathfinder’s outline action.&lt;/p&gt;
&lt;p&gt;This round is a tie.&lt;/p&gt;
&lt;h3 id="round-6-anchor-point-cleanup"&gt;Round 6: Anchor point cleanup&lt;/h3&gt;
&lt;p&gt;Did you know you can use shape builder and pathfinder to clean up anchor points? They both typically only remove redundant points on straight lines, and work best on 90º lines. They can both also be used to remove coincidental points (anchor points that are on top of each other).&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/shapebuildervspathfinder/shapebuilder-cleanup.gif" alt=""&gt;&lt;/p&gt;
&lt;p&gt;They both do a similar job, but the results can be different, and pathfinder is often slightly better, as can be seen with this hexagon example.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/shapebuildervspathfinder/pathfinder-cleanup.gif" alt=""&gt;&lt;/p&gt;
&lt;p&gt;There’s also scenarios where shape builder adds unneeded anchor points, like when combining these shapes to create a final puzzle piece. The shape builder result has 36 anchor points, while the pathfinder result only has 32 anchor points.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/shapebuildervspathfinder/puzzle-piece.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Pathfinder wins this round.&lt;/p&gt;
&lt;h3 id="round-7-working-with-open-paths"&gt;Round 7: Working with open paths&lt;/h3&gt;
&lt;p&gt;When working with open paths, pathfinder just considers them to be closed, allowing all actions to be performed anyway. Well, all but three actions (divide, trim, and marge). This means pathfinder does something, and it likely does what you’d expect it to do.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/shapebuildervspathfinder/pathfinder-openpaths.gif" alt=""&gt;&lt;/p&gt;
&lt;p&gt;In contrast, shape builder doesn’t let you act on shape segments for open paths. This limitation feels unnecessarily restrictive.&lt;/p&gt;
&lt;p&gt;Pathfinder wins this round.&lt;/p&gt;
&lt;h3 id="round-8-precision"&gt;Round 8: Precision&lt;/h3&gt;
&lt;p&gt;For this test, I united a circle and a rectangle, exported the resulting shape as an SVG, then checked the coordinates. Bézier path intersections are notoriously tricky to do accurately, and it’s common to see rounding errors. Pathfinder seems to have done a better job, and is closer to the ideal result.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/shapebuildervspathfinder/precision.gif" alt=""&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-svg" data-lang="svg"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;// Ideal
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;// 2.6862915 is the correct value
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;path&lt;/span&gt; &lt;span class="na"&gt;d=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;m0,6C0,2.6862915,2.6862915,0,6,0s6,2.6862915,6,6v6H0v-6Z&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;// Shape builder
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;// 2.6900024 is not as close as pathfinder
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;path&lt;/span&gt; &lt;span class="na"&gt;d=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;m12,6v6H0v-6C0,2.6900024,2.6900024,0,6,0s6,2.6900024,6,6Z&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;// Pathfinder
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;// 2.6862793 is pretty good
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;path&lt;/span&gt; &lt;span class="na"&gt;d=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;m6,0C2.6862793,0,0,2.6862793,0,6v6h12v-6c0-3.3137207-2.6862793-6-6-6Z&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Shape builder also encourages multiple actions, which is likely to lead to cumulative rounding errors and paths with more anchor points.&lt;/p&gt;
&lt;p&gt;Pathfinder wins this round.&lt;/p&gt;
&lt;h3 id="final-score"&gt;Final score&lt;/h3&gt;
&lt;p&gt;For those keeping tally, the winner will be obvious. While there are some cases where shape builder is preferable, pathfinder is superior overall. Having said that, I’m going to do my best to use the most appropriate method for each situation.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/shapebuildervspathfinder/score.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;This article is also available as a video: &lt;a href="https://www.youtube.com/watch?v=EprkU5El594"&gt;Shape builder vs pathfinder&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>Formulas for optical adjustments</title><link>https://bjango.com/articles/opticaladjustments/</link><pubDate>Mon, 13 Feb 2023 00:00:00 +0000</pubDate><guid>https://bjango.com/articles/opticaladjustments/</guid><description>&lt;p&gt;A long-standing trope of the design world is that computers are bad at aligning and balancing the relative scales of elements. This is incorrect.&lt;/p&gt;
&lt;p&gt;Nudging elements around until they feel good is typically referred to as “optical adjustment” or “optical alignment”. The pitch is that you can’t rely on the numbers — matching the width and height of two objects doesn’t mean they’ll carry the same visual weight. Instead of typing exact values, you should drag things around until it looks right. The instinct is good, but the execution is too imprecise for my liking. The numbers can be relied on, if the correct calculation for the situation is used.&lt;/p&gt;
&lt;h3 id="squares-and-circles"&gt;Squares and circles&lt;/h3&gt;
&lt;p&gt;A common example used to present the case for humans being in charge of relative scale is a square sitting next to a circle. A square and a circle with matching width and height do not look like they are the same weight. The circle seems smaller.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/opticaladjustments/circle-same-wh.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Rather than just scaling up the circle until you’re feeling good vibes, what if the area of the square and circle matched? Doing this means the circle needs to be scaled by 112.84%.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/opticaladjustments/circle-same-area.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;To make the difference more obvious, here’s the original and larger circles, switching back and forth.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/opticaladjustments/circle-comparison.gif" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Using the area works well for a circle, but, what about a donut? The hole in the middle reduces the total area. This also happens with stars and other shapes. Holes and concave segments should probably be ignored. A method to do this exists, and it’s typically called a &lt;a href="https://en.wikipedia.org/wiki/Convex_hull"&gt;convex hull&lt;/a&gt;. It’s like stretching a rubber band around the entire object. That’s probably a pretty good formula to work out visual weight that matches human perception. Here’s some more shapes, using the convex hull area to set the scale.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/opticaladjustments/lotsofshapes.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;It’s possible there are situations where this will not provide the best result, like a star with very thin spokes. For user interface elements and icons, it’ll also be normal to snap the shape’s size to the nearest pixel boundary, trading scale accuracy for crisper rendering.&lt;/p&gt;
&lt;h3 id="triangles-and-circles"&gt;Triangles and circles&lt;/h3&gt;
&lt;p&gt;To prove alignment can only be properly done by humans, it’s common to show an equilateral triangle inside a circle. This resembles a play icon, and it’s a good example to work with.&lt;/p&gt;
&lt;p&gt;The object alignment feature in design tools often uses fitted bounding boxes to work out where to move elements. A fitted bounding box is the smallest box that can fit the shape. For triangles, the center of the bounding box often does not feel like the center of the triangle, and aligning by this method looks incorrect.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/opticaladjustments/play-boundingbox.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Triangles have many different types of centers, including &lt;a href="https://en.wikipedia.org/wiki/Centroid"&gt;centroid&lt;/a&gt;, incenter, circumcenter, and orthocenter. For equilateral triangles, those all coincide, so it doesn’t matter which is used. Aligning the triangle centroid to the center of the circle now looks right — the distance from the triangle points to the edge of the circle are consistent and it appears perfectly centered.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/opticaladjustments/play-centroid.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Here’s the bounding box and centroid with some construction lines, showing how the center is found.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/opticaladjustments/play-comparison.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Rotating the triangle with the center of the circle as the origin shows how unbalanced the bounding box version is.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/opticaladjustments/play-rotate.gif" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Things could get a bit more complex with scalene triangles (sides and angles don’t match), or if the corners were rounded by different amounts.&lt;/p&gt;
&lt;h3 id="colour"&gt;Colour&lt;/h3&gt;
&lt;p&gt;I don’t have much to say about optical adjustments for colours, except that I often see the difference and I don’t like it. Trying to be too clever can result in complex rules for design systems and color palettes, which do more harm than good.&lt;/p&gt;
&lt;p&gt;If you have some really thin type next to a heavy icon and you’re perceiving the text as a different colour, maybe just choose a heavier typeface?&lt;/p&gt;
&lt;h3 id="find-the-formula-to-match-your-intent"&gt;Find the formula to match your intent&lt;/h3&gt;
&lt;p&gt;In many situations, there will be an appropriate way to express layout intent via a formula. I am not suggesting a calculator should be used every time a shape is created or edited — that’d be slow, and not much fun. I just believe there are very rational reasons for elements to feel balanced.&lt;/p&gt;
&lt;p&gt;No matter what, you’re still going to have to use your best judgement. Hopefully this article sparks a conversion, so we can move beyond superstition and guessing. In situations where you need to automate or animate, having a formula to determine visual weight or alignment can be helpful.&lt;/p&gt;</description></item><item><title>Smaller Mac app icons</title><link>https://bjango.com/articles/smallermacappicons/</link><pubDate>Thu, 12 Jan 2023 00:00:00 +0000</pubDate><guid>https://bjango.com/articles/smallermacappicons/</guid><description>&lt;p&gt;In an effort to reduce the final app size of iStat Menus, we’ve been investigating ways to slim down our app icon. It’s currently about 1.22MB, which is normal for an app icon, but a decent percentage of our bundle.&lt;/p&gt;
&lt;p&gt;As part of the research, I tested which assets are used across the various places icons are shown in macOS. The goal was to identify if we could remove certain icon sizes, or intentionally degrade specific sizes via lossy compression.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/smallermacappicons/smallermacappicons-xcode.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;To test, I created an app icon that shows a different colour for each asset size, with a white sash added for the non-Retina versions.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/smallermacappicons/smallermacappicons-resize-icon.gif" alt=""&gt;&lt;/p&gt;
&lt;h3 id="retina-display-results"&gt;Retina display results&lt;/h3&gt;
&lt;p&gt;For the dock, the 128pt 2× (256px) asset is always used, no matter how big or small the dock is, and even when magnified. Launchpad uses the 256px 1× non-Retina asset, even on a Retina display. This feels like a bug?&lt;/p&gt;
&lt;p&gt;The dock and Finder column view info pane display sizes in pixels are approximates, but should be pretty close to the actual sizes.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/smallermacappicons/smallermacappicons-chart.png" alt=""&gt;&lt;/p&gt;
&lt;h3 id="non-retina-display-results"&gt;Non-retina display results&lt;/h3&gt;
&lt;p&gt;The same tests were run on a non-Retina display by &lt;a href="https://twitter.com/kitgrose"&gt;Kit Grose&lt;/a&gt; (thanks!). Everything matches what you’d expect, and Launchpad uses the correct, non-Retina asset.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/smallermacappicons/smallermacappicons-chart-non-retina.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;All the icon assets are used somewhere, and omitting sizes doesn’t seem wise.&lt;/p&gt;
&lt;h3 id="lossy-compression"&gt;Lossy compression&lt;/h3&gt;
&lt;p&gt;The 1024×1024 app icon asset is only used in two places — the Finder when using icon view with a size over 264pt, and in the Finder’s column view info pane. The icon view only shows an unscaled asset with a size of 512pt, and the column info pane’s icon is always scaled down. With that in mind, lossy compressing just the 1024×1024 icon using &lt;a href="https://pngquant.org"&gt;pngquant&lt;/a&gt; seems like an acceptable trade-off in quality. Pngquant converts PNGs to indexed colour images, while maintaining alpha transparency. It’s a lossy technique, but depending on the source image, it can look good and be far smaller. If you’re going to do it, I’d recommend 256 colours, and you may as well use the best quality, because it’s a quick process.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pngquant 256 --speed 1 icon-1024.png
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The 1024×1024 app icon asset is almost always shown scaled down, so the quantisation of converting to an indexed PNG is partially undone, because the scaled icon averages out the errors. The comparison below shows the most obvious differences in our icon, zoomed really far in. I think it’d be very difficult to spot the difference in the Finder. For icons that don’t contain gradients, the results will likely be even better.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/smallermacappicons/smallermacappicons-quant-errors.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;So far, we’ve opted to not use this technique for iStat Menus, but if you’re looking to shave a little more off your final app size, it’s good.&lt;/p&gt;
&lt;h3 id="asset-catalog-duplicate-files-and-recompression"&gt;Asset catalog duplicate files and recompression&lt;/h3&gt;
&lt;p&gt;By default, asset catalogs for Mac app icons end up with lots of duplicate files — 32×32, 64×64, 128×128, 256×256, and 512×512 are all included twice, even if the same files are used when importing into Xcode. App thinning likely removes duplicates for App Store apps, but that doesn’t help web downloaded apps. Apple’s version of PNGCrush is also used to recompress images, which typically makes files a lot larger than they need to be. The good news is that indexed PNGs are preserved, so running pngquant does still provide benefits.&lt;/p&gt;
&lt;p&gt;We haven’t yet figured out how to stop Xcode from recompressing PNGs as the asset catalog is created. COMPRESS_PNG_FILES=NO and ASSETCATALOG_COMPILER_COMPRESS_PNGS=NO don’t alter the behaviour.&lt;/p&gt;
&lt;p&gt;If you know how to stop PNGs from being recompressed, please &lt;a href="https://bjango.com/contact"&gt;get in contact&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="potential-sizes"&gt;Potential sizes&lt;/h3&gt;
&lt;p&gt;If Mac app icon asset catalogs could just store a single set of the sizes needed, and if the PNGCrush recompression step could be avoided, Mac app icons could take up a lot less space. Here’s the results for our app icon.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/smallermacappicons/smallermacappicons-potential-sizes.png" alt=""&gt;&lt;/p&gt;</description></item><item><title>Icon speedrun videos</title><link>https://bjango.com/articles/iconspeedrunvideos/</link><pubDate>Mon, 19 Dec 2022 00:00:00 +0000</pubDate><guid>https://bjango.com/articles/iconspeedrunvideos/</guid><description>&lt;p&gt;I’m excited to announce the launch of &lt;a href="https://www.youtube.com/@MarcEdwards"&gt;my new YouTube channel&lt;/a&gt;, which will feature videos that cover the types of topics you’d expect as Bjango articles.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/iconspeedrunvideos/iconspeedrunvideos-poster.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;It’s also likely to follow a similar schedule as articles on this website — posts will happen as I get time and have ideas worthy of your attention. There’s five videos up already. Enjoy!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=J_DRxMLUTrs"&gt;8 icons in 2 mins 40 secs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=jlmpkBKKKhw"&gt;Camera iris and puzzle piece&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=dH7D7xB7otU"&gt;Soccer ball and magnet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=GXh2tWvEK1Y"&gt;Fountain pen and fingerprint&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=e_hI4y4u2BE"&gt;Flag and pushpin&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Fingerprint icon speedrun</title><link>https://bjango.com/articles/speedrunfingerprint/</link><pubDate>Sat, 19 Nov 2022 00:00:00 +0000</pubDate><guid>https://bjango.com/articles/speedrunfingerprint/</guid><description>&lt;p&gt;When viewing my &lt;a href="https://bjango.com/articles/iconspeedruns/"&gt;vector icon speedruns&lt;/a&gt;, it can be difficult to see precisely what’s going on. Everything happens quickly, with many actions triggered via keyboard shortcuts, and Illustrator’s interface is cropped out of view. That’s just the nature of what they are, which means they provide more entertainment than education.&lt;/p&gt;
&lt;p&gt;This article aims to be a director’s commentary for my fingerprint icon speedrun, noting the techniques used, and why they were chosen. I use Adobe Illustrator for all the icon speedruns, but many of the tips are relevant for other design tools.&lt;/p&gt;
&lt;p&gt;My personal best for this icon is around &lt;a href="https://bjango.com/images/articles/speedrunfingerprint/fingerprint-12-seconds.mp4"&gt;12 seconds&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/speedrunfingerprint/fingerprint-speedrun.gif" alt="A fingerprint icon being drawn in Adobe Illustrator"&gt;&lt;/p&gt;
&lt;h3 id="workspace"&gt;Workspace&lt;/h3&gt;
&lt;p&gt;One important aspect to working quickly is setting up your workspace. When designing icons, I like having a working area well defined, with the center point marked. Both are locked, so I can’t accidentally move or alter them. The “working area” is typically the target icon size. In this example, I’m using a 16×16px area.&lt;/p&gt;
&lt;p&gt;Working to a coarse grid is faster and more accurate. If points need to be placed off-grid, Illustrator’s move window can be used, allowing for precise numeric offsets. Illustrator’s snap to pixel has some behaviour I don’t like, so I use &lt;a href="https://bjango.com/articles/illustratorsnapping/"&gt;snap to grid&lt;/a&gt; instead.&lt;/p&gt;
&lt;p&gt;Mac shortcuts are noted below, so please substitute control for command, and alt for option if you’re using Windows.&lt;/p&gt;
&lt;h3 id="step-1"&gt;Step 1&lt;/h3&gt;
&lt;p&gt;Switch to the ellipse tool and draw a circle that’s 20×20px. With the direct selection tool, select the top and left points of the circle and delete them by pressing the delete key, or by cutting them with command-X. I often cut instead of deleting points and objects, because it means my left hand can stay in the same position on the keyboard.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/speedrunfingerprint/fingerprint-step-1.gif" alt="Step 1 of a fingerprint icon being drawn in Adobe Illustrator"&gt;&lt;/p&gt;
&lt;p&gt;We’re after a 1px stroke and no fill for the path. If your path has a black fill, pressing &lt;code&gt;shift-X&lt;/code&gt; will swap the fill and stroke. Open the stroke panel and set the stroke to be 1px wide with a round cap.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/speedrunfingerprint/stroke.png" alt="The stroke panel in Adobe Illustrator"&gt;&lt;/p&gt;
&lt;h3 id="step-2"&gt;Step 2&lt;/h3&gt;
&lt;p&gt;Illustrator’s offset path command creates a new path that follows the perimeter of the selected path, but offset by a specified amount. It’s like creating a stroke, then outlining the stroke.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/speedrunfingerprint/fingerprint-step-2.gif" alt="Step 2 of a fingerprint icon being drawn in Adobe Illustrator"&gt;&lt;/p&gt;
&lt;p&gt;For our icon, it’ll help turn our quarter circle into fingerprint ridges. Choose &lt;code&gt;Object&lt;/code&gt; › &lt;code&gt;Path&lt;/code&gt; › &lt;code&gt;Offset Path&lt;/code&gt;, and set the offset to be 2px, and the joins to be rounded. Repeat this another two times. There should be three new paths in total at this point. Choose &lt;code&gt;Object&lt;/code&gt; › &lt;code&gt;Path&lt;/code&gt; › &lt;code&gt;Offset Path&lt;/code&gt; again, but this time set the offset to be 1px.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/speedrunfingerprint/offset-path-window.png" alt="The offset path window in Adobe Illustrator"&gt;&lt;/p&gt;
&lt;h3 id="step-3"&gt;Step 3&lt;/h3&gt;
&lt;p&gt;With the outer ring still selected, switch to the rotate tool, and click the center of the icon area to set the origin, then drag while holding shift to rotate while constraining the angle. It’s also possible to option-click on the canvas to open up the rotate window, so exact values can be typed in.&lt;/p&gt;
&lt;p&gt;Switch to the selection tool and drag a marquee across all the paths to select them. In the pathfinder panel, click &lt;code&gt;Outline&lt;/code&gt;. This cuts all the paths at their intersection points.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/speedrunfingerprint/fingerprint-step-3.gif" alt="Step 3 of a fingerprint icon being drawn in Adobe Illustrator"&gt;&lt;/p&gt;
&lt;p&gt;Choose &lt;code&gt;Object&lt;/code&gt; › &lt;code&gt;Ungroup&lt;/code&gt;, then open the stroke panel and set the stroke to be 1px with a rounded cap. Turn on the dashed line checkbox and set an 8px dash with a 2px gap. We’re almost done.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/speedrunfingerprint/dashed-stroke.png" alt="The stroke panel in Adobe Illustrator"&gt;&lt;/p&gt;
&lt;h3 id="step-4"&gt;Step 4&lt;/h3&gt;
&lt;p&gt;Switch to the selection tool, hold shift, and drag a marquee selection around the parts of the icon we’d like to keep. Holding shift toggles the selection — things that were selected will be unselected, and things that weren’t selected will become selected. Press delete or command-X to remove the paths we don’t need.&lt;/p&gt;
&lt;p&gt;Switch to the scissors tool and cut a couple of the paths near the ends. This alters the dash start positions, and makes the fingerprint ridges look more unique.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/speedrunfingerprint/fingerprint-step-4.gif" alt="Step 4 of a fingerprint icon being drawn in Adobe Illustrator"&gt;&lt;/p&gt;
&lt;p&gt;This article is also available as a video: &lt;a href="https://www.youtube.com/watch?v=GXh2tWvEK1Y"&gt;Icon speedruns: Fountain pen and fingerprint&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>Fountain pen icon speedrun</title><link>https://bjango.com/articles/speedrunpen/</link><pubDate>Thu, 17 Nov 2022 00:00:00 +0000</pubDate><guid>https://bjango.com/articles/speedrunpen/</guid><description>&lt;p&gt;When viewing my &lt;a href="https://bjango.com/articles/iconspeedruns/"&gt;vector icon speedruns&lt;/a&gt;, it can be difficult to see precisely what’s going on. Everything happens quickly, with many actions triggered via keyboard shortcuts, and Illustrator’s interface is cropped out of view. That’s just the nature of what they are, which means they provide more entertainment than education.&lt;/p&gt;
&lt;p&gt;This article aims to be a director’s commentary for my fountain pen icon speedrun, noting the techniques used, and why they were chosen. I use Adobe Illustrator for all the icon speedruns, but many of the tips are relevant for other design tools.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/speedrunpen/pen-speedrun.gif" alt="A fountain pen icon being drawn in Adobe Illustrator"&gt;&lt;/p&gt;
&lt;h3 id="workspace"&gt;Workspace&lt;/h3&gt;
&lt;p&gt;One important aspect to working quickly is setting up your workspace. When designing icons, I like having a working area well defined, with the center point marked. Both are locked, so I can’t accidentally move or alter them. The “working area” is typically the target icon size. In this example, I’m using a 16×16px area.&lt;/p&gt;
&lt;p&gt;Working to a coarse grid is faster and more accurate. If points need to be placed off-grid, Illustrator’s move window can be used, allowing for precise numeric offsets. Illustrator’s snap to pixel has some behaviour I don’t like, so I use &lt;a href="https://bjango.com/articles/illustratorsnapping/"&gt;snap to grid&lt;/a&gt; instead.&lt;/p&gt;
&lt;p&gt;Mac shortcuts are noted below, so please substitute control for command, and alt for option if you’re using Windows.&lt;/p&gt;
&lt;h3 id="step-1"&gt;Step 1&lt;/h3&gt;
&lt;p&gt;Start by selecting the polygon tool and creating a hexagon with a radius of 4px. There’s a couple of ways this can be done. Clicking once on the canvas with the polygon tool lets you type in specific values. Or, click and drag to set the radius. While dragging, the up and down arrow keys can be used to increase or decrease the number of sides in the polygon.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/speedrunpen/pen-step-1.gif" alt="Step 1 of a fountain pen icon being drawn in Adobe Illustrator"&gt;&lt;/p&gt;
&lt;p&gt;Switch to the direct selection tool, then drag upwards while holding the option and shift keys. This will create a copy of the hexagon directly above.&lt;/p&gt;
&lt;h3 id="step-2"&gt;Step 2&lt;/h3&gt;
&lt;p&gt;Select the bottom two points of the new hexagon with the direct selection tool. I often prefer dragging a marquee selection around points to select them, rather than clicking and shift-clicking to add the points needed. It can be fewer clicks, but the main benefit is accuracy — it’s harder to make mistakes because the hit zones can be larger.&lt;/p&gt;
&lt;p&gt;Switch to the scale tool and drag the right point outwards a bit over 1px. When some points of a path are selected, Illustrator’s scale, rotate and other transform tools operate just on those points. In this instance, the scale tool moves the points only along the X axis, because they both have the same Y position. The scale tool is a great way to make mirrored adjustments. This is common trick I use when designing.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/speedrunpen/pen-step-2.gif" alt="Step 2 of a fountain pen icon being drawn in Adobe Illustrator"&gt;&lt;/p&gt;
&lt;p&gt;Please note that Illustrator’s bounding box must be turned off when points are being transformed like this. If you’re seeing a bounding box around the selection, choose &lt;code&gt;View&lt;/code&gt; › &lt;code&gt;Hide Bounding Box&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id="step-3"&gt;Step 3&lt;/h3&gt;
&lt;p&gt;Switch back to the direct selection tool and select the top two points. Choose &lt;code&gt;Object&lt;/code&gt; › &lt;code&gt;Align&lt;/code&gt; › &lt;code&gt;Horizontal Align Center&lt;/code&gt; to move both points to the center of the shape (the button in the align panel can also be used).&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/speedrunpen/pen-step-3.gif" alt="Step 3 of a fountain pen icon being drawn in Adobe Illustrator"&gt;&lt;/p&gt;
&lt;p&gt;Because there’s two points on top of each other, the live corner widget can’t be used to round the corner. This can be fixed with a bit of a hack. Open the pathfinder panel and click &lt;code&gt;Unite&lt;/code&gt;. The resulting shape will look the same, but there’s only one point at the top now. Select the point and drag down to form an arc by using the live corner widget.&lt;/p&gt;
&lt;p&gt;Pathfinder’s unite function is a great way to clean up paths, especially when &lt;code&gt;Remove Redundant Points&lt;/code&gt; is enabled. This setting can be found in pathfinder options, in the menu in the pathfinder panel.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/speedrunpen/pathfinder-options.png" alt="Pathfinder options in Adobe Illustrator"&gt;&lt;/p&gt;
&lt;h3 id="step-4"&gt;Step 4&lt;/h3&gt;
&lt;p&gt;Switch to the direct selection tool and click on the lower hexagon to select it. Choose &lt;code&gt;Object&lt;/code&gt; › &lt;code&gt;Path&lt;/code&gt; › &lt;code&gt;Add Anchor Points&lt;/code&gt; to subdivide the path, providing enough points to finish the tip of the pen.&lt;/p&gt;
&lt;p&gt;Drag a marquee selection over the bottom 5 points. Then, switch to the scale tool, click in the center of the hexagon to set the origin, and drag down and across until the tip of the pen is narrower and 1px outside the bottom of the icon area.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/speedrunpen/pen-step-4.gif" alt="Step 4 of a fountain pen icon being drawn in Adobe Illustrator"&gt;&lt;/p&gt;
&lt;h3 id="step-5"&gt;Step 5&lt;/h3&gt;
&lt;p&gt;Switch to the direct selection tool and drag a marquee selection over the lower left and right points. Then drag out the live corner handles to form arcs for the sides of the pen tip.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/speedrunpen/pen-step-5.gif" alt="Step 5 of a fountain pen icon being drawn in Adobe Illustrator"&gt;&lt;/p&gt;
&lt;h3 id="step-6"&gt;Step 6&lt;/h3&gt;
&lt;p&gt;Switch to the pen tool and draw a line from 1px below center of the tip to the center of the lower shape. In the stroke panel, set the weight to 0.25px, then choose &lt;code&gt;Object&lt;/code&gt; › &lt;code&gt;Path&lt;/code&gt; › &lt;code&gt;Outline Stroke&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Switch to the ellipse tool and draw a 1×1px circle near the center of the lower shape. Given grid snapping is turned on, the shape will have to be nudged 0.5 on the X and Y axis. Switch to the selection tool, press enter to open up the move window, and type in the adjustment required (maybe 0.5 in the horizontal field and 0.5 in the vertical field).&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/speedrunpen/pen-step-6.gif" alt="Step 6 of a fountain pen icon being drawn in Adobe Illustrator"&gt;&lt;/p&gt;
&lt;p&gt;Drag a marquee over the 3 bottom shapes that form pen tip, then click &lt;code&gt;Minus Front&lt;/code&gt; in the pathfinder panel. This will remove the top two shapes from the underlying main pen tip shape.&lt;/p&gt;
&lt;h3 id="step-7"&gt;Step 7&lt;/h3&gt;
&lt;p&gt;The last step rotates the icon into place. Switch to the selection tool and drag a marquee over both paths. Switch to the rotate tool and click the center of the icon area to set the origin. Drag to rotate, while holding shift to constrain the angle to 45º.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/speedrunpen/pen-step-7.gif" alt="Step 7 of a fountain pen icon being drawn in Adobe Illustrator"&gt;&lt;/p&gt;
&lt;p&gt;This article is also available as a video: &lt;a href="https://www.youtube.com/watch?v=GXh2tWvEK1Y"&gt;Icon speedruns: Fountain pen and fingerprint&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>Pushpin icon speedrun</title><link>https://bjango.com/articles/speedrunpushpin/</link><pubDate>Wed, 16 Nov 2022 00:00:00 +0000</pubDate><guid>https://bjango.com/articles/speedrunpushpin/</guid><description>&lt;p&gt;When viewing my &lt;a href="https://bjango.com/articles/iconspeedruns/"&gt;vector icon speedruns&lt;/a&gt;, it can be difficult to see precisely what’s going on. Everything happens quickly, with many actions triggered via keyboard shortcuts, and Illustrator’s interface is cropped out of view. That’s just the nature of what they are, which means they provide more entertainment than education.&lt;/p&gt;
&lt;p&gt;This article aims to be a director’s commentary for my pushpin icon speedrun, noting the techniques used, and why they were chosen. I use Adobe Illustrator for all the icon speedruns, but many of the tips are relevant for other design tools.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/speedrunpushpin/pushpin-speedrun.gif" alt="A pushpin icon being drawn in Adobe Illustrator"&gt;&lt;/p&gt;
&lt;h3 id="workspace"&gt;Workspace&lt;/h3&gt;
&lt;p&gt;One important aspect to working quickly is setting up your workspace. When designing icons, I like having a working area well defined, with the center point marked. Both are locked, so I can’t accidentally move or alter them. The “working area” is typically the target icon size. In this example, I’m using a 16×16px area.&lt;/p&gt;
&lt;p&gt;Working to a coarse grid is faster and more accurate. If points need to be placed off-grid, Illustrator’s move window can be used, allowing for precise numeric offsets. Illustrator’s snap to pixel has some behaviour I don’t like, so I use &lt;a href="https://bjango.com/articles/illustratorsnapping/"&gt;snap to grid&lt;/a&gt; instead.&lt;/p&gt;
&lt;p&gt;Mac shortcuts are noted below, so please substitute control for command, and alt for option if you’re using Windows.&lt;/p&gt;
&lt;h3 id="step-1"&gt;Step 1&lt;/h3&gt;
&lt;p&gt;Start by drawing a rectangle that’s 12×2px. With the direct selection tool, select the top two points, and drag the live corner handle (the little circle that appears near corners) to create rounded corners.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/speedrunpushpin/pushpin-step-1.gif" alt="Step 1 of a pushpin icon being drawn in Adobe Illustrator"&gt;&lt;/p&gt;
&lt;p&gt;It’s up to you how rounded the corners should be. In the example above, my corner radius is about 1.5px (stopping before the maximum of 2px). If you’d like to type in a specific value, you can do that in the control bar, or by double clicking a live corner. It’s also possible to option-click live corners to change the corner type.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/speedrunpushpin/illustrator-control-bar.png" alt="Adobe Illustrator’s control bar"&gt;&lt;/p&gt;
&lt;h3 id="step-2"&gt;Step 2&lt;/h3&gt;
&lt;p&gt;Select the entire shape by clicking on it with the selection tool. Then, switch to the rotate tool. Click once on the canvas to set the rotation origin, then click and drag while holding option and shift to rotate a copy that’s also angle constrained. This is a bit of a tricky move, but one that’s worthwhile getting good at, because it works with all the transform tools.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/speedrunpushpin/pushpin-step-2.gif" alt="Step 2 of a pushpin icon being drawn in Adobe Illustrator"&gt;&lt;/p&gt;
&lt;h3 id="step-3"&gt;Step 3&lt;/h3&gt;
&lt;p&gt;Switch to the rectangle tool and create an 8×6px rectangle that connects the two other shapes. Switch to the direct selection tool and drag a marquee that selects the top of the pushpin and the top two points of the newly created rectangle.&lt;/p&gt;
&lt;p&gt;We’ll now attempt to taper the pushpin and scale the top in one move. Switch to the scale tool and click in the center of the rectangle to set the scale origin. Then, click and drag from the top right point towards the center. In my icon, i’m moving the top right corner 2px left and 1px down. Please note that Illustrator’s bounding box must be turned off when points are being transformed like this. If you’re seeing a bounding box around the selection, choose &lt;code&gt;View&lt;/code&gt; › &lt;code&gt;Hide Bounding Box&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/speedrunpushpin/pushpin-step-3.gif" alt="Step 3 of a pushpin icon being drawn in Adobe Illustrator"&gt;&lt;/p&gt;
&lt;h3 id="step-4"&gt;Step 4&lt;/h3&gt;
&lt;p&gt;Switch to the rectangle tool and draw a 2×6px rectangle for the pushpin’s tip. Then, choose &lt;code&gt;Object&lt;/code&gt; › &lt;code&gt;Path&lt;/code&gt; › &lt;code&gt;Add Anchor Points&lt;/code&gt; to subdivide the path.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/speedrunpushpin/pushpin-step-4.gif" alt="Step 4 of a pushpin icon being drawn in Adobe Illustrator"&gt;&lt;/p&gt;
&lt;h3 id="step-5"&gt;Step 5&lt;/h3&gt;
&lt;p&gt;Switch to the direct selection tool and select the bottom left and bottom right corner points, then choose &lt;code&gt;Object&lt;/code&gt; › &lt;code&gt;Path&lt;/code&gt; › &lt;code&gt;Remove Anchor Points&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Select the points on the left and right side, and drag the live corner handles until the segments become thicker. This indicates that the corners are the largest radius possible. The resulting shape is two perfect arcs forming a sharp tip at the bottom.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/speedrunpushpin/pushpin-step-5.gif" alt="Step 5 of a pushpin icon being drawn in Adobe Illustrator"&gt;&lt;/p&gt;
&lt;h3 id="step-6"&gt;Step 6&lt;/h3&gt;
&lt;p&gt;All that’s left now is to rotate the shape by 45º. Switch to the selection tool, and drag a marquee to select the entire shape. Then, switch to the rotate tool, click once in the center of the icon area to set the rotation origin, then drag while holding shift to rotate while constraining to 45º increments (or whatever angle increment is set under &lt;code&gt;Illustrator&lt;/code&gt; › &lt;code&gt;Preferences&lt;/code&gt; › &lt;code&gt;Smart Guides&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/speedrunpushpin/pushpin-step-6.gif" alt="Step 6 of a pushpin icon being drawn in Adobe Illustrator"&gt;&lt;/p&gt;
&lt;p&gt;This article is also available as a video: &lt;a href="https://www.youtube.com/watch?v=e_hI4y4u2BE"&gt;Icon speedruns: Flag and pushpin&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>Flag icon speedrun</title><link>https://bjango.com/articles/speedrunflag/</link><pubDate>Tue, 15 Nov 2022 00:00:00 +0000</pubDate><guid>https://bjango.com/articles/speedrunflag/</guid><description>&lt;p&gt;When viewing my &lt;a href="https://bjango.com/articles/iconspeedruns/"&gt;vector icon speedruns&lt;/a&gt;, it can be difficult to see precisely what’s going on. Everything happens quickly, with many actions triggered via keyboard shortcuts, and Illustrator’s interface is cropped out of view. That’s just the nature of what they are, which means they provide more entertainment than education.&lt;/p&gt;
&lt;p&gt;This article aims to be a director’s commentary for my flag icon speedrun, noting the techniques used, and why they were chosen. I use Adobe Illustrator for all the icon speedruns, but many of the tips are relevant for other design tools.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/speedrunflag/flag-speedrun.gif" alt="A flag icon being drawn in Adobe Illustrator"&gt;&lt;/p&gt;
&lt;h3 id="workspace"&gt;Workspace&lt;/h3&gt;
&lt;p&gt;One important aspect to working quickly is setting up your workspace. When designing icons, I like having a working area well defined, with the center point marked. Both are locked, so I can’t accidentally move or alter them. The “working area” is typically the target icon size. In this example, I’m using a 16×16px area.&lt;/p&gt;
&lt;p&gt;Working to a coarse grid is faster and more accurate. If points need to be placed off-grid, Illustrator’s move window can be used, allowing for precise numeric offsets. Illustrator’s snap to pixel has some behaviour I don’t like, so I use &lt;a href="https://bjango.com/articles/illustratorsnapping/"&gt;snap to grid&lt;/a&gt; instead.&lt;/p&gt;
&lt;p&gt;Mac shortcuts are noted below, so please substitute control for command, and alt for option if you’re using Windows.&lt;/p&gt;
&lt;h3 id="step-1"&gt;Step 1&lt;/h3&gt;
&lt;p&gt;Start by drawing a rectangle that’s 12×6px. Holding option when creating shapes draws them from the center. With snapping turned on, this means the resulting shape will always be even by even dimensions. It’s also a good technique for situations where you know the center point you’d like for the object.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/speedrunflag/flag-step-1.gif" alt="Step 1 of a flag icon being drawn in Adobe Illustrator"&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Object&lt;/code&gt; › &lt;code&gt;Path&lt;/code&gt; › &lt;code&gt;Add Anchor Points&lt;/code&gt; can then be used to subdivide each path segment into two parts. We’re after more points along the top and bottom of the rectangle, but there’s no way to selectively add anchor points to just part of the path. One way to solve this is to switch to the direct selection tool, then select the points in the left and right sides, and remove them with &lt;code&gt;Object&lt;/code&gt; › &lt;code&gt;Path&lt;/code&gt; › &lt;code&gt;Remove Anchor Points&lt;/code&gt;. This removes the points and connects the surrounding points. It’s different to pressing delete, which removes the points and segments.&lt;/p&gt;
&lt;p&gt;After the side points have been removed, &lt;code&gt;Object&lt;/code&gt; › &lt;code&gt;Path&lt;/code&gt; › &lt;code&gt;Add Anchor Points&lt;/code&gt; can be used again to add more points to the top and bottom, and re-add the left and right points back again. The flag now has all the points we need.&lt;/p&gt;
&lt;h3 id="step-2"&gt;Step 2&lt;/h3&gt;
&lt;p&gt;With the direct selection tool, select the six points shown below, and drag or nudge them up 2px.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/speedrunflag/flag-step-2.gif" alt="Step 2 of a flag icon being drawn in Adobe Illustrator"&gt;&lt;/p&gt;
&lt;h3 id="step-3"&gt;Step 3&lt;/h3&gt;
&lt;p&gt;I find it’s often easier and better to start with a polygon, then round the shape with Illustrator’s live corners, rather than using the pen tool or dragging bézier handles around. Live corners always result in perfect arcs, which can be a nice stylistic choice for geometric icons.&lt;/p&gt;
&lt;p&gt;With the direct selection tool, select the four points shown below, and drag the live corner handle (the little circle that appears near corners) to create rounded corners. When the line segment gets thicker, you’ve reached the largest radius possible.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/speedrunflag/flag-step-3.gif" alt="Step 3 of a flag icon being drawn in Adobe Illustrator"&gt;&lt;/p&gt;
&lt;p&gt;Clicking on the canvas with a shape creation tool lets the width, height and other parameters for the shape be typed in. Option-clicking the canvas creates from the center as well.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/speedrunflag/illustrator-object-size.png" alt="The move window in Adobe Illustrator"&gt;&lt;/p&gt;
&lt;h3 id="step-4"&gt;Step 4&lt;/h3&gt;
&lt;p&gt;The side points now need to be dragged in 1px. The right point needs to also be moved down 0.5px.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/speedrunflag/flag-step-4.gif" alt="Step 4 of a flag icon being drawn in Adobe Illustrator"&gt;&lt;/p&gt;
&lt;p&gt;I have an &lt;a href="https://bjango.com/designresources/#greyprint"&gt;action&lt;/a&gt; for this, but another easy technique is to press enter to bring up the move window, which lets exact values be typed in.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/speedrunflag/move-window.png" alt="The move window in Adobe Illustrator"&gt;&lt;/p&gt;
&lt;h3 id="step-5"&gt;Step 5&lt;/h3&gt;
&lt;p&gt;Select the rectangle tool and draw the pole. That’s it!&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/speedrunflag/flag-step-5.gif" alt="Step 5 of a flag icon being drawn in Adobe Illustrator"&gt;&lt;/p&gt;
&lt;p&gt;This article is also available as a video: &lt;a href="https://www.youtube.com/watch?v=e_hI4y4u2BE"&gt;Icon speedruns: Flag and pushpin&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>Designing macOS menu bar extras</title><link>https://bjango.com/articles/designingmenubarextras/</link><pubDate>Mon, 25 Apr 2022 00:00:00 +0000</pubDate><guid>https://bjango.com/articles/designingmenubarextras/</guid><description>&lt;p&gt;Apple’s HIG is great, but it doesn‘t contain much information related to designing &lt;a href="https://developer.apple.com/design/human-interface-guidelines/macos/extensions/menu-bar-extras/"&gt;menu bar extras&lt;/a&gt;. This article aims to provide additional details and context needed to create icons for macOS menu bar extras.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/designingmenubarextras/menu-bar-icons.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;The height of the Mac menu bar has grown a little over time, starting at 19pt on System 1, growing to 21pt for the Mac OS X beta, then 22pt in Yosemite, and finally 24pt in Big Sur, which is where it stands today.&lt;/p&gt;
&lt;p&gt;Those sizes are in points, where 1 point is equal to 1 non-Retina pixel and 2 Retina pixels. The menu bar screenshots below are from &lt;a href="https://512pixels.net/projects/aqua-screenshot-library/"&gt;512 Pixels&lt;/a&gt; and the &lt;a href="https://guidebookgallery.org/screenshots"&gt;Graphical User Interface Gallery&lt;/a&gt;. It’s interesting to see how the menu bar has grown over the past few decades.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/designingmenubarextras/menu-bar-history.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;14-inch and 16-inch MacBook Pros with a camera housing at the top of the screen have an even taller menu bar, measuring 37pt. When display scaling is used, the menu bar changes height to ensure it always fits the camera housing. On a 14-inch MacBook Pro the menu bar can be 27pt, 29pt, 34pt, 37pt, or 43pt tall, depending on the display scaling setting.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/designingmenubarextras/menu-bar-display-scaling.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;On a 16-inch MacBook Pro, it’s almost the same, but the middle display scaling menu bar height is 33pt, rather than 34pt. I’m not sure why.&lt;/p&gt;
&lt;h3 id="menu-bar-extra-size"&gt;Menu bar extra size&lt;/h3&gt;
&lt;p&gt;Despite the variation in possible menu bar heights, the working area for menu bar extras is fixed at 22pt, and items can not be taller. A good size for a circular item to feel the same weight as system menu bar items is 16×16pt. Assets can be a different size, provided they’re not taller than 22pt.&lt;/p&gt;
&lt;p&gt;There should typically not be any padding, unless it is needed to assist with vertical centering.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/designingmenubarextras/menu-bar-template.png" alt=""&gt;&lt;/p&gt;
&lt;h3 id="colour-and-template-images"&gt;Colour and template images&lt;/h3&gt;
&lt;p&gt;Menu bar extras can be full colour, or monochrome &lt;a href="https://developer.apple.com/documentation/appkit/nsimage/1520017-template"&gt;template images&lt;/a&gt;. A template image is a standard image, but macOS will ignore the colour, and only use the alpha channel information. Template images are preferred, because they’re automatically tinted to match the system icons in light mode and dark mode, without the need for different assets.&lt;/p&gt;
&lt;p&gt;Given colour is ignored, template image artwork should be created as a solid colour icon. If needed, it’s possible to use different levels of opacity to provide shading. This is often used to indicate state, like volume or Wi-Fi strength. Apple typically uses 35% opacity to indicate disabled elements.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/designingmenubarextras/menu-bar-opacity.png" alt=""&gt;&lt;/p&gt;
&lt;h3 id="file-format"&gt;File format&lt;/h3&gt;
&lt;p&gt;Menu bar extra image assets can be a single SVG, a single PDF, or a pair of PNGs (1× and 2× scales for non-Retina and Retina displays). They can also be drawn with code, if you require something dynamic, like an analogue clock or a calendar icon that shows the day of the month.&lt;/p&gt;
&lt;h3 id="reduce-transparency"&gt;Reduce transparency&lt;/h3&gt;
&lt;p&gt;The reduce transparency option under accessibility in system preferences changes the menu bar to be dark grey or light grey, rather than a colour that’s similar to the desktop background. The reduce transparency preference can be a good way to get cleaner screenshots of the menu bar, and it’s worth being aware that some people will see your menu bar extra with this option enabled.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/designingmenubarextras/reduce-transparency.png" alt=""&gt;&lt;/p&gt;</description></item><item><title>SVG passthrough precision</title><link>https://bjango.com/articles/svgpassthroughprecision/</link><pubDate>Mon, 18 Apr 2022 00:00:00 +0000</pubDate><guid>https://bjango.com/articles/svgpassthroughprecision/</guid><description>&lt;p&gt;If an SVG is imported into a design tool, then immediately exported as another SVG, how much precision is kept? What’s added, removed, or altered?&lt;/p&gt;
&lt;p&gt;To test rounding precision, an SVG can be created with elements covering the range of decimal places to check. In the example below, the X and Y positions of rectangles hold values with 1 to 10 decimal places. Passing it through a design tool reveals the tool’s precision.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-svg" data-lang="svg"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.1&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.1&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.01&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.01&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.001&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.001&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.0001&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.0001&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.00001&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.00001&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.000001&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.000001&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.0000001&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.0000001&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.00000001&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.00000001&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.000000001&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.000000001&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.0000000001&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.0000000001&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For &lt;a href="https://bjango.com/articles/svgexports/"&gt;ideal SVG exporting&lt;/a&gt;, design tools should have settings for rounding precision — lower precision can result in smaller files that are good for production assets, and higher precision can be good when transporting artwork between tools, where file size doesn’t matter.&lt;/p&gt;
&lt;p&gt;This is an important test, because post processing SVGs with a tool like &lt;a href="https://github.com/svg/svgo"&gt;SVGO&lt;/a&gt; can not recover lost data. Once it’s gone, it’s gone.&lt;/p&gt;
&lt;h3 id="affinity-designer"&gt;Affinity Designer&lt;/h3&gt;
&lt;p&gt;Here’s the resulting SVG exported from Affinity Designer. The markup is nice and clean, but it stops at 3 decimal place of precision, which I don’t consider to be enough for many uses. There’s no settings for controlling rounding.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-svg" data-lang="svg"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.1&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.1&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.01&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.01&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.001&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.001&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="figma"&gt;Figma&lt;/h3&gt;
&lt;p&gt;Figma’s SVG makes it to 4 decimal places. Rectangles are converted to paths, which results in a larger and messier SVG that would be harder to hand edit. It’s also interesting how the fill is a named colour (“black”). Black is the default shape colour for SVGs, so the fill attribute can be omitted entirely, as per the source SVG.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-svg" data-lang="svg"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;path&lt;/span&gt; &lt;span class="na"&gt;d=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;M20.1 10.1H10.1V20.1H20.1V10.1Z&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;fill=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;black&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;path&lt;/span&gt; &lt;span class="na"&gt;d=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;M20.01 10.01H10.01V20.01H20.01V10.01Z&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;fill=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;black&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;path&lt;/span&gt; &lt;span class="na"&gt;d=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;M20.001 10.001H10.001V20.001H20.001V10.001Z&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;fill=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;black&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;path&lt;/span&gt; &lt;span class="na"&gt;d=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;M20.0001 10.0001H10.0001V20.0001H20.0001V10.0001Z&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;fill=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;black&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;path&lt;/span&gt; &lt;span class="na"&gt;d=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;M20 10H10V20H20V10Z&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;fill=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;black&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;path&lt;/span&gt; &lt;span class="na"&gt;d=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;M20 10H10V20H20V10Z&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;fill=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;black&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;path&lt;/span&gt; &lt;span class="na"&gt;d=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;M20 10H10V20H20V10Z&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;fill=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;black&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;path&lt;/span&gt; &lt;span class="na"&gt;d=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;M20 10H10V20H20V10Z&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;fill=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;black&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;path&lt;/span&gt; &lt;span class="na"&gt;d=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;M20 10H10V20H20V10Z&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;fill=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;black&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;path&lt;/span&gt; &lt;span class="na"&gt;d=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;M20 10H10V20H20V10Z&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;fill=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;black&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="illustrator"&gt;Illustrator&lt;/h3&gt;
&lt;p&gt;Using Illustrator’s Export As export method gets to 5 decimal places. Export As does have some settings, and 5 decimal places is the maximum precision that can be set. Interestingly, this also sets the rounding when copying objects to the clipboard and pasting them as SVGs into other tools or a text editor.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-svg" data-lang="svg"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.1&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.1&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.01&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.01&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.001&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.001&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.0001&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.0001&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.00001&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.00001&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Being a large app with multiple ways to do almost everything, Illustrator also has multiple methods to export SVGs. Exporting an SVG via the Save As menu command results in something that’s far worse than Export As, and is frankly a bit of a mess.&lt;/p&gt;
&lt;p&gt;It’s difficult to assess the precision of Save As’ SVG. The values contained in the SVG would visually look almost identical to Export As, but the results don’t match the input. 10.1000004 is not 10.1. What’s up with the width and height changing? I know float to string conversions are difficult, but Export As gets this right, as do other design tools. I consider numerically incorrect values to be a failure, so Save As doesn’t successfully meet the criteria for 1 decimal place of precision. Thankfully, Export As can be used instead of Save As.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-svg" data-lang="svg"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.1000004&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.1000004&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.0100002&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.0100002&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.0010004&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.0010004&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;9.999999&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;9.999999&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.0001001&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.0001001&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;9.999999&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;9.999999&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.0000095&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.0000095&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.000001&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.000001&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;9.999999&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;9.999999&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is pretty interesting, because the settings for Save As go up to 7 decimal places. You might think it’s more precise than Export As, but it’s not. The image below also contains the settings I used for Export As and Save As.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/svgpassthroughprecision/illustrator-settings.png" alt=""&gt;&lt;/p&gt;
&lt;h3 id="sketch"&gt;Sketch&lt;/h3&gt;
&lt;p&gt;Precision wise, Sketch was the best tool tested, with 7 decimal places of precision successfully passed through. The fill attribute isn’t needed, and it would be good to be able to optionally remove the IDs, but precision wise, this is good.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-svg" data-lang="svg"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Rectangle&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;fill=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;#000000&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.1&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.1&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/rect&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Rectangle&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;fill=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;#000000&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.01&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.01&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/rect&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Rectangle&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;fill=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;#000000&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.001&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.001&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/rect&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Rectangle&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;fill=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;#000000&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.0001&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.0001&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/rect&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Rectangle&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;fill=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;#000000&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.00001&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.00001&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/rect&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Rectangle&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;fill=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;#000000&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.000001&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.000001&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/rect&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Rectangle&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;fill=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;#000000&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.0000001&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.0000001&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/rect&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Rectangle&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;fill=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;#000000&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/rect&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Rectangle&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;fill=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;#000000&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/rect&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Rectangle&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;fill=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;#000000&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/rect&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="xd"&gt;XD&lt;/h3&gt;
&lt;p&gt;XD only makes it to 3 decimal places before giving up. It also uses the transform attribute for position and sprays layer names everywhere. I’m not a fan of this at all.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-svg" data-lang="svg"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Rectangle_2&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;data-name=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Rectangle 2&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;transform=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;translate(10.1 10.1)&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Rectangle_3&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;data-name=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Rectangle 3&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;transform=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;translate(10.01 10.01)&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Rectangle_4&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;data-name=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Rectangle 4&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;transform=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;translate(10.001 10.001)&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Rectangle_5&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;data-name=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Rectangle 5&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;transform=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;translate(10 10)&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Rectangle_6&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;data-name=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Rectangle 6&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;transform=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;translate(10 10)&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Rectangle_7&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;data-name=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Rectangle 7&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;transform=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;translate(10 10)&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Rectangle_8&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;data-name=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Rectangle 8&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;transform=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;translate(10 10)&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Rectangle_9&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;data-name=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Rectangle 9&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;transform=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;translate(10 10)&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Rectangle_10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;data-name=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Rectangle 10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;transform=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;translate(10 10)&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Rectangle_11&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;data-name=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Rectangle 11&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;transform=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;translate(10 10)&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="other-tests"&gt;Other tests&lt;/h3&gt;
&lt;p&gt;So far, only the X and Y position attribute precision have been discussed. I ran similar tests for rectangle width and height, rectangle corner radius, stroke size, polygon anchor point position, bézier control handle position, and object opacity. That’s not a complete set of every single attribute, but it should cover a lot of the common places rounding precision matters.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-svg" data-lang="svg"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;opacity: 0.1&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;opacity: 0.01&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;opacity: 0.001&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;opacity: 0.0001&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;opacity: 0.00001&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;opacity: 0.000001&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;opacity: 0.0000001&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;opacity: 0.00000001&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;opacity: 0.000000001&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;opacity: 0.0000000001&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Surprisingly, every single tool had inconsistent results, with different rounding across different attributes. This was true, even when a setting for the precision existed.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/svgpassthroughprecision/svg-passthrough-precision-chart.png" alt=""&gt;&lt;/p&gt;</description></item><item><title>Ideal SVG exports</title><link>https://bjango.com/articles/svgexports/</link><pubDate>Tue, 12 Apr 2022 00:00:00 +0000</pubDate><guid>https://bjango.com/articles/svgexports/</guid><description>&lt;p&gt;The following article is a random collection of opinions on how design tools should export SVGs. Do you agree? Feel free to &lt;a href="https://twitter.com/marcedwards"&gt;let me know&lt;/a&gt; if you think something is missing or incorrect.&lt;/p&gt;
&lt;p&gt;The XML declaration and namespace should be included in the header, especially if SVG 1.1 or newer is being used. I know skipping it saves some space, and doing so probably won’t cause issues, but it’s only an additional 88 bytes. If you’d like compact files, space can be saved other ways.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-svg" data-lang="svg"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;&amp;lt;?xml version=&amp;#34;1.1&amp;#34; encoding=&amp;#34;utf-8&amp;#34;?&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;svg&lt;/span&gt; &lt;span class="na"&gt;viewBox=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;0 0 30 30&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;http://www.w3.org/2000/svg&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;version=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;1.1&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;/svg&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It should be optional to include the width and height in the SVG tag, so it’s possible to create images that resize to fit their container, or images that maintain a set size. Omitting the width and height is the same as setting them both to 100%.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-svg" data-lang="svg"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;&amp;lt;!-- Resizes to fit container --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;svg&lt;/span&gt; &lt;span class="na"&gt;viewBox=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;0 0 30 30&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;http://www.w3.org/2000/svg&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;version=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;1.1&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;&amp;lt;!-- Maintains fixed size --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;svg&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;30&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;30&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;viewBox=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;0 0 30 30&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;http://www.w3.org/2000/svg&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;version=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;1.1&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I don‘t need to know which tool created an SVG. I’d prefer the exported file was completely absent of comments like the one below. I realise this could be handy for debugging, but it feels more like marketing to me. Skip it.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-svg" data-lang="svg"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;&amp;lt;!-- Generator: Adobe Illustrator 26.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;By default, layer names should not be inserted as IDs or data attributes. Including layer names as IDs makes SVGs larger, harder to edit, and there’s a potential risk of information being unwillingly shared. There are situations where it can be handy, so providing an option is good.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-svg" data-lang="svg"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;&amp;lt;!-- This just makes SVGs larger and harder to edit --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Rectangle_1&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;data-name=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Rectangle 1&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If a value is entered into a design tool, the same value should appear in the SVG, assuming the output isn’t intentionally scaled, transformed, or rounded. It feels strange to mention this, but some tools get it wrong.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-svg" data-lang="svg"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;&amp;lt;!-- This shouldn’t happen if 10 was set as width and height --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;9.999999&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;9.999999&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Rounding on export should be controllable. For production assets you’d like to keep as small as possible, having a 3 or so decimal places of precision might be enough. For transporting artwork at the highest quality possible between tools, 7+ or a way to disable rounding entirely might be needed.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-svg" data-lang="svg"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;&amp;lt;!-- Control over rounding precision is important --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.001&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10.001&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Positions and sizes should be resolved to node elements, and transforms should not be used, unless rotate or skew are included to preserve a primitive shape.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-svg" data-lang="svg"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;&amp;lt;!-- This is nice --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;&amp;lt;!-- This is not as nice --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;transform=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;translate(10 10)&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Where possible, primitives should be used. This means rectangles and rounded rectangles should be &amp;lt;rect&amp;gt;, circles should be &amp;lt;circle&amp;gt;, and ellipses should be &amp;lt;ellipse&amp;gt;. Paths should only be used for things that can not be primitive shapes.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-svg" data-lang="svg"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;&amp;lt;!-- This is nice --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;rx=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;1.1&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;&amp;lt;!-- This is not as nice --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;path&lt;/span&gt; &lt;span class="na"&gt;d=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;M20,11.1c0,-0.607 -0.493,-1.1 -1.1,-1.1l-7.8,0c-0.607,0 -1.1,0.493 -1.1,1.1l0,7.8c0,0.607 0.493,1.1 1.1,1.1l7.8,0c0.607,0 1.1,-0.493 1.1,-1.1l0,-7.8Z&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I prefer hex values over named colours (“hotpink”, “cyan” etc) for tool generated SVGs. There’s nothing wrong with named colours, and they can sometimes be shorter, but I would rather the exporting be consistent across all colours.&lt;/p&gt;
&lt;p&gt;Colours must also be converted to sRGB, if the design tool or document is in another colour space. SVGs can only currently be sRGB, and if colours aren’t converted, they’ll &lt;a href="https://bjango.com/articles/colourmanagementissues/"&gt;probably look incorrect&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I’d like the choice between using CSS styles and inline styles. Both can be good, depending on the situation. CSS styles shouldn’t be wrapped in &amp;lt;defs&amp;gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-svg" data-lang="svg"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;&amp;lt;!-- This is good --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; .c { fill: #ff69b4; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;c&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;&amp;lt;!-- This is also good --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;fill=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;ff69b4&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For path commands, it’d be nice to have a choice between relative and absolute coordinates, with the default being absolute. Bonus points awarded for a third option that automatically uses the method that creates the smallest string. If you ever need to convert path commands between relative and absolute, &lt;a href="https://lea.verou.me/2019/05/utility-convert-svg-path-to-all-relative-or-all-absolute-commands/"&gt;Lea Verou’s converter&lt;/a&gt; is excellent.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-svg" data-lang="svg"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;&amp;lt;!-- Relative coordinates --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;path&lt;/span&gt; &lt;span class="na"&gt;d=&lt;/span&gt;&lt;span class="s"&gt;M9,9c-1,1,-9,1,-9,1c0,0,0,-8,1,-9s9,-1,9,-1c0,0,0,8,-1,9z/&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;&amp;lt;!-- Absolute coordinates --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;path&lt;/span&gt; &lt;span class="na"&gt;d=&lt;/span&gt;&lt;span class="s"&gt;M9,9C8,10,0,10,0,10C0,10,0,2,1,1S10,0,10,0C10,0,10,8,9,9Z/&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It’s nice to have the ability to keep text editable, contained within text tags. It’s also nice to be able to convert text to paths. Converting text to paths typically creates a much larger file, but it also means text renders correctly, even if the font is not available. It’s only appropriate for single words or short phrases though.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-svg" data-lang="svg"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;&amp;lt;!-- Text --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;text&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;a&lt;span class="nt"&gt;&amp;lt;/text&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;&amp;lt;!-- Text converted to a path --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;path&lt;/span&gt; &lt;span class="na"&gt;d=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;M14.08984,16l-.08398-.73145h-.03613c-.32373,.45557-.94727,.86328-1.7749,.86328-1.17529,0-1.7749-.82764-1.7749-1.66699,0-1.40332,1.24707-2.1709,3.48975-2.15869v-.12012c0-.47949-.13184-1.34326-1.31885-1.34326-.54004,0-1.10352,.16797-1.51123,.43164l-.24023-.69531c.47998-.31201,1.17529-.51562,1.90723-.51562,1.7749,0,2.20654,1.21094,2.20654,2.37451v2.1709c0,.50342,.02393,.99512,.09619,1.39111h-.95947Zm-.15625-2.9624c-1.15137-.02393-2.4585,.18018-2.4585,1.30713,0,.68359,.45605,1.00781,.99561,1.00781,.75537,0,1.23535-.47998,1.40332-.97168,.03564-.10791,.05957-.22803,.05957-.33594v-1.00732Z&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Inner and outer strokes are not yet supported in SVGs. Only centered strokes are possible. This means inner and outer strokes need to be outlined when exported, or masked with a clipping path, which adds complexity.&lt;/p&gt;
&lt;p&gt;Attempting to offset a path to convert an inner or outer stroke into a centered stroke doesn’t yield the same result in many scenarios. Even closed paths consisting only of straight line segments can not always be replicated by offsetting the path and using a centered stroke. This just isn’t a viable technique and it should not be used.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/svgexports/strokes.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;It’d be great to have a choice between minified SVGs where everything’s as compact as possible, and beautified SVGs that contain line breaks and indenting, which make debugging and further editing easier.&lt;/p&gt;</description></item><item><title>Mac external displays for designers and developers, part 2</title><link>https://bjango.com/articles/macexternaldisplays2/</link><pubDate>Fri, 01 Apr 2022 00:00:00 +0000</pubDate><guid>https://bjango.com/articles/macexternaldisplays2/</guid><description>&lt;p&gt;Since writing about Mac external displays in 2016, not much has changed. LG, Dell, Samsung, and other display makers have either never catered for the specs many Mac designers and developers want, or they’ve reluctantly produced products that have been short-lived or compromised.&lt;/p&gt;
&lt;p&gt;In 2019, Apple announced their return to the display market, with an incredible product carrying an incredible price tag. The &lt;a href="https://www.apple.com/pro-display-xdr/"&gt;Pro Display XDR&lt;/a&gt; surpasses the specs many Mac users need, which unfortunately also puts it out of reach for many financially.&lt;/p&gt;
&lt;p&gt;2019 also saw an update to LG’s 4K UltraFine display, increasing its size from 21.5-inch to 23.7-inch, but lowering its resolution pixel density. This effectively left the market with a single option — the LG 5K UltraFine. Not only that, but the LG 5K UltraFine has been going in and out of stock globally. It’s unclear to me if the product still exists as a going concern.&lt;/p&gt;
&lt;p&gt;Thankfully, Apple’s new &lt;a href="https://www.apple.com/studio-display/"&gt;Studio Display&lt;/a&gt; now provides a great option.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/macexternaldisplays2/studio-display.jpg" alt="Photo of Apple Studio Display"&gt;&lt;/p&gt;
&lt;p&gt;Spec wise, it’s incredibly similar to LG’s 5K UltraFine, and the display of the now discontinued 27-inch iMac, even though &lt;a href="https://www.dpreview.com/news/8597049512/review-apple-studio-display-2022-an-excellent-monitor-at-a-steep-price"&gt;it’s not using the same panel&lt;/a&gt;. The Studio Display is precisely what I and many others have been asking Apple for — an iMac without the computer. It’s definitely true the Studio Display could have included local dimming, HDR, 120Hz refresh rate and other niceties, but I think that would have been the wrong choice if it meant a higher price. The Studio Display hits an incredibly important target, and it can now be the default choice for discerning Mac designers and developers.&lt;/p&gt;
&lt;p&gt;With that in mind, what are the criteria for a good external Mac display in 2022?&lt;/p&gt;
&lt;h3 id="pixel-density"&gt;Pixel density&lt;/h3&gt;
&lt;p&gt;macOS has been designed to be legible and usable with a pixel density of about 218PPI (pixels per inch) for “Retina” class desktop displays. If a display’s PPI is higher, text and the macOS user interface will be smaller. If a display’s PPI is lower, text and the macOS user interface will be larger. Stray too far from 218PPI and macOS becomes unusable.&lt;/p&gt;
&lt;p&gt;Apple’s laptops have slightly higher pixel density, at 227PPI and 254PPI for the MacBook Air and 16-inch MacBook Pro respectively. This trades a little legibility for screen real estate, while also catering for the closer viewing distance (the closer you get to a display, the larger things look). These choices dictate how physically large text and interface elements appear on the respective devices.&lt;/p&gt;
&lt;p&gt;Everything above assumes macOS is being run without display scaling. Display scaling is a system preferences setting that renders your Mac’s screen to a virtual buffer that is larger or smaller than your display, and then scales the final result to fit. This allows Macs to work with a wide range of displays with different pixel densities.&lt;/p&gt;
&lt;p&gt;However, display scaling comes with some significant caveats, including a blurrier picture, shimmering when scrolling, moiré patterns, worse GPU performance, and worse battery life if you’re using a laptop. Display scaling also undoes dithering, which can mean gradients aren’t as smooth. With those issues in mind, it’s far, far better to run macOS at the pixel density it was designed for.&lt;/p&gt;
&lt;p&gt;The comparisons below are made by simulating a Studio Display on the left and a 4K UHD (3840×2160 pixel) 27-inch display on the right, with macOS display scaling set so text and elements are the same size. The 4K display represents a common high-end display, with a pixel density of around 163PPI. The images are also presented larger to make the issues more pronounced, but these problems can definitely be seen with the naked eye, once you know what to look for. Please note that browser zoom, display scaling and other settings may make it harder to see the differences in the examples below.&lt;/p&gt;
&lt;p&gt;The main issue is that everything’s just blurrier with display scaling enabled.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/macexternaldisplays2/simulated-blurrier.png" alt="A comparison of 218PPI vs simulated 163PPI, showing the 163PPI display being blurrier"&gt;&lt;/p&gt;
&lt;p&gt;When pixels aren’t mapped 1:1 with the macOS window buffer, scrolling means edges and thin lines shimmer when moving.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/macexternaldisplays2/simulated-shimmer.gif" alt="A comparison of 218PPI vs simulated 163PPI, showing the 163PPI display shimmering as fine lines are scrolled"&gt;&lt;/p&gt;
&lt;p&gt;Even when elements aren’t moving, fine details can form moiré patterns. The example below shows a checkerboard being turned into a bit of a lumpy mess.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/macexternaldisplays2/simulated-moire.png" alt="A comparison of 218PPI vs simulated 163PPI, showing the 163PPI display with a moiré pattern"&gt;&lt;/p&gt;
&lt;p&gt;Here’s a couple of photos of a 14-inch MacBook Pro’s screen, taken at the same distance from the display. The example on the left shows 1×1 pt checkerboard pattern with the “default for display” option. The example on the right shows the same pattern with the “more space” display scaling option.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/macexternaldisplays2/photo-macbookpro.jpg" alt="Two close-up photos of a MacBook Pro screen"&gt;&lt;/p&gt;
&lt;p&gt;Not everyone’s going to see these issues or be annoyed by them, but they are very real. There’s also very legitimate reasons for using display scaling, or purchasing displays that can’t run macOS with 1:1 pixel mapping. It’s just good to be aware of the compromises. If you’re after a cheaper option, buying a non-Retina display could be a good choice. For that, you’d want a display that’s around 109PPI. It will look more pixelated though.&lt;/p&gt;
&lt;p&gt;Here’s an overview of the pixel density for Apple’s current displays and some other external display options. You can use Sven Neuhaus’s &lt;a href="https://www.sven.de/dpi/"&gt;PPI calculator&lt;/a&gt; to work out the pixel density of any display you’re interested in.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/macexternaldisplays2/ppi-chart.png" alt="List of external displays and their respective PPI (pixels per inch) values"&gt;&lt;/p&gt;
&lt;h3 id="colour-space"&gt;Colour space&lt;/h3&gt;
&lt;p&gt;The range of colours a display can produce is often noted by its colour space. In 2016, I stated “if you only need sRGB, buy an sRGB only display”. Wider gamut content is more common now, and purchasing something that covers Display P3 or Adobe RGB might be a good idea, especially if you’re looking to keep your display for a while. It’s a bit of a moot point though — all the displays that meet the pixel density requirement cover the Display P3 colour space.&lt;/p&gt;
&lt;p&gt;Future displays will likely cover wider and wider ranges of colours, until the point we hit the limits of human perception (&lt;a href="https://en.wikipedia.org/wiki/Academy_Color_Encoding_System"&gt;ACES&lt;/a&gt;). The next stop on the train for consumer displays might be &lt;a href="https://en.wikipedia.org/wiki/Rec._2020"&gt;Rec.2020&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="bit-depth"&gt;Bit depth&lt;/h3&gt;
&lt;p&gt;Support for wider gamuts increases the need for more steps when expressing colours as digital values. Standard gamut (sRGB) displays typically use 8 bits per component (red, green, and blue, with a total of 256 steps of intensity for each), which results in around 16.7 million different possible colours.&lt;/p&gt;
&lt;p&gt;To avoid issues like gradient banding, 10 bits per component is needed for wide gamut displays. As far as I can tell, the Studio Display, Pro Display XDR, and LG 5K UltraFine all accept 10 bits per component. In Apple’s tech specs, this is typically noted as “1 billion colours”. I believe this means 10 bits per component is sent to the display, but the panel itself may use fewer bits in combination with temporal dithering and other techniques to make the most of the hardware.&lt;/p&gt;
&lt;p&gt;For a wide gamut display, 10 bits per component is a good idea. Once again, the Studio Display meets this requirement. The 24-inch M1 iMac and M1-based 14-inch and 16-inch MacBook Pros also list their displays as supporting “1 billion colours”. The 13-inch MacBook Pro and MacBook Air are both listed as “millions of colours”.&lt;/p&gt;
&lt;h3 id="brightness"&gt;Brightness&lt;/h3&gt;
&lt;p&gt;I barely venture beyond 50% brightness on any Mac desktop display I use. I know others have a different opinion, and some friends use maximum brightness. Your working environment will likely dictate your brightness requirements.&lt;/p&gt;
&lt;h3 id="local-dimming"&gt;Local dimming&lt;/h3&gt;
&lt;p&gt;Splitting a display’s backlight into individually controllable zones can increase the contrast ratio and provide deeper black levels. This is usually called local dimming or mini-LED. The Pro Display XDR, 12.9-inch iPad Pro, 14-inch MacBook Pro, and 16-inch MacBook Pro all have local dimming. I believe Apple denotes this feature as “XDR display” in their tech specs, because using mini-LED backlights provides local dimming, and it can assist with HDR support.&lt;/p&gt;
&lt;p&gt;Local dimming is a great feature, and this is the first improvement I’d like to see on a revised Studio Display in the future (the current Studio Display doesn’t have local dimming). I don’t think local dimming is essential though.&lt;/p&gt;
&lt;h3 id="high-dynamic-range"&gt;High dynamic range&lt;/h3&gt;
&lt;p&gt;HDR (high dynamic range) support is nice to have, but is only critical if you’re viewing or editing high dynamic range content. This may be important for editing video or photos, but is probably not important for most designers and developers.&lt;/p&gt;
&lt;h3 id="refresh-rate"&gt;Refresh rate&lt;/h3&gt;
&lt;p&gt;120Hz refresh rate would be nice to have, but there is no display I’m aware of that meets the macOS pixel density requirement while also providing faster refresh rates. The Studio Display, LG 5K UltraFine and Pro Display XDR are all 60Hz. I believe 5K at 120Hz and 10 bit per component should be technically possible over Thunderbolt 3 with Display Stream Compression, but I may have messed up the calculations.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/macexternaldisplays2/120hz-calculation.png" alt="Bandwidth calculations for 5K 120hz using Display Stream Compression"&gt;&lt;/p&gt;
&lt;h3 id="true-tone-and-night-shift"&gt;True Tone and Night Shift&lt;/h3&gt;
&lt;p&gt;True Tone and Night Shift both move the display’s colours away from the truth. They make what you’re seeing less accurate. When you’re doing any work with colour, I think they should be both turned off. I also think it’s wise to consider your environment, and try to minimise how much variation there is in lighting changes throughout your work day. Human perception is notoriously relative, but I believe constant exposure to a neutral and fixed environment can build muscle memory for colours. The more consistent your space is, the better. There’s a reason video edit suites and colour grading suites have minimal, neutral lighting, often even carefully choosing &lt;a href="https://en.wikipedia.org/wiki/Middle_gray"&gt;paint colours&lt;/a&gt; for walls.&lt;/p&gt;
&lt;p&gt;The health benefits of Night Shift seem to be &lt;a href="https://gimletmedia.com/shows/science-vs/o2hx57"&gt;inconclusive at best&lt;/a&gt;. If you enjoy using it, great. Just turn it off when you’re doing colour critical work.&lt;/p&gt;
&lt;h3 id="my-setup"&gt;My setup&lt;/h3&gt;
&lt;p&gt;I’m currently using a Pro Display XDR, but I would have definitely purchased a Studio Display if it was available when I needed a display. I’m using the default reference mode of P3-500 nits, with True Tone off, Night Shift off, and automatic brightness adjustment off.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/macexternaldisplays2/my-setup.png" alt=""&gt;&lt;/p&gt;</description></item><item><title>Camera iris icon speedrun</title><link>https://bjango.com/articles/speedruncamerairis/</link><pubDate>Fri, 17 Dec 2021 00:00:00 +0000</pubDate><guid>https://bjango.com/articles/speedruncamerairis/</guid><description>&lt;p&gt;When viewing my &lt;a href="https://bjango.com/articles/iconspeedruns/"&gt;vector icon speedruns&lt;/a&gt;, it can be difficult to see precisely what’s going on. Everything happens quickly, with many actions triggered via keyboard shortcuts, and Illustrator’s interface is cropped out of view. That’s just the nature of what they are, which means they provide more entertainment than education.&lt;/p&gt;
&lt;p&gt;This article aims to be a director’s commentary for my camera iris icon speedrun, noting the techniques used, and why they were chosen. I use Adobe Illustrator for all the icon speedruns, but many of the tips are relevant for other design tools.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/speedruncamerairis/camerairis-6-full.gif" alt="A camera iris icon being drawn in Adobe Illustrator"&gt;&lt;/p&gt;
&lt;h3 id="workspace"&gt;Workspace&lt;/h3&gt;
&lt;p&gt;One important aspect to working quickly is setting up your workspace. When designing icons, I like having a working area well defined, with the center point marked. Both are locked, so I can’t accidentally move or alter them. The “working area” is typically the target icon size. In this example, I’m using a 16×16px area.&lt;/p&gt;
&lt;p&gt;Working to a coarse grid is faster and more accurate. If points need to be placed off-grid, Illustrator’s move window can be used, allowing for precise numeric offsets. Illustrator’s snap to pixel has some behaviour I don’t like, so I use &lt;a href="https://bjango.com/articles/illustratorsnapping/"&gt;snap to grid&lt;/a&gt; instead.&lt;/p&gt;
&lt;p&gt;Mac shortcuts are noted below, so please substitute control for command, and alt for option if you’re using Windows.&lt;/p&gt;
&lt;h3 id="step-1"&gt;Step 1&lt;/h3&gt;
&lt;p&gt;Start by drawing a rectangle. The bottom of the rectangle will be the edge of the iris opening, so place it where you’d like that to be. The position of the top, left and right of the rectangle aren’t critical — they just need enough padding to cover the circle we’ll be using for masking later.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/speedruncamerairis/camerairis-step-1.png" alt="The first step of a camera iris icon being drawn in Adobe Illustrator"&gt;&lt;/p&gt;
&lt;h3 id="step-2"&gt;Step 2&lt;/h3&gt;
&lt;p&gt;Switch to the rotate tool, and option-click the center of the icon area. This sets the origin for the rotation and opens up the rotation window, so a specific value can be typed in. Illustrator accepts equations in input fields, so 360/6 can be typed in to work out the angle for a six blade camera iris. If you’d like your iris to have a different number of blades, type in 360 divided by the number of blades you’d like.&lt;/p&gt;
&lt;p&gt;Click copy or press option-enter to create a rotated copy of the original rectangle.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/speedruncamerairis/camerairis-step-2.png" alt="The second step of a camera iris icon being drawn in Adobe Illustrator"&gt;&lt;/p&gt;
&lt;h3 id="step-3"&gt;Step 3&lt;/h3&gt;
&lt;p&gt;With the copied rectangle still selected, remove the fill and give the shape a stroke. The stroke will set the gap between the iris blades. If the stroke is centered, then the size should be double the gap size you’d like. For example, a 2px centered stroke will result in a 1px gap between the blades. Choose &lt;code&gt;Object&lt;/code&gt; › &lt;code&gt;Path&lt;/code&gt; › &lt;code&gt;Outline Stroke&lt;/code&gt; to convert the stroke to a filled path.&lt;/p&gt;
&lt;p&gt;Using &lt;code&gt;Object&lt;/code&gt; › &lt;code&gt;Path&lt;/code&gt; › &lt;code&gt;Offset Path&lt;/code&gt; is another method for achieving the same result. I use strokes and Outline Stroke more often, because I have &lt;a href="https://github.com/bjango/Greyprint"&gt;premade graphic styles&lt;/a&gt; for various common stroke sizes and an action button for outlining strokes, so that’s quicker for me (just two clicks from permanently visible buttons).&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/speedruncamerairis/camerairis-step-3.png" alt="The third step of a camera iris icon being drawn in Adobe Illustrator"&gt;&lt;/p&gt;
&lt;h3 id="step-4"&gt;Step 4&lt;/h3&gt;
&lt;p&gt;Draw a circle that covers the entire icon area. With the ellipse tool selected, click the center of the icon area while holding shift and option to constrain to a circle and set the origin to the centre of the shape.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/speedruncamerairis/camerairis-step-4.png" alt="The forth step of a camera iris icon being drawn in Adobe Illustrator"&gt;&lt;/p&gt;
&lt;h3 id="step-5"&gt;Step 5&lt;/h3&gt;
&lt;p&gt;Select all three shapes, and choose divide from the pathfinder panel. This will break the selection into separate paths, with nothing overlaping. Divide always creates grouped results, so choose &lt;code&gt;Object&lt;/code&gt; › &lt;code&gt;Ungroup&lt;/code&gt; to ungroup everything.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/speedruncamerairis/camerairis-step-5a.png" alt="The fifth step of a camera iris icon being drawn in Adobe Illustrator"&gt;&lt;/p&gt;
&lt;p&gt;All the work up until this point was done to create the correct path for a single iris blade. We now have that path, so delete everything except the top right pie-like section.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/speedruncamerairis/camerairis-step-5b.png" alt="The fifth step of a camera iris icon being drawn in Adobe Illustrator"&gt;&lt;/p&gt;
&lt;p&gt;Constructing geometric icons using primitives and boolean operations is faster and more accurate than using the pen tool. I do use the pen tool, but typically only when there is no other alternative.&lt;/p&gt;
&lt;h3 id="step-6"&gt;Step 6&lt;/h3&gt;
&lt;p&gt;Switch to the rotate tool, and option-click the center of the icon. This sets the origin of rotation and opens up the rotation window. The angle should already be correct from the previous rotation, so you can just click copy or press option-enter.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/speedruncamerairis/camerairis-step-6.png" alt="The sixth step of a camera iris icon being drawn in Adobe Illustrator"&gt;&lt;/p&gt;
&lt;h3 id="step-7"&gt;Step 7&lt;/h3&gt;
&lt;p&gt;Choosing &lt;code&gt;Object&lt;/code&gt; › &lt;code&gt;Transform&lt;/code&gt; › &lt;code&gt;Transform Again&lt;/code&gt; will repeat the last transformation, giving you three blades. Repeat this until you have all six blades, or however many you need. The keyboard shortcut for Transform Again is great to learn for instances like this, where multiple rotated copies are required.&lt;/p&gt;
&lt;p&gt;If you’d like the icon to be orientated differently, I’d rotate now, once everything else has been drawn.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/speedruncamerairis/camerairis-step-7.png" alt="The seventh step of a camera iris icon being drawn in Adobe Illustrator"&gt;&lt;/p&gt;
&lt;h3 id="different-numbers-of-blades"&gt;Different numbers of blades&lt;/h3&gt;
&lt;p&gt;The same steps work with any number of iris blades. Here’s versions with five and seven blades.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/speedruncamerairis/camerairis-5and7-full.gif" alt="Camera iris icons with 5 and 7 blades being drawn in Adobe Illustrator"&gt;&lt;/p&gt;
&lt;h3 id="an-alternate-method"&gt;An alternate method&lt;/h3&gt;
&lt;p&gt;I experimented starting with a polygon, but ultimately it turned out to be more steps and a little harder to control.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bjango.com/images/articles/speedruncamerairis/camerairis-6-full-alt.gif" alt="A camera iris icon being drawn in Adobe Illustrator"&gt;&lt;/p&gt;
&lt;p&gt;This article is also available as a video: &lt;a href="https://www.youtube.com/watch?v=jlmpkBKKKhw"&gt;Icon speedruns: Camera iris and puzzle piece&lt;/a&gt;.&lt;/p&gt;</description></item></channel></rss>