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.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  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>Blaming Screen Readers 🚩×5 (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://adrianroselli.com/2021/10/blaming-screen-readers-red-flag.html">
  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>Blaming Screen Readers 🚩×5</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://adrianroselli.com/2021/10/blaming-screen-readers-red-flag.html" title="Lien vers le contenu original">Source originale</a>
  67. </p>
  68. </nav>
  69. <hr>
  70. <p>
  71. The title of this post is pretty specific. It relates to the meme on Twitter where users identify a trait or preference that they see as problematic, and identify it as a <em>red flag</em>. The emoji represents the red flag. For example:
  72. </p>
  73. <p><span id="RedFlag">
  74. <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 100.2 105.5" xml:space="preserve" focusable="false" aria-hidden="true">
  75. <title>A stylized red flag</title></p>
  76. <pre><code>&lt;g&gt;
  77. &lt;path class="wh" d="m93.3 105.3-1-.2c-.6-.3-1.1-.8-1.3-1.4L56.7 11.5c-.5-1.3.2-2.7 1.4-3.2l4.3-1.6.9-.2 1 .2c.7.3 1.2.8 1.4 1.4l34.2 92.1c.5 1.3-.2 2.7-1.4 3.2l-4.3 1.6-.9.3z"&gt;&lt;/path&gt;
  78. &lt;path class="wh" d="m39.3 53-.6-.1c-.8-.2-1.4-.8-1.7-1.5-4.3-10.9-8.3-21.9-12.2-32.6-.2-.5-.2-1.1 0-1.7 2.1-6.3 7.3-9.3 15.6-9.3 4 0 8.2.6 12.3 1.3l5.4.8c.9.1 1.7.7 2.1 1.6L73 46.4c.3.8.2 1.6-.3 2.3-.5.7-1.2 1.1-2 1.1h-2.1c-2.7 0-5.4-.1-8-.3l-7-.2c-6.2 0-10 .9-12.5 3.1-.6.4-1.2.6-1.8.6z"&gt;&lt;/path&gt;
  79. &lt;path class="wh" d="M46.9 57.9h-.5l-8.2-1.6c-.9-.2-1.7-.9-1.9-1.8-.2-.9.1-1.9.8-2.5l1.9-1.6a10 10 0 0 1 5.1-2.6h.5c1 0 1.9.6 2.3 1.5l2.3 5.3c.4.9.2 1.8-.3 2.6-.5.4-1.2.7-2 .7z"&gt;&lt;/path&gt;
  80. &lt;path class="wh" d="M22.6 67.1c-3.9 0-7.9-.5-11.8-1.4-.7-.2-1.3-.6-1.6-1.2-.3-.6-.4-1.4-.2-2l3.5-9.7 3-8.3C10.6 39 5.6 33.4.7 28.2c-.6-.7-.9-1.7-.5-2.6s1.1-1.5 2.1-1.6L27 21h.3c1 0 2 .7 2.4 1.7L34 34.3c2 5.3 4 10.7 5.9 16.3l1 2.2.2.8 7.6 1.7c1 .2 1.8 1 1.9 2.1.2 1-.3 2-1.2 2.5a55.9 55.9 0 0 1-26.8 7.2zm35.8-55.6a2 2 0 0 1-1.1-.3 6.1 6.1 0 0 1-2.9-3.4c-.6-1.5-.5-3.2.3-4.6A5.5 5.5 0 0 1 58 .7c.7-.2 1.3-.4 2-.4 2.4 0 4.4 1.4 5.3 3.5l.2.9c0 1.1 0 2.1-.5 3.4-.2.7-.8 1.3-1.5 1.5l-4.3 1.6c-.2.3-.5.3-.8.3z"&gt;&lt;/path&gt;
  81. &lt;path class="bl" d="m63.4 9 34.2 92.1-4.3 1.7-34.2-92.1z"&gt;&lt;/path&gt;
  82. &lt;path class="rd" d="M70.6 47.2c-12.2.3-24.3-2.6-31.2 3.3-4.3-10.9-8.2-21.7-12.2-32.6 3.9-11.5 19.4-6.9 30.6-5.6l12.8 34.9zm-31.9 6.6 2-1.6a8 8 0 0 1 3.9-2l2.3 5.3-8.2-1.7z"&gt;&lt;/path&gt;
  83. &lt;path class="rd" d="m37.4 51.5 1 2.3v.3l.7 1.6 8.9 2a50.2 50.2 0 0 1-36.5 5.6l6.9-19.4C13 38 7.8 32 2.5 26.5l24.7-3c3.3 9.2 6.9 18.4 10.2 28z"&gt;&lt;/path&gt;
  84. &lt;path class="bl" d="M63 4.7c0 1 0 1.6-.3 2.6L58.4 9a3 3 0 0 1-1.6-2c-.7-1.6.3-3.6 2-3.9 1.6-.7 3.6 0 4.2 1.6z"&gt;&lt;/path&gt;
  85. &lt;/g&gt;
  86. </code></pre>
  87. <p></svg>
  88. </span></p>
  89. <blockquote>
  90. <p>
  91. Blaming Screen Readers 🚩🚩🚩🚩🚩
  92. </p>
  93. </blockquote>
  94. <p>
  95. And here we see the usual pattern repeat itself. An inaccessible meme goes viral. After it is so tired that brands use it, someone relying on assistive technology points out how annoying this can be. Authors and developers jump up to blame assistive technology for being terrible at internetting.
  96. </p>
  97. <p>
  98. In the last few days I have seen more than a few people on Twitter blame screen readers for not being evergreen like browsers, for not understanding the context, for not returning just a count of emoji, and so on. I have even seen people post code snippets on how they could <em>fix</em> screen readers.
  99. </p>
  100. <h2 id="Not">Screen Readers Are Not…</h2>
  101. <p>
  102. …to blame for your inaccessible content.
  103. </p>
  104. <h3 id="API">Screen Readers Are Not Browsers</h3>
  105. <p>
  106. To address one false assumption, screen readers do not read pages. Not exactly. Screen readers announce what information the web browser hands them. Screen readers will add instructions for operating things, but even that is based on how the browser reports it. In the context of the web, barring heuristics and bugs, the browser is in charge.
  107. </p>
  108. <p>
  109. This means that all those bits of content, navigation, the states of controls, the count of how many items are in a list, cues for form field errors, and so on, are themselves built on what the developers write. The HTML.
  110. </p>
  111. <p>
  112. I am leaving out <a href="https://alistapart.com/article/semantics-to-screen-readers/">a bunch of technical detail</a> about accessibility APIs, the DOM, the virtual DOM, heuristics, and so on. I just want to impress upon you that browsers are what screen readers announce.
  113. </p>
  114. <h3 id="NLP">Screen Readers Do Not Use Natural Language Processing</h3>
  115. <p>
  116. Another false assumption is that screen readers understand the human content they are reading. They do not. Mostly. Screen reader heuristics will look at some strings of characters and announce them differently than what you may see (1<sup>st</sup> as <q>first</q>). But even that varies across screen readers <em>and</em> browsers.
  117. </p>
  118. <p>
  119. I have a long history trying to <a href="https://stackoverflow.com/questions/43491644/how-can-i-override-a-screen-readers-pronunciation-of-a-word-in-a-sentence-witho/43496525#43496525">stop developers from overriding how screen readers announce things</a> when it is not what they expect.
  120. </p>
  121. <p>
  122. A screen reader does not know the context of what you wrote, the implications of what it contains, or even what you wanted to convey. It just reads words aloud the best it can, adding inflection based on punctuation and maybe some other cues.
  123. </p>
  124. <h3 id="See">Screen Readers Do Not See What You See</h3>
  125. <p>
  126. But here is a curve ball — the red flag emoji <a href="https://twitter.com/ChanceyFleet/status/1448798849519210497">isn’t a red flag</a>. It is a <q>triangular flag on post</q>.
  127. </p>
  128. <blockquote>
  129. <p>
  130. Blaming Screen Readers triangular flag on post triangular flag on post triangular flag on post triangular flag on post triangular flag on post
  131. </p>
  132. </blockquote>
  133. <p>
  134. That is not the fault of screen readers. That is the risk of using emoji to convey meanings that are not part of the Unicode standard for the character. It is a fluke that they appear red. Platforms could make them yellow, or green, or striped, and so on.
  135. </p>
  136. <p>
  137. The author intent is completely dependent on the arbitrary color in the emoji. Without it, the meaning you wanted to convey is completely lost.
  138. </p>
  139. <h3 id="Cycle">Screen Readers Do Not Update Overnight</h3>
  140. <p>
  141. Screen readers are software with release cycles. They add features, fix bugs, and have to contend with browsers that change every six weeks, all at whatever pace they can muster.
  142. </p>
  143. <p>
  144. Some are tied into the operating system, like VoiceOver, and historically only update with the operating system. Just because Apple is a trillion dollar company does not mean it will move any faster <a href="/2020/03/i-dont-care-what-google-or-apple-or-whomever-did.html">or even get it right</a>. NVDA may be able to pivot more quickly, but it is open source and its release cycle reflects its revenue stream. <a href="https://github.com/FreedomScientific/VFO-standards-support/issues">JAWS has a public bug tracker</a>, and you can see it has a lot sitting out there, more important than memes.
  145. </p>
  146. <p>
  147. Never mind that the half-life of a typical meme is measured in days. Some are done and gone before the screen reader engineers have been able to get their VMs fired up to do regression testing.
  148. </p>
  149. <h3 id="Free">Screen Readers Are Not Free</h3>
  150. <p>
  151. As in beer. There is a cost to being able to run a screen reader, particularly the latest release.
  152. </p>
  153. <p>
  154. The <a href="https://www.forbes.com/sites/denisebrodey/2019/10/26/why-underemployment-plagues-people-with-disabilities-even-in-a-strong-economy/">disabled community is historically under-employed</a>. This means older hardware, older software, less frequent access to tech support, to updates, and so on. The latest screen reader may require the latest browser. It may require the latest hardware (when built into the operating system). It may require more time and effort to even update than its users reasonably have.
  155. </p>
  156. <p>
  157. Let’s not forget the opportunity cost. First think about everyone in your family who is not comfortable with technology. Now apply that same ratio to the disabled community. Now consider that if something goes wrong in their upgrade, that the tool that may be their lifeline is suddenly broken, and they cannot fix it. Now imagine the existential risk involved in upgrading to read a meme.
  158. </p>
  159. <h3 id="Stagnant">Screen Readers Are Not Stagnant</h3>
  160. <p>
  161. We have seen screen readers update to account for memes already. TalkBack used to ignore all the <a href="https://twitter.com/aardrian/status/1136647423328227328">special characters used to mimic bold and italic text in tweets</a>. Now it treats them as if they were regular ASCII letters.
  162. </p>
  163. <p>
  164. The trade-off is that for users who had a genuine purpose to use those characters, whether for math or science, those characters are now lost to them.
  165. </p>
  166. <p>
  167. I have also been told (sadly, it is anecdata and I have no specific example to show) that VoiceOver will ignore runs of emoji altogether. Which could be a problem if those emoji have meaning to convey, especially if the sender and receiver previously relied on them being announced.
  168. </p>
  169. <h2 id="Handle">How Should a Screen Reader Handle…</h2>
  170. <p>
  171. …the red flag meme? Some people suggested round them all up and give a count.
  172. </p>
  173. <p>
  174. Although, Twitter could step in here too. We already know <a href="/2018/01/improving-your-tweet-accessibility.html#:~:text=three%20different%20ways%20you%20can%20experience%20a%20single%20tweet">Twitter does some emoji processing on the fly</a>, and it has a dedicated accessibility team. As the venue for the meme, it is in the best place to consider how (or if) it should concatenate those repetitive emoji.
  175. </p>
  176. <p>
  177. How do you propose it handle some of the other memes that have been popular? That rely on spacing and position? That mix words and letters with symbols and emoji?
  178. </p>
  179. <h3 id="Box">That Text Intersecting Year Thing</h3>
  180. <figure>
  181. <video preload="metadata" controls="" poster="/wp-content/uploads/2018/01/2020-meme_VO-Safari-macOS_poster.png">
  182. <source src="/wp-content/uploads/2018/01/2020-meme_VO-Safari-macOS.mp4" type="video/mp4">
  183. <track label="English" kind="subtitles" srclang="en-us" src="/wp-content/uploads/2018/01/2020-meme_VO-Safari-macOS.vtt" default="">
  184. Sorry, your browser doesn’t support embedded videos, but don’t worry, you can <a href="/wp-content/uploads/2018/01/2020-meme_VO-Safari-macOS.mp4">download it</a>. The <a href="/wp-content/uploads/2018/01/2020-meme_VO-Safari-macOS.vtt">caption file</a> is also available in case your video player can import it.
  185. </track></source></video>
  186. <figcaption>As captured in VoiceOver for macOS using Safari. I wrote the captions instead of relying on the speech viewer.</figcaption>
  187. </figure>
  188. <h3 id="Clapping">Clapping Hands</h3>
  189. <figure>
  190. <video preload="metadata" controls="" poster="/wp-content/uploads/2018/01/twitter-mobile-emoji-three-ways_poster.jpg">
  191. <source src="/wp-content/uploads/2018/01/twitter-mobile-emoji-three-ways.mp4" type="video/mp4">
  192. <track label="English" kind="subtitles" srclang="en-us" src="/wp-content/uploads/2018/01/twitter-mobile-emoji-three-ways.vtt" default="">
  193. Sorry, your browser doesn’t support embedded videos, but don’t worry, you can <a href="/wp-content/uploads/2018/01/twitter-mobile-emoji-three-ways.mp4">download it</a>. The <a href="/wp-content/uploads/2018/01/twitter-mobile-emoji-three-ways.vtt">caption file</a> is also available in case your video player can import it.
  194. </track></source></video>
  195. <figcaption>TalkBack 9.1 on Android 11 with Chrome 91. First using <em>Read from next item</em> (which announces every image but does not announce its emoji alt text), then reading the entire tweet as a block, and then reading the tweet as a block after <a href="https://twitter.com/aardrian/status/1424875391970390023">Twitter’s script has updated it with the plain language alternative text</a> on the emoji images.</figcaption>
  196. </figure>
  197. <h3 id="Sheriff">Sheriff</h3>
  198. <figure>
  199. <video preload="metadata" controls="" poster="/wp-content/uploads/2021/10/tweet_meme_sheriff.jpg">
  200. <source src="/wp-content/uploads/2021/10/tweet_meme_sheriff.mp4" type="video/mp4">
  201. <track label="English" kind="subtitles" srclang="en-us" src="/wp-content/uploads/2021/10/tweet_meme_sheriff.vtt" default="">
  202. Sorry, your browser doesn’t support embedded videos, but don’t worry, you can <a href="/wp-content/uploads/2021/10/tweet_meme_sheriff.mp4">download it</a>. The <a href="/wp-content/uploads/2021/10/tweet_meme_sheriff.vtt">caption file</a> is also available in case your video player can import it.
  203. </track></source></video>
  204. <figcaption>Captured in Firefox 93 with NVDA 2021.2. Announced just from putting focus on the page. Had I done a read-all command, each emoji would have been announced as clickable. <a href="ttps://twitter.com/ellkay_/status/884103936935948290">Try it yourself</a>.</figcaption>
  205. </figure>
  206. <h3 id="Bunny">Sign Bunny</h3>
  207. <figure>
  208. <video preload="metadata" controls="" poster="/wp-content/uploads/2021/10/tweet_meme_sign-bunny.jpg">
  209. <source src="/wp-content/uploads/2021/10/tweet_meme_sign-bunny.mp4" type="video/mp4">
  210. <track label="English" kind="subtitles" srclang="en-us" src="/wp-content/uploads/2021/10/tweet_meme_sign-bunny.vtt" default="">
  211. Sorry, your browser doesn’t support embedded videos, but don’t worry, you can <a href="/wp-content/uploads/2021/10/tweet_meme_sign-bunny.mp4">download it</a>. The <a href="/wp-content/uploads/2021/10/tweet_meme_sign-bunny.vtt">caption file</a> is also available in case your video player can import it.
  212. </track></source></video>
  213. <figcaption>Captured in Chrome 94 with JAWS 2021. Notice how it fails to announce the majority of characters. You can <a href="https://twitter.com/AcademicsSay/status/1017926074150187010">test it</a> in your favorite combination.</figcaption>
  214. </figure>
  215. <h3 id="Jump">Building Jump</h3>
  216. <figure>
  217. <video preload="metadata" controls="" poster="/wp-content/uploads/2021/10/tweet_meme_building-jump.jpg">
  218. <source src="/wp-content/uploads/2021/10/tweet_meme_building-jump.mp4" type="video/mp4">
  219. <track label="English" kind="subtitles" srclang="en-us" src="/wp-content/uploads/2021/10/tweet_meme_building-jump.vtt" default="">
  220. Sorry, your browser doesn’t support embedded videos, but don’t worry, you can <a href="/wp-content/uploads/2021/10/tweet_meme_building-jump.mp4">download it</a>. The <a href="/wp-content/uploads/2021/10/tweet_meme_building-jump.vtt">caption file</a> is also available in case your video player can import it.
  221. </track></source></video>
  222. <figcaption>Captured in Edge 94 with Narrator (Windows 10). The only part of <a href="https://twitter.com/hamsandcastle/status/464478899217649664">this meme</a> it announced was the word and preceding slash.</figcaption>
  223. </figure>
  224. <h3 id="Peek">Peeking</h3>
  225. <figure>
  226. <video preload="metadata" controls="" poster="/wp-content/uploads/2021/10/tweet_meme_peeking.jpg">
  227. <source src="/wp-content/uploads/2021/10/tweet_meme_peeking.mp4" type="video/mp4">
  228. <track label="English" kind="subtitles" srclang="en-us" src="/wp-content/uploads/2021/10/tweet_meme_peeking.vtt" default="">
  229. Sorry, your browser doesn’t support embedded videos, but don’t worry, you can <a href="/wp-content/uploads/2021/10/tweet_meme_peeking.mp4">download it</a>. The <a href="/wp-content/uploads/2021/10/tweet_meme_peeking.vtt">caption file</a> is also available in case your video player can import it.
  230. </track></source></video>
  231. <figcaption>As heard using VoiceOver on iOS 14.8 with Safari 14. I did not investigate why it switches languages on the second read (starting at 1:25), but you can try it with the <a href="https://twitter.com/edburmila/status/1024712919316148224">original tweet</a> and see what you get.</figcaption>
  232. </figure>
  233. <h2 id="Wrap">Wrap-up</h2>
  234. <p>
  235. The better, more immediate, solution is to be more thoughtful in how you post your content (memes). Be considerate of others, even if it takes an extra minute. Stop offloading blame. Stop making it someone else’s problem.
  236. </p>
  237. <p>
  238. Screen readers happen to be the focus of this post, but everything holds true for other disabilities and other assistive technologies. Videos without captions, blinking and flashing imagery, unnecessary animations, loud noises, terrible audio, CAPTCHAs, and so on.
  239. </p>
  240. <p>
  241. Techniques to make your content accessible abound. They are no more than a quick search away should you care to try. Once a user (a fellow human) has raised a problem, you would have to actively work to ignore it. Which might make you kind of a jerk.
  242. </p>
  243. <p>
  244. Also, while you are thinking of other people, wear a mask and get vaccinated.
  245. </p>
  246. </article>
  247. <hr>
  248. <footer>
  249. <p>
  250. <a href="/david/" title="Aller à l’accueil"><svg class="icon icon-home">
  251. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-home"></use>
  252. </svg> Accueil</a> •
  253. <a href="/david/log/" title="Accès au flux RSS"><svg class="icon icon-rss2">
  254. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-rss2"></use>
  255. </svg> Suivre</a> •
  256. <a href="http://larlet.com" title="Go to my English profile" data-instant><svg class="icon icon-user-tie">
  257. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-user-tie"></use>
  258. </svg> Pro</a> •
  259. <a href="mailto:david%40larlet.fr" title="Envoyer un courriel"><svg class="icon icon-mail">
  260. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-mail"></use>
  261. </svg> Email</a> •
  262. <abbr class="nowrap" title="Hébergeur : Alwaysdata, 62 rue Tiquetonne 75002 Paris, +33184162340"><svg class="icon icon-hammer2">
  263. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-hammer2"></use>
  264. </svg> Légal</abbr>
  265. </p>
  266. <template id="theme-selector">
  267. <form>
  268. <fieldset>
  269. <legend><svg class="icon icon-brightness-contrast">
  270. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-brightness-contrast"></use>
  271. </svg> Thème</legend>
  272. <label>
  273. <input type="radio" value="auto" name="chosen-color-scheme" checked> Auto
  274. </label>
  275. <label>
  276. <input type="radio" value="dark" name="chosen-color-scheme"> Foncé
  277. </label>
  278. <label>
  279. <input type="radio" value="light" name="chosen-color-scheme"> Clair
  280. </label>
  281. </fieldset>
  282. </form>
  283. </template>
  284. </footer>
  285. <script src="/static/david/js/instantpage-5.1.0.min.js" type="module"></script>
  286. <script>
  287. function loadThemeForm(templateName) {
  288. const themeSelectorTemplate = document.querySelector(templateName)
  289. const form = themeSelectorTemplate.content.firstElementChild
  290. themeSelectorTemplate.replaceWith(form)
  291. form.addEventListener('change', (e) => {
  292. const chosenColorScheme = e.target.value
  293. localStorage.setItem('theme', chosenColorScheme)
  294. toggleTheme(chosenColorScheme)
  295. })
  296. const selectedTheme = localStorage.getItem('theme')
  297. if (selectedTheme && selectedTheme !== 'undefined') {
  298. form.querySelector(`[value="${selectedTheme}"]`).checked = true
  299. }
  300. }
  301. const prefersColorSchemeDark = '(prefers-color-scheme: dark)'
  302. window.addEventListener('load', () => {
  303. let hasDarkRules = false
  304. for (const styleSheet of Array.from(document.styleSheets)) {
  305. let mediaRules = []
  306. for (const cssRule of styleSheet.cssRules) {
  307. if (cssRule.type !== CSSRule.MEDIA_RULE) {
  308. continue
  309. }
  310. // WARNING: Safari does not have/supports `conditionText`.
  311. if (cssRule.conditionText) {
  312. if (cssRule.conditionText !== prefersColorSchemeDark) {
  313. continue
  314. }
  315. } else {
  316. if (cssRule.cssText.startsWith(prefersColorSchemeDark)) {
  317. continue
  318. }
  319. }
  320. mediaRules = mediaRules.concat(Array.from(cssRule.cssRules))
  321. }
  322. // WARNING: do not try to insert a Rule to a styleSheet you are
  323. // currently iterating on, otherwise the browser will be stuck
  324. // in a infinite loop…
  325. for (const mediaRule of mediaRules) {
  326. styleSheet.insertRule(mediaRule.cssText)
  327. hasDarkRules = true
  328. }
  329. }
  330. if (hasDarkRules) {
  331. loadThemeForm('#theme-selector')
  332. }
  333. })
  334. </script>
  335. </body>
  336. </html>