A place to cache linked articles (think custom and personal wayback machine)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

index.html 24KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. <!doctype html><!-- This is a valid HTML5 document. -->
  2. <!-- Screen readers, SEO, extensions and so on. -->
  3. <html lang="fr">
  4. <!-- Has to be within the first 1024 bytes, hence before the `title` element
  5. See: https://www.w3.org/TR/2012/CR-html5-20121217/document-metadata.html#charset -->
  6. <meta charset="utf-8">
  7. <!-- Why no `X-UA-Compatible` meta: https://stackoverflow.com/a/6771584 -->
  8. <!-- The viewport meta is quite crowded and we are responsible for that.
  9. See: https://codepen.io/tigt/post/meta-viewport-for-2015 -->
  10. <meta name="viewport" content="width=device-width,initial-scale=1">
  11. <!-- Required to make a valid HTML5 document. -->
  12. <title>Dunbar’s number and how speaking is 2.8x better than picking fleas (archive) — David Larlet</title>
  13. <meta name="description" content="Publication mise en cache pour en conserver une trace.">
  14. <!-- That good ol' feed, subscribe :). -->
  15. <link rel="alternate" type="application/atom+xml" title="Feed" href="/david/log/">
  16. <!-- Generated from https://realfavicongenerator.net/ such a mess. -->
  17. <link rel="apple-touch-icon" sizes="180x180" href="/static/david/icons2/apple-touch-icon.png">
  18. <link rel="icon" type="image/png" sizes="32x32" href="/static/david/icons2/favicon-32x32.png">
  19. <link rel="icon" type="image/png" sizes="16x16" href="/static/david/icons2/favicon-16x16.png">
  20. <link rel="manifest" href="/static/david/icons2/site.webmanifest">
  21. <link rel="mask-icon" href="/static/david/icons2/safari-pinned-tab.svg" color="#07486c">
  22. <link rel="shortcut icon" href="/static/david/icons2/favicon.ico">
  23. <meta name="msapplication-TileColor" content="#f7f7f7">
  24. <meta name="msapplication-config" content="/static/david/icons2/browserconfig.xml">
  25. <meta name="theme-color" content="#f7f7f7" media="(prefers-color-scheme: light)">
  26. <meta name="theme-color" content="#272727" media="(prefers-color-scheme: dark)">
  27. <!-- Documented, feel free to shoot an email. -->
  28. <link rel="stylesheet" href="/static/david/css/style_2021-01-20.css">
  29. <!-- See https://www.zachleat.com/web/comprehensive-webfonts/ for the trade-off. -->
  30. <link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_regular.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
  31. <link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_bold.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
  32. <link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_italic.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
  33. <link rel="preload" href="/static/david/css/fonts/triplicate_t3_regular.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
  34. <link rel="preload" href="/static/david/css/fonts/triplicate_t3_bold.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
  35. <link rel="preload" href="/static/david/css/fonts/triplicate_t3_italic.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
  36. <script>
  37. function toggleTheme(themeName) {
  38. document.documentElement.classList.toggle(
  39. 'forced-dark',
  40. themeName === 'dark'
  41. )
  42. document.documentElement.classList.toggle(
  43. 'forced-light',
  44. themeName === 'light'
  45. )
  46. }
  47. const selectedTheme = localStorage.getItem('theme')
  48. if (selectedTheme !== 'undefined') {
  49. toggleTheme(selectedTheme)
  50. }
  51. </script>
  52. <meta name="robots" content="noindex, nofollow">
  53. <meta content="origin-when-cross-origin" name="referrer">
  54. <!-- Canonical URL for SEO purposes -->
  55. <link rel="canonical" href="https://interconnected.org/home/2022/04/05/dunbar">
  56. <body class="remarkdown h1-underline h2-underline h3-underline em-underscore hr-center ul-star pre-tick" data-instant-intensity="viewport-all">
  57. <article>
  58. <header>
  59. <h1>Dunbar’s number and how speaking is 2.8x better than picking fleas</h1>
  60. </header>
  61. <nav>
  62. <p class="center">
  63. <a href="/david/" title="Aller à l’accueil"><svg class="icon icon-home">
  64. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-home"></use>
  65. </svg> Accueil</a> •
  66. <a href="https://interconnected.org/home/2022/04/05/dunbar" title="Lien vers le contenu original">Source originale</a>
  67. </p>
  68. </nav>
  69. <hr>
  70. <p class="measure-wide f6 f5-l lh-copy black-80">150, Dunbar’s number, is the natural size of human social groups. Robin Dunbar’s 1993 paper, where he put forward this hypothesis, is a great read – it’s got twists and turns, so much more in it than just the 150 number.</p>
  71. <p class="measure-wide f6 f5-l lh-copy black-80"><em>(If you design software for people to socialise or collaborate, like Slack or Google Docs, then what Dunbar says is useful to know! Also true if you build communities in Discords or DAOs, I reckon, good knowledge to have when structuring the spaces and processes for interaction.)</em></p>
  72. <p class="measure-wide f6 f5-l lh-copy black-80">I’ve added a reference to Dunbar’s paper, <em>Coevolution of neocortical size, group size and language in humans,</em> at the bottom of this post. It’s not online but you can <a href="https://pdodds.w3.uvm.edu/files/papers/others/1993/dunbar1993a.pdf">snag a pre-print PDF here</a>.</p>
  73. <p class="measure-wide f6 f5-l lh-copy black-80">The paper and the number are both super well-known.</p>
  74. <p class="measure-wide f6 f5-l lh-copy black-80">BUT - I insist! - still not well-known <em>enough</em> in our software and design circles. Especially given there is a revitalisation and renewed interest in building and innovating with the social internet.</p>
  75. <p class="measure-wide f6 f5-l lh-copy black-80">So I figured I would share my favourite bits.</p>
  76. <hr class="h1 xh2-ns w1 xw2-ns ml4 mv4 bb bw1 b--white">
  77. <p class="measure-wide f6 f5-l lh-copy black-80">Dunbar lists a bunch of places this 150 group size appears. To pick out a convincing selection…</p>
  78. <ul class="list ph0 ph0-ns bulleted-list">
  79. <li class="measure-wide f6 f5-l lh-copy black-80">6500-5500 BC: <q>the size of Neolithic villages in Mesopotamia are of about the same magnitude.</q></li>
  80. <li class="measure-wide f6 f5-l lh-copy black-80">In South Dakota: <q>the Hutterites regard 150 individuals as the limiting size for their farming communities: once a community reaches this size, steps are taken to split it into two daughter communities.</q></li>
  81. <li class="measure-wide f6 f5-l lh-copy black-80">Academic communities: <q>research specialities in the sciences tend to consist of up to 200 individuals, but rarely more.</q></li>
  82. <li class="measure-wide f6 f5-l lh-copy black-80">Professional armies have a basic unit of about 150 men: <q>This was as true of the Roman Army (both before and after the reforms of 104 BC) as of modern armies since the sixteenth century.</q></li>
  83. <li class="measure-wide f6 f5-l lh-copy black-80">Work: <q>the likelihood of having friends within the workplace reaches an asymptote at a shop size of 90-150 individuals.</q></li>
  84. </ul>
  85. <p class="measure-wide f6 f5-l lh-copy black-80">It’s the number of people on your Christmas card list. When AOL Instant Messenger launched, it was the maximum allowable number of buddies.</p>
  86. <p class="measure-wide f6 f5-l lh-copy black-80"><em>(And the number of Pokemon in generation one… 151. Huh.)</em></p>
  87. <p class="measure-wide f6 f5-l lh-copy black-80">Pretty compelling. Something to be explained.</p>
  88. <hr class="h1 xh2-ns w1 xw2-ns ml4 mv4 bb bw1 b--white">
  89. <p class="measure-wide f6 f5-l lh-copy black-80"><strong>The clever bit:</strong></p>
  90. <p class="measure-wide f6 f5-l lh-copy black-80">The catarrhine primates: Old World monkeys (baboons, macaques, mandrill, and ~130 other species) plus the apes… tailless simians including gibbons, gorillas, chimpanzees, and humans.</p>
  91. <p class="measure-wide f6 f5-l lh-copy black-80">Dunbar’s insight was to look at the catarrhine primates and realise that <strong>these three factors are connected:</strong></p>
  92. <ul class="list ph0 ph0-ns bulleted-list">
  93. <li class="measure-wide f6 f5-l lh-copy black-80">Group size</li>
  94. <li class="measure-wide f6 f5-l lh-copy black-80">Time devoted to social grooming: a bonding mechanism (if you wanna have friends, you gotta spend time picking fleas)</li>
  95. <li class="measure-wide f6 f5-l lh-copy black-80">Neocortex size, being the amount of brain available for tracking the social group, i.e. a limit on <q>the number of relationships that an animal can keep track of in a complex, continuously changing social world</q></li>
  96. </ul>
  97. <p class="measure-wide f6 f5-l lh-copy black-80">Dunbar gives equations that relate these.</p>
  98. <p class="measure-wide f6 f5-l lh-copy black-80">Then:</p>
  99. <blockquote class="bl bw2 pl2 b--orange ml0 italic i">
  100. <p class="measure-wide f6 f5-l lh-copy black-80">If we extrapolate from the nonhuman primate regression, what group size would we predict for anatomically modern humans, given our current neocortex size?</p>
  101. </blockquote>
  102. <p class="measure-wide f6 f5-l lh-copy black-80">Oh-ho, a prediction!</p>
  103. <p class="measure-wide f6 f5-l lh-copy black-80"><q>Equation (1) yields a predicted group size for humans of 147.8.</q></p>
  104. <p class="measure-wide f6 f5-l lh-copy black-80">So there’s the observed number 150, right there in the size of the brain.</p>
  105. <p class="measure-wide f6 f5-l lh-copy black-80">BUT THEN, A TWIST:</p>
  106. <p class="measure-wide f6 f5-l lh-copy black-80"><q>The group size predicted for modern humans by equation (1) would require as much as 42% of the total time budget to be devoted to social grooming.</q></p>
  107. <p class="measure-wide f6 f5-l lh-copy black-80">We <em>(humans)</em> clearly don’t spend all that time on social grooming. There’s not the time in the day. It’s incompatible with resting, foraging, and staying in the shade on hot days. Chimpanzees are the most comparable to humans, and they have a social time budget of about only 15%.</p>
  108. <p class="measure-wide f6 f5-l lh-copy black-80">So what gives?</p>
  109. <p class="measure-wide f6 f5-l lh-copy black-80">Humans, says Dunbar, must have <strong>a method of social grooming that is 2.8x more effective</strong> than the method used by the nonhuman primates. But what is it?</p>
  110. <hr class="h1 xh2-ns w1 xw2-ns ml4 mv4 bb bw1 b--white">
  111. <p class="measure-wide f6 f5-l lh-copy black-80">What is our ultra efficient bonding mechanism, better than caring, grooming, and picking fleas? It is LANGUAGE.</p>
  112. <blockquote class="bl bw2 pl2 b--orange ml0 italic i">
  113. <p class="measure-wide f6 f5-l lh-copy black-80">The observed mean group size for chimpanzees (presumably the closest approximation to the ancestral condition for the hominid lineage) is 53.5 (Dunbar 1992a). Since the predicted size for human groups is 147.8, this implies that <u>language</u> (the human bonding mechanism) ought to be 147.8/53.5=2.76 times as efficient as social grooming (the nonhuman primate bonding mechanism).</p>
  114. </blockquote>
  115. <p class="measure-wide f6 f5-l lh-copy black-80">Speaking is way better than grooming, which requires 100% attention and is one-on-one. But we can talk to more than one person at once! See: <q>not only can speech be combined with almost every other activity (we can forage and talk at the same time), but it can also be used to address several different individuals simultaneously.</q></p>
  116. <p class="measure-wide f6 f5-l lh-copy black-80">Dunbar’s suggestion is that language evolved as a <q>‘cheap’ form of social grooming,</q> a way to increase group size. And there follows a cascade of consequences and speculations…</p>
  117. <hr class="h1 xh2-ns w1 xw2-ns ml4 mv4 bb bw1 b--white">
  118. <p class="measure-wide f6 f5-l lh-copy black-80">The interesting bit, for me, is about the “natural” size of a conversation group.</p>
  119. <p class="measure-wide f6 f5-l lh-copy black-80">Dunbar’s prediction, based on the estimated efficiency gain versus chimps: <q>human conversation group sizes should be limited to about 3.8 in size (one speaker plus 2.8 listeners).</q></p>
  120. <p class="measure-wide f6 f5-l lh-copy black-80">And this holds up!</p>
  121. <ul class="list ph0 ph0-ns bulleted-list">
  122. <li class="measure-wide f6 f5-l lh-copy black-80">Looking at restaurant reservations: <q>the mean size of 3070 groups was 3.8.</q></li>
  123. <li class="measure-wide f6 f5-l lh-copy black-80">In a university refectory: <q>the average number of people directly involved in a conversation (as speaker or attentive listener) reached an asymptotic value of about 3.4 (one speaker plus 2.4 listeners) and that groups tended to partition into new conversational cliques at multiples of about four individuals.</q></li>
  124. </ul>
  125. <p class="measure-wide f6 f5-l lh-copy black-80">Which feels about right, right?</p>
  126. <p class="measure-wide f6 f5-l lh-copy black-80">I mean, think of a sitting with friends round a dinner table. Two people, three people, four people, it’s one conversation. Five people, it’s still one conversation – just. At six it’s hard to maintain; the conversation often splits and oscillates between 4/2 and 3/3 modes.</p>
  127. <p class="measure-wide f6 f5-l lh-copy black-80">The cognitive limit corresponds to how our <em>ears and voices</em> work.</p>
  128. <blockquote class="bl bw2 pl2 b--orange ml0 italic i">
  129. <p class="measure-wide f6 f5-l lh-copy black-80">It turns out that there is, in fact, a psycho-physical limit on the size of conversation groups. Due to the rate at which speech attenuates with the distance between speaker and hearer under normal ambient noise levels, there is a physical limit on the number of individuals that can effectively take part in a conversation. Sommer (1961), for example, found that <u>a nose-to-nose distance of 1.7m was the upper limit for comfortable conversation in dyadic groups; this would yield a maximum conversation group size of five individuals</u> with a shoulder-to-shoulder spacing of 0.5m between adjacent individuals standing around the circumference of a circle.</p>
  130. </blockquote>
  131. <p class="measure-wide f6 f5-l lh-copy black-80">“Comfortable” conversation means <q>background noise levels typical of both offices and city streets</q> – our normal voice levels, our normal hearing, our normal comfortable personal social distance, our normal <em>width of shoulders</em> all combine to produce conversional groups of… 5 people.</p>
  132. <p class="measure-wide f6 f5-l lh-copy black-80">Absolutely wonderful. It makes me laugh every time I read this bit.</p>
  133. <hr class="h1 xh2-ns w1 xw2-ns ml4 mv4 bb bw1 b--white">
  134. <p class="measure-wide f6 f5-l lh-copy black-80"><strong>Evidence for Dunbar’s Number in the analysis of 6 billion phone calls:</strong></p>
  135. <p class="measure-wide f6 f5-l lh-copy black-80">Dunbar actually doesn’t say that we devote “grooming time” to the whole social group of 150. Rather he says that the 150 is made up from <q>welding together</q> much smaller “primary networks”: coalitions, friendship groups. Intensive grooming (language, for humans) is reserved for close friends. Our intimate group is very small, averaging just five.</p>
  136. <p class="measure-wide f6 f5-l lh-copy black-80">Dunbar suggests other group sizes too, in papers that follow his 1993 original…</p>
  137. <blockquote cite="https://www.technologyreview.com/2016/04/29/160438/your-brain-limits-you-to-just-five-bffs/" class="quoteback bl bw2 pl2 b--orange ml0 italic i" data-author="MIT Technology Review" data-title="Your Brain Limits You to Just Five BFFs (2016)">
  138. <p class="measure-wide f6 f5-l lh-copy black-80">Individuals, he says, generally have up to five people in the closest layer. The next closest layer contains an additional 10, the one beyond that an extra 35, and the final group another 100. So cumulatively, the layers contain five, 15, 50, and 150 people.</p>
  139. </blockquote>
  140. <p class="measure-wide f6 f5-l lh-copy black-80">And this result is new to me:</p>
  141. <p class="measure-wide f6 f5-l lh-copy black-80">Looking at <q>some six billion calls made by 35 million people</q> they did some number crunching and…</p>
  142. <blockquote class="bl bw2 pl2 b--orange ml0 italic i">
  143. <p class="measure-wide f6 f5-l lh-copy black-80">the average cumulative layer turns out to hold 4.1, 11.0, 29.8, and 128.9 users.</p>
  144. </blockquote>
  145. <p class="measure-wide f6 f5-l lh-copy black-80">Ta-da! Dunbar’s number proved, close enough.</p>
  146. <p class="measure-wide f6 f5-l lh-copy black-80">You can get the PDF on arXiv: <a href="https://arxiv.org/abs/1604.02400">Calling Dunbar’s Numbers (2016)</a>. I’ve included the full reference below.</p>
  147. <p class="measure-wide f6 f5-l lh-copy black-80">Kinda amazing to have evidence for something that feels so intuitive (the average number of best friends/family) and that lends confidence in the discovery in the data of Dunbar’s number itself too.</p>
  148. <hr class="h1 xh2-ns w1 xw2-ns ml4 mv4 bb bw1 b--white">
  149. <p class="measure-wide f6 f5-l lh-copy black-80">BTW I found that second paper via <a href="https://twitter.com/emollick">Ethan Mollick (@emollick) on Twitter</a> who <em>daily</em> shares and summarises fascinating papers and is 100% a must-follow.</p>
  150. <hr class="h1 xh2-ns w1 xw2-ns ml4 mv4 bb bw1 b--white">
  151. <p class="measure-wide f6 f5-l lh-copy black-80">Again, why this is relevant: if you’re designing systems for working in groups, whether that’s IRL workgroups and committees, or online chat groups, or software, the relevant numbers are 150 people who can be recognised over time, and approx 5 in a simultaneous conversation. That’s what it suggests to me anyway.</p>
  152. <p class="measure-wide f6 f5-l lh-copy black-80">The numbers are just averages, of course, and we’re each individuals and you shouldn’t put too much weight on evo psych or be deterministic about this stuff, but what we <em>can</em> do is use these as springboards to provoke new feature ideas. Such as…</p>
  153. <ul class="list ph0 ph0-ns bulleted-list">
  154. <li class="measure-wide f6 f5-l lh-copy black-80">could a Figma document suggest how to subdivide itself once more than five people are involved? Could my Twitter auto-segment into groups of 150?</li>
  155. <li class="measure-wide f6 f5-l lh-copy black-80">could we automatically adapt the interface of Zoom at the various Dunbar layers? Can we visually (and with interaction design) represent the structure of a 150 group <em>“welded together”</em> from smaller table-sized conversational groups, the two scales operating simultaneously?</li>
  156. <li class="measure-wide f6 f5-l lh-copy black-80">in pseudonymous groups where everyone is represented by avatars and obscure names, such as web3 communities on Discords, what is the right level of <em>detail</em> to help our ancient recognition systems to kick in, so we can get to Dunbar’s number and all the helpful formal and informal networks and subgroups that arise?</li>
  157. <li class="measure-wide f6 f5-l lh-copy black-80">when we’re building <a href="/home/2020/12/04/coops">software-enabled co-ops</a> or, in new language, creating governance and consensus systems for DAOs, could we optimise around Dunbar’s layers in order to avoid the inevitable bureaucratic requirements when we don’t – bureaucracy which is now perhaps revealed to be a social technology, a kind of relationships prosthetic for when self-organisation caps out.</li>
  158. </ul>
  159. <p class="measure-wide f6 f5-l lh-copy black-80">(Those last two points relevant now the global public timelines of 2010s social media are evaporating into the unindexable Discords and WhatsApp groups of 2020s <a href="/home/2021/01/07/dunbar_spaces">virtual private neighbourhoods</a>.)</p>
  160. <p class="measure-wide f6 f5-l lh-copy black-80">AND SO ON.</p>
  161. <hr class="h1 xh2-ns w1 xw2-ns ml4 mv4 bb bw1 b--white">
  162. <p class="measure-wide f6 f5-l lh-copy black-80"><em>References</em></p>
  163. <p class="measure-wide f6 f5-l lh-copy black-80">Dunbar, R.I.M., 1993. Coevolution of neocortical size, group size and language in humans. Behavioral and Brain Sciences 16, 681–694. <a href="https://doi.org/10.1017/S0140525X00032325">https://doi.org/10.1017/S0140525X00032325</a></p>
  164. <p class="measure-wide f6 f5-l lh-copy black-80">MacCarron, P., Kaski, K., Dunbar, R., 2016. Calling Dunbar’s Numbers. Social Networks 47, 151–155. <a href="https://doi.org/10.1016/j.socnet.2016.06.003">https://doi.org/10.1016/j.socnet.2016.06.003</a></p>
  165. </article>
  166. <hr>
  167. <footer>
  168. <p>
  169. <a href="/david/" title="Aller à l’accueil"><svg class="icon icon-home">
  170. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-home"></use>
  171. </svg> Accueil</a> •
  172. <a href="/david/log/" title="Accès au flux RSS"><svg class="icon icon-rss2">
  173. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-rss2"></use>
  174. </svg> Suivre</a> •
  175. <a href="http://larlet.com" title="Go to my English profile" data-instant><svg class="icon icon-user-tie">
  176. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-user-tie"></use>
  177. </svg> Pro</a> •
  178. <a href="mailto:david%40larlet.fr" title="Envoyer un courriel"><svg class="icon icon-mail">
  179. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-mail"></use>
  180. </svg> Email</a> •
  181. <abbr class="nowrap" title="Hébergeur : Alwaysdata, 62 rue Tiquetonne 75002 Paris, +33184162340"><svg class="icon icon-hammer2">
  182. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-hammer2"></use>
  183. </svg> Légal</abbr>
  184. </p>
  185. <template id="theme-selector">
  186. <form>
  187. <fieldset>
  188. <legend><svg class="icon icon-brightness-contrast">
  189. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-brightness-contrast"></use>
  190. </svg> Thème</legend>
  191. <label>
  192. <input type="radio" value="auto" name="chosen-color-scheme" checked> Auto
  193. </label>
  194. <label>
  195. <input type="radio" value="dark" name="chosen-color-scheme"> Foncé
  196. </label>
  197. <label>
  198. <input type="radio" value="light" name="chosen-color-scheme"> Clair
  199. </label>
  200. </fieldset>
  201. </form>
  202. </template>
  203. </footer>
  204. <script src="/static/david/js/instantpage-5.1.0.min.js" type="module"></script>
  205. <script>
  206. function loadThemeForm(templateName) {
  207. const themeSelectorTemplate = document.querySelector(templateName)
  208. const form = themeSelectorTemplate.content.firstElementChild
  209. themeSelectorTemplate.replaceWith(form)
  210. form.addEventListener('change', (e) => {
  211. const chosenColorScheme = e.target.value
  212. localStorage.setItem('theme', chosenColorScheme)
  213. toggleTheme(chosenColorScheme)
  214. })
  215. const selectedTheme = localStorage.getItem('theme')
  216. if (selectedTheme && selectedTheme !== 'undefined') {
  217. form.querySelector(`[value="${selectedTheme}"]`).checked = true
  218. }
  219. }
  220. const prefersColorSchemeDark = '(prefers-color-scheme: dark)'
  221. window.addEventListener('load', () => {
  222. let hasDarkRules = false
  223. for (const styleSheet of Array.from(document.styleSheets)) {
  224. let mediaRules = []
  225. for (const cssRule of styleSheet.cssRules) {
  226. if (cssRule.type !== CSSRule.MEDIA_RULE) {
  227. continue
  228. }
  229. // WARNING: Safari does not have/supports `conditionText`.
  230. if (cssRule.conditionText) {
  231. if (cssRule.conditionText !== prefersColorSchemeDark) {
  232. continue
  233. }
  234. } else {
  235. if (cssRule.cssText.startsWith(prefersColorSchemeDark)) {
  236. continue
  237. }
  238. }
  239. mediaRules = mediaRules.concat(Array.from(cssRule.cssRules))
  240. }
  241. // WARNING: do not try to insert a Rule to a styleSheet you are
  242. // currently iterating on, otherwise the browser will be stuck
  243. // in a infinite loop…
  244. for (const mediaRule of mediaRules) {
  245. styleSheet.insertRule(mediaRule.cssText)
  246. hasDarkRules = true
  247. }
  248. }
  249. if (hasDarkRules) {
  250. loadThemeForm('#theme-selector')
  251. }
  252. })
  253. </script>
  254. </body>
  255. </html>