Leilukin's HubLeilukin's personal website.2024-11-21T17:09:28Zhttps://leilukin.com/Leilukincontact@leilukin.comChangelog: 21 November 20242024-11-20T16:55:40Zhttps://leilukin.com/<ul>
<li>Officially launch my <a href="https://leilukin.com/shrines/pokemonoras"><cite>Pokémon Omega Ruby</cite> and <cite>Alpha Sapphire</cite> shrine</a> to celebrate the 10th anniversary of the games' release.</li>
</ul>
Changelog: 19 November 20242024-11-19T14:19:00Zhttps://leilukin.com/<ul>
<li>Expand the home page of my <a href="https://leilukin.com/shrines/cassettebeasts"><cite>Cassette Beasts</cite> shrine</a> by adding a <a href="https://leilukin.com/shrines/cassettebeasts/#cassette-beasts-my-ultimate-comfort-media">"<cite>Cassette Beasts</cite> — My Ultimate Comfort Media"</a> section.</li>
</ul>
Changelog: 28 October 20242024-10-28T09:17:22Zhttps://leilukin.com/<ul>
<li>New blog post: <a href="https://leilukin.com/blog/posts/2024-10-28-re-social-media-personal-blog">"Re: Social Media Hasn't Killed the Personal Blog Just Yet"</a></li>
</ul>
Re: Social Media Hasn't Killed the Personal Blog Just Yet | Blog2024-10-28T09:16:14Zhttps://leilukin.com/blog/posts/2024-10-28-re-social-media-personal-blog/<p><a href="https://jimmitchell.org/">Jim Mitchell</a> wrote a blog post, <a href="https://jimmitchell.org/2024/09/21/social-media-hasnt.html">"Social Media Hasn't Killed the Personal Blog Just Yet"</a>, discussing the decline of personal blogs after social media took off, and the question of if social media killed personal blogs, and if personal blogging can make a comeback. This post caught me by surprise when I discovered it, because recently I have been reflecting on my blogging history, and how social media changed that, with my thoughts ended up being incredibly similar to Jim's.</p>
<p>Blogs have always had a special place in my heart and my history with the web, because blogging was my first foray into creating things and sharing things about myself on the web way back in the 2000s as a teenager. Teenage me was deeply fascinated by the concept of writing a personal journal on the web, and being able to connect with other people on the internet through reading and commenting on each other's online journal. I have loved writing and like to express myself through writing since I was a child, so blogging seemed to be a great way to do so.</p>
<p>Then social media began to take off. Jim Mitchell wrote:</p>
<blockquote>
<p>Personal blogs didn’t just disappear in one big poof. It was more like a slow fade. As Facebook, Instagram, and Twitter took off, people – me included – found it easier to share bite-sized pieces of life. Why write a long, reflective post to publish on your personal site when you could sum it up in a quick status update that some “friend” you don’t really even know could give you a mindless like?</p>
</blockquote>
<p>I can attest to that, because I was there when bloggers began to use social media, and how social media platforms gradually replaced their personal blogs as means share their thoughts and life updates. I was introduced to Facebook in the late 2000s by other Malaysian Chinese bloggers. As more of us bloggers use Facebook, updates of our personal blogs have gradually decreased.</p>
<p>Jim Mitchell's post talked about the shift to niche or professional blogging, which is a phenomenon I have noticed as well. I do not think blogs ever died, and in fact, even before discovering the personal web and coding my own website from scratch for the first time in 2022, I still found niche blogs to follow and subscribed to their RSS feeds, but social media and search engine optimisation (SEO) have made personal blogs obscure and more difficult to find than niche and professional blogs.</p>
<p>That said, exploring the web outside social media and seeing the resurgence of personal websites and blogs on platforms like <a href="https://neocities.org/">Neocities</a> and <a href="https://bearblog.dev/">Bear Blog</a>, gave me hope. I am happy to see people on the personal web are bringing back personal blogs too, which motivated me to include a blog to my website.</p>
<p>As Jim Mitchell concluded in his post:</p>
<blockquote>
<p>Is social media the death of the personal blog? Not quite. It may have nearly killed it, yes. But for those of us willing to carve out our own space in the digital landscape, personal blogs still have a heartbeat. It just takes more effort to keep it alive.</p>
</blockquote>
Changelog: 17 September 20242024-09-17T05:58:34Zhttps://leilukin.com/<ul>
<li>Add <a href="https://leilukin.com/adoptables/#Pantson-Color-Club">Pantson Color Club section</a> to my <a href="https://leilukin.com/adoptables">adoptables page</a>, including my own colour card for the pixel club.</li>
</ul>
Changelog: 6 September 20242024-09-06T15:16:00Zhttps://leilukin.com/<ul>
<li>Replace the estimated reading time of articles and blog posts with word count, by using the <a href="https://www.npmjs.com/package/eleventy-plugin-wordcount-extended">eleventy-plugin-wordcount-extended</a> plugin.</li>
<li>Create 200×40 pixel size version of Leilukin's Hub site button.</li>
</ul>
Changelog: 18 August 20242024-08-18T12:33:42Zhttps://leilukin.com/<ul>
<li>New blog post about me officially becoming a professional web developer, <a href="https://leilukin.com/blog/posts/2024-08-18-from-hobbyist-to-professional-web-developer">"From Hobbyist to Professional Web Developer"</a>.</li>
</ul>
From Hobbyist to Professional Web Developer | Blog2024-08-18T12:28:21Zhttps://leilukin.com/blog/posts/2024-08-18-from-hobbyist-to-professional-web-developer/<p>I am pleased to announce that I am officially a professional web developer now — starting from 16 August 2024, I am working for a local traditional Chinese medicine (TCM) healthcare company, with my job involving web development, UX design and graphic design. I owe much to this very website for inspiring me to pursue web development as a profession.</p>
<div class="heading-wrapper h2">
<h2 id="my-web-design-origin-story">My Web Design Origin Story</h2>
<a class="heading-anchor" href="https://leilukin.com/blog/posts/2024-08-18-from-hobbyist-to-professional-web-developer/#my-web-design-origin-story" aria-labelledby="my-web-design-origin-story"><span hidden="">#</span></a></div>
<p>My interest in web design and development go back as far as my teenage years in the 2000s. I had a GeoCities account, but by the time I started to participate on the web when I was around 14, blogs were on the rise, so blogging was my first foray into creating on the internet, so I did not experience creating and coding a personal website like other GeoCities users did. That said, I got my start on HTML and CSS through blogging, by editing the codes of widgets and blog themes, while being inspired by many other blogs.</p>
<p>In particular, there was a Taiwanese blogger who was a professional designer whose blog had a gorgeous header made with Flash, who ended up being an inspiration for me to aspire to become a graphic designer when I grew up. I did study graphic design, earn a diploma and began working as a graphic designer. However, years in the field, I got burned out; there were multiple factors contributing to my burnout from the graphic design field, but the short version is that the reality of graphic design work, at least in my experience, did not turn out as great as what my younger self had expected and hoped for.</p>
<div class="heading-wrapper h2">
<h2 id="rekindled-interest-in-web-design">Rekindled Interest in Web Design</h2>
<a class="heading-anchor" href="https://leilukin.com/blog/posts/2024-08-18-from-hobbyist-to-professional-web-developer/#rekindled-interest-in-web-design" aria-labelledby="rekindled-interest-in-web-design"><span hidden="">#</span></a></div>
<p>Fast forward to 2022, my interest in web design was rekindled when I discovered Neocities through Tumblr and the resurgence of creating personal websites, so I decided to build and code my own website to gather various stuff I have created and curated across various online spaces. For this, I re-learned HTML and CSS, and began to truly experience the joy of carving one's own space on the web, and the more I worked on my website, the more I learned about not only web design, but also web development, by dabbling in JavaScript.</p>
<p>Furthermore, despite being burned out from graphic design as a profession, my graphic design background does come in handy in building Leilukin's Hub, by designing and creating graphics for my website, including header image, site button, favicon, etc., as well as applying my design knowledge and skill to design my own website, from colour schemes to layout.</p>
<div class="heading-wrapper h2">
<h2 id="web-development-more-than-a-hobby">Web Development: More than a Hobby</h2>
<a class="heading-anchor" href="https://leilukin.com/blog/posts/2024-08-18-from-hobbyist-to-professional-web-developer/#web-development-more-than-a-hobby" aria-labelledby="web-development-more-than-a-hobby"><span hidden="">#</span></a></div>
<p>Over time, my interest in web development evolved enough to take online coding courses, starting with <a href="https://www.freecodecamp.org/">freeCodeCamp</a>, then <a href="https://scrimba.com/">Scrimba</a> shortly after. Taking these courses made me realise that these languages have evolved a lot since more than a decade ago. I applied the HTML, CSS and JavaScript skills and knowledge I learned from these courses to make improvements to my website.</p>
<p>Meanwhile, learning that there were people who became developers without a computer science degree inspired me to consider switching my career path to web development. In other words, web design and development have become more than a hobby to me. I did not expect it to be easy, so I did put as much as I could in learning and practising web development. That said, Leilukin's Hub remains a hobby project, and it serves as a good platform for me to practice and experiment my front end web development.</p>
<p>After teaching myself to code for almost two years, and received multiple code and tech-related certifications, I updated my résumé with information about my interest in switching career from graphic design to web development, and hope for transferring my creativity and design expertise into building the web. I started to try hunting for front end web developer jobs, but my attempts to apply for the job for many companies did not succeed, then I received a surprised belated birthday present in the form of a job interview invitation.</p>
<div class="heading-wrapper h2">
<h2 id="new-job-interview-a-surprise-belated-birthday-present">New Job Interview: A Surprise Belated Birthday Present</h2>
<a class="heading-anchor" href="https://leilukin.com/blog/posts/2024-08-18-from-hobbyist-to-professional-web-developer/#new-job-interview-a-surprise-belated-birthday-present" aria-labelledby="new-job-interview-a-surprise-belated-birthday-present"><span hidden="">#</span></a></div>
<p>On 29 July 2024, a day after my birthday, I received an invitation by the managing director of a local traditional Chinese medicine company to attend an interview with him. The company was looking for someone with web development expertise to work on and improve their website, which is built with WordPress, and the managing director discovered my résumé on a Malaysian job hunting website I had registered an account on.</p>
<p>During my interview, I explained to the managing director that I have been looking to switch career from graphic design to web development. Turned out, the company was also interested in hiring a web developer with design expertise to improve the front end of their website, so my 8 years worth of graphic design experience was a bonus. A week after the interview, the managing director sent me a job offer, and I accepted and got hired, with my responsibilities include web development, UX design and graphic design.</p>
<div class="heading-wrapper h2">
<h2 id="wordpress-developer-by-day-eleventy-developer-by-night">WordPress Developer by Day, Eleventy Developer by Night</h2>
<a class="heading-anchor" href="https://leilukin.com/blog/posts/2024-08-18-from-hobbyist-to-professional-web-developer/#wordpress-developer-by-day-eleventy-developer-by-night" aria-labelledby="wordpress-developer-by-day-eleventy-developer-by-night"><span hidden="">#</span></a></div>
<p>Starting my professional web development journey with WordPress is going to be a new experience for me. I had brief experience with working on WordPress websites as a website administrator in one of my previous jobs, but never as a developer. Furthermore, prior to receiving this job offer, I never studied WordPress development, nor built my own website with WordPress.</p>
<p>That said, I hope to apply the programming knowledge and skills I learned from the coding courses I had taken to adapt to learning WordPress development. My confidence in my ability to learn new tech skills was bolstered by the time I created a <a href="https://leilukin.com/projects/code/bellabuffs-phpmailer/">fork for the fanlisting script BellaBuffs with SMTP support</a> despite my inexperience with PHP. I am looking forward to learning more about PHP with my new job as well.</p>
<p>Although now I work on WordPress in my day job, my personal website will continue to be built with Eleventy. One of the reasons I wanted to pursue web development as a profession is the freedom to learn and use different tools outside day job while continuing to grow as a developer.</p>
<p>None of the coding courses I took taught about Eleventy or any static site generator, but <a href="https://leilukin.com/blog/posts/2024-04-21-april-2024-leilukins-hub-overhaul-with-eleventy/">rebuilding Leilukin's Hub with Eleventy in April 2024</a> allowed me to learn more about web development, not to mention I do have a lot of fun with using Eleventy. Therefore, I am content to be a WordPress developer by day, Eleventy developer by night.</p>
<div class="heading-wrapper h2">
<h2 id="wrapping-up">Wrapping Up</h2>
<a class="heading-anchor" href="https://leilukin.com/blog/posts/2024-08-18-from-hobbyist-to-professional-web-developer/#wrapping-up" aria-labelledby="wrapping-up"><span hidden="">#</span></a></div>
<p>Looking back, even I am amazed by the fact that building this very website kickstarted my path to become a professional web developer, especially since I did not come from a tech educational or industrial background, but I am glad that it happened.</p>
<p>I am happy to be able to switch my career path to web development despite not having a computer science degree, and that my prior working experience as a graphic designer helped with getting this new opportunity.</p>
Changelog: 11 August 20242024-08-11T14:46:00Zhttps://leilukin.com/<ul>
<li>Improve the site's <a href="https://leilukin.com/feed.xml">RSS feed</a>:
<ul>
<li>Make RSS feeds <a href="https://blog.jim-nielsen.com/2021/automatically-discoverable-rss-feeds/">automatically discoverable</a> by feed readers</li>
<li>Use time and time zone to make feed items' timestamps accurate</li>
</ul>
</li>
</ul>
Changelog: 6 August 20242024-08-06T13:20:00Zhttps://leilukin.com/<ul>
<li>New article: <a href="https://leilukin.com/articles/accessible-footnotes">"How I (Tried to) Implement Accessible Footnotes"</a>, which is also my entry for <a href="https://32bit.cafe/">32-Bit Cafe</a>'s <a href="https://32bit.cafe/~xandra/events/codejam5/">Community Code Jam #5: Back to School</a>.</li>
</ul>
How I (Tried to) Implement Accessible Footnotes | Articles2024-08-05T16:04:00Zhttps://leilukin.com/articles/accessible-footnotes/<p class="center-text"><a href="https://32bit.cafe/~xandra/events/codejam5/" class="inline-img"><img src="https://leilukin.com/assets/images/articles/accessible-footnotes/32bitcafe-backtoschool.png" alt="32-Bit Cafe "Back to School" Code Jam button" /></a></p>
<p class="center-text">(32-Bit Cafe "Back to School" button made by <a href="https://ribo.zone/">Loren</a>)</p>
<p><a href="https://32bit.cafe/">32-Bit Cafe</a> is holding its fifth community code jam, titled <a href="https://32bit.cafe/~xandra/events/codejam5/">"Back to School"</a>, from 4 to 17 August 2024. I have been looking forward to participating in 32-Bit Cafe's community code jam for the first time, so I am excited. This motivates me to finally write a how-to article I have been meaning to do for a while: how to implement accessible footnotes on Leilukin's Hub, or at least, I tried to do so to the best of my abilities.</p>
<p>On <a href="https://discourse.32bit.cafe/">32-Bit Cafe's Discourse forum</a>, I made a <a href="https://discourse.32bit.cafe/t/handling-citations-and-or-footnotes/1061/2?u=leilukin">post on 28 June 2024</a> in response to <a href="https://solaria.neocities.org/">solaria</a>'s thread <a href="https://discourse.32bit.cafe/t/handling-citations-and-or-footnotes/1061">"Handling Citations and/or Footnotes"</a> to share my methods of adding footnotes on my website. Now, I am writing an extended version of that post of mine in the form of this article, so I could share what I learned about web page footnotes on my website as well.</p>
<p>(Note: This article assumes a foundational familiarity with HTML and CSS)</p>
<div class="heading-wrapper h2">
<h2 id="about-footnotes">About Footnotes</h2>
<a class="heading-anchor" href="https://leilukin.com/articles/accessible-footnotes/#about-footnotes" aria-labelledby="about-footnotes"><span hidden="">#</span></a></div>
<p>Plagiarism.org <a href="https://www.plagiarism.org/article/what-are-footnotes">defines footnotes</a> as notes placed at the bottom of a page, and what footnotes do is to cite references or comment on a designated part of the text above it.</p>
<p>My use case of footnotes is citing sources of information, particularly citing the same source multiple times on the same page when information from the same source is spread across my page. As of this writing, my website pages that use footnotes include the <a href="https://leilukin.com/shrines/asummersend/trivia/">trivia page of my <cite>A Summer’s End — Hong Kong 1986</cite> shrine 1</a> and the <a href="https://leilukin.com/shrines/cassettebeasts/facts/">facts page of my <cite>Cassette Beasts</cite> shrine</a>. You are free to look at the HTML and CSS for reference, including when you are reading this article as I am explaining how I implement the footnotes.</p>
<p>Footnotes are used both on print and on the web. However, maintaining footnotes on the web can be tedious, especially if you want to update a web page to add or remove them, since you will need to change the number references of existing footnotes.</p>
<div class="heading-wrapper h2">
<h2 id="attempted-to-use-css-counters">Attempted to Use CSS Counters</h2>
<a class="heading-anchor" href="https://leilukin.com/articles/accessible-footnotes/#attempted-to-use-css-counters" aria-labelledby="attempted-to-use-css-counters"><span hidden="">#</span></a></div>
<p>When I was searching for how to implement accessible footnotes, I discovered <a href="https://kittygiraudel.com/">Kitty Giraudel</a>'s article, <a href="https://www.sitepoint.com/accessible-footnotes-css/">"Accessible Footnotes with CSS"</a> which teaches the method of using the combination of HTML <a href="https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-describedby"><code>aria-describedby</code></a> attribute and <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_counter_styles/Using_CSS_counters">CSS counters</a> to add numbered references, to reduce the hassle of manually re-numbering all existing footnotes in case you want to update or reorder the references.</p>
<p>Her article also teaches adding a highlight background colour when heading to a footnote from a reference, as well as providing back links to head back to a reference from a footnote, by using the combination of the backlink Unicode icon (↩) and the HTML <code>aria-label</code> attribute with a value of “Back to content”. The uses of ARIA labels make footnotes more screen reader-friendly.</p>
<p>Furthermore, Kitty created the <a href="https://github.com/KittyGiraudel/eleventy-plugin-footnotes">eleventy-plugin-footnotes plugin</a> for the static site generator <a href="https://www.11ty.dev/">Eleventy</a>, and wrote a blog post about it, <a href="https://kittygiraudel.com/2020/12/02/footnotes-in-11ty/">"Footnotes in 11ty"</a>. Since I already had begun to <a href="https://leilukin.com/blog/posts/2024-04-21-april-2024-leilukins-hub-overhaul-with-eleventy">use Eleventy to build my website</a>, I tried Kitty's plugin.</p>
<p>Unfortunately, a known limitation of using CSS counter method to generate footnotes is <a href="https://github.com/KittyGiraudel/eleventy-plugin-footnotes/issues/83">not being able to reference the same footnote multiple times</a>. As I want to be able to reference the same footnote more than once when I am citing sources on my shrine pages, I had to give up the plugin and look for an alternative.</p>
<div class="heading-wrapper h2">
<h2 id="starting-with-markdown-it-footnote-plugins-default-footnote-markup">Starting with markdown-it-footnote Plugin's Default Footnote Markup</h2>
<a class="heading-anchor" href="https://leilukin.com/articles/accessible-footnotes/#starting-with-markdown-it-footnote-plugins-default-footnote-markup" aria-labelledby="starting-with-markdown-it-footnote-plugins-default-footnote-markup"><span hidden="">#</span></a></div>
<p>Kitty Giraudel's blog post about creating footnotes in Eleventy mentioned <a href="https://github.com/markdown-it/markdown-it-footnote">markdown-it-footnote</a>, the footnotes plugin for <a href="https://github.com/markdown-it/markdown-it">markdown-it</a> Markdown parser, which is integrated in Eleventy by default to convert Markdown to HTML. Kitty commented on the accessibility shortcomings of markdown-it-footnote in the blog post:</p>
<blockquote>
<p>[...]it’s not super accessible (let alone by default), even considering all the customisation options. That’s because the footnote references end up being numbers (e.g. [1]) which are meaningless when listed or tabbed through because devoid of their surrounding context.</p>
</blockquote>
<p>That said, since the plugin is customisable, I still wanted to give it a shot to see if I could make configurations to improve its accessibility, so I installed markdown-it-footnote and looked into the plugin's default HTML markup output.</p>
<p>Here is a sample of what the HTML markup output of markdown-it-footnote looks like:</p>
<pre class="language-html" tabindex="0"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span>This is a paragraph with the first footnote reference. <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>sup</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>footnote-ref<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>#fn1<span class="token punctuation">"</span></span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>fnref1<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>[1]<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>a</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>sup</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span>Here is the second paragraph with the second footnote reference. <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>sup</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>footnote-ref<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>#fn2<span class="token punctuation">"</span></span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>fnref2<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>[2]<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>a</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>sup</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span>This the third paragraph, but with a foootnote reference that points to the first footnote. <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>sup</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>footnote-ref<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>#fn1<span class="token punctuation">"</span></span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>fnref1:1<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>[1:1]<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>a</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>sup</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>hr</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>footnotes-sep<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>section</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>footnotes<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>ol</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>footnotes-list<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>li</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>fn1<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>footnote-item<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>First footnote <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>#fnref1<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>footnote-backref<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>↩︎<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>a</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>#fnref1:1<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>footnote-backref<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>↩︎<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>a</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>li</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>li</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>fn2<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>footnote-item<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Second footnote <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>#fnref2<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>footnote-backref<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>↩︎<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>a</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>li</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>ol</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>section</span><span class="token punctuation">></span></span></code></pre>
<p>This is what this HTML markup will look like on a live web page:</p>
<p><img src="https://leilukin.com/assets/images/articles/accessible-footnotes/footnote-sample.avif" alt="Web page footnotes sample screenshot" /></p>
<p>What this HTML markup does:</p>
<ul>
<li>Adding a footnote reference as a superscript by using the <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/sup"><code><sup></code></a> tag with numbers as the content.</li>
<li>Using a <code><hr></code> horizontal line element to separate the main body of the page and the footnote section;</li>
<li>Using the <code><ol></code> tag to render the footnotes as a numbered list;</li>
<li>Each footnote list item has an <code>id</code> attribute</li>
<li>If a footnote is referenced more than once, the additional footnote references are labelled with colons.</li>
</ul>
<p>(Note: the class names were added by markdown-it-footnote, but if you do not use it, you can rename the class name to whatever you want, and even if you use markdown-it-footnote, you can still change the class names if you want to go deep into it)</p>
<p>Next step is trying to improve this HTML markup by making it accessible.</p>
<div class="heading-wrapper h2">
<h2 id="make-markdown-it-footnotes-markup-more-accessible">Make markdown-it-footnote's Markup More Accessible</h2>
<a class="heading-anchor" href="https://leilukin.com/articles/accessible-footnotes/#make-markdown-it-footnotes-markup-more-accessible" aria-labelledby="make-markdown-it-footnotes-markup-more-accessible"><span hidden="">#</span></a></div>
<div class="heading-wrapper h3">
<h3 id="clarify-footnote-reference-labels">Clarify Footnote Reference Labels</h3>
<a class="heading-anchor" href="https://leilukin.com/articles/accessible-footnotes/#clarify-footnote-reference-labels" aria-labelledby="clarify-footnote-reference-labels"><span hidden="">#</span></a></div>
<p>As pointed out by Kitty Giraudel, labelling the footnote reference as mere numbers like [1] is an accessibility shortcoming, because these reference links become meaningless when being focused on by tabbing through the links, as these reference links would be devoid of context.</p>
<p>What I did to tackle this was changing the reference labels by adding a word "Footnote" to clarify that these links are for footnotes. For example, [1] becomes [Footnote #1], so when screen readers focus on a footnote reference link, it will be read out as "Footnote number one link".</p>
<pre class="language-html" tabindex="0"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>sup</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>footnote-ref<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>#fn1<span class="token punctuation">"</span></span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>fnref1<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>[1]<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>a</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>sup</span><span class="token punctuation">></span></span></code></pre>
<p>Optionally, if you want your footnote labels to still display only numbers on screen, you can use a CSS class to <a href="https://www.a11yproject.com/posts/how-to-hide-content/">visually hide</a> the extra characters in the footnote label. This <code>.visually-hidden</code> utility class is a useful tool in your arsenal for accessible web design, as it is often used to hide a content that you do not mean to show on screen, but you still want it to be read by assistive technology.</p>
<pre class="language-css" tabindex="0"><code class="language-css"><span class="token selector">.visually-hidden</span> <span class="token punctuation">{</span>
<span class="token property">clip</span><span class="token punctuation">:</span> <span class="token function">rect</span><span class="token punctuation">(</span>0 0 0 0<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token property">clip-path</span><span class="token punctuation">:</span> <span class="token function">inset</span><span class="token punctuation">(</span>50%<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token property">height</span><span class="token punctuation">:</span> 1px<span class="token punctuation">;</span>
<span class="token property">overflow</span><span class="token punctuation">:</span> hidden<span class="token punctuation">;</span>
<span class="token property">position</span><span class="token punctuation">:</span> absolute<span class="token punctuation">;</span>
<span class="token property">white-space</span><span class="token punctuation">:</span> nowrap<span class="token punctuation">;</span>
<span class="token property">width</span><span class="token punctuation">:</span> 1px<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>To make my footnote reference labels display only a number on screen, I use a <code>span</code> tag with <code>visually-hidden</code> as the value of the <code>class</code> attribute to wrap around "Footnote #", so on screen, [Footnote #1] is changed to [1].</p>
<pre class="language-html" tabindex="0"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>sup</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>footnote-ref<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>#fn1<span class="token punctuation">"</span></span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>fnref1<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
[<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>visually-hidden<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Footnote #<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>span</span><span class="token punctuation">></span></span>1]
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>a</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>sup</span><span class="token punctuation">></span></span></code></pre>
<div class="heading-wrapper h3">
<h3 id="add-aria-label-to-footnote-back-links">Add ARIA Label to Footnote Back Links</h3>
<a class="heading-anchor" href="https://leilukin.com/articles/accessible-footnotes/#add-aria-label-to-footnote-back-links" aria-labelledby="add-aria-label-to-footnote-back-links"><span hidden="">#</span></a></div>
<p>Next step is adding an ARIA label to the footnote backlinks, by adding an <code>aria-label</code> attribute with "Back to reference #[Insert reference number]" as its value. For example:</p>
<pre class="language-html" tabindex="0"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>a</span> <span class="token attr-name">aria-label</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Back to reference #1<span class="token punctuation">"</span></span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>#fnref1<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>footnote-backref<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>↩︎<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>a</span><span class="token punctuation">></span></span></code></pre>
<p>When a footnote back link is focused on via tabbing, screen readers will read it out as "Back to reference number one link".</p>
<div class="heading-wrapper h3">
<h3 id="add-heading-to-footnote-section">Add Heading to Footnote Section</h3>
<a class="heading-anchor" href="https://leilukin.com/articles/accessible-footnotes/#add-heading-to-footnote-section" aria-labelledby="add-heading-to-footnote-section"><span hidden="">#</span></a></div>
<p>To make it clear that the section is for footnotes, I add a HTML heading before the list of footnotes, such as:</p>
<pre class="language-html" tabindex="0"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>h2</span><span class="token punctuation">></span></span>Footnotes<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>h2</span><span class="token punctuation">></span></span></code></pre>
<div class="heading-wrapper h2">
<h2 id="final-html-markup-for-accessible-footnotes">Final HTML Markup for Accessible Footnotes</h2>
<a class="heading-anchor" href="https://leilukin.com/articles/accessible-footnotes/#final-html-markup-for-accessible-footnotes" aria-labelledby="final-html-markup-for-accessible-footnotes"><span hidden="">#</span></a></div>
<p>Here is my final HTML markup sample to create accessible footnotes:</p>
<pre class="language-html" tabindex="0"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span>This is a paragraph with the first footnote reference. <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>sup</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>footnote-ref<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>#fn1<span class="token punctuation">"</span></span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>fnref1<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>[<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>visually-hidden<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Footnote #<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>span</span><span class="token punctuation">></span></span>1]<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>a</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>sup</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span>Here is the second paragraph with the second footnote reference. <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>sup</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>footnote-ref<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>#fn2<span class="token punctuation">"</span></span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>fnref2<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>[<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>visually-hidden<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Footnote #<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>span</span><span class="token punctuation">></span></span>2]<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>a</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>sup</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span>This the third paragraph, but with a foootnote reference that points to the first footnote. <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>sup</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>footnote-ref<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>#fn1<span class="token punctuation">"</span></span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>fnref1:1<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>[<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>visually-hidden<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Footnote #<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>span</span><span class="token punctuation">></span></span>1:1]<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>a</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>sup</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>hr</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>footnotes-sep<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>section</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>footnotes<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>h2</span><span class="token punctuation">></span></span>Footnotes<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>h2</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>ol</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>footnotes-list<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>li</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>fn1<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>footnote-item<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
First footnote
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>a</span> <span class="token attr-name">aria-label</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Back to reference #1<span class="token punctuation">"</span></span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>#fnref1<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>footnote-backref<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>↩︎<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>a</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>a</span> <span class="token attr-name">aria-label</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Back to reference #1:1<span class="token punctuation">"</span></span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>#fnref1:1<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>footnote-backref<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>↩︎<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>a</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>li</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>li</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>fn2<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>footnote-item<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
Second footnote
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>a</span> <span class="token attr-name">aria-label</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Back to reference #2<span class="token punctuation">"</span></span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>#fnref2<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>footnote-backref<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>↩︎<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>a</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>li</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>ol</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>section</span><span class="token punctuation">></span></span></code></pre>
<p>As for the CSS, in addition to using the <code>.visually-hidden</code> utility class, I refer to Kitty Giraudel's <a href="https://www.sitepoint.com/accessible-footnotes-css/">"Accessible Footnotes with CSS"</a> article to style the highlight background color when heading to a footnote from a reference.</p>
<div class="heading-wrapper h2">
<h2 id="configure-markdown-it-footnote-in-eleventys-configuration-file">Configure markdown-it-footnote in Eleventy's Configuration File</h2>
<a class="heading-anchor" href="https://leilukin.com/articles/accessible-footnotes/#configure-markdown-it-footnote-in-eleventys-configuration-file" aria-labelledby="configure-markdown-it-footnote-in-eleventys-configuration-file"><span hidden="">#</span></a></div>
<p>(If you do not use Eleventy, you may skip this section)</p>
<p>My final step was to configure the markdown-it-footnote plugin, by editing Eleventy's configuration file (I named mine <code>eleventy.config.js</code>), so the plugin would render my accessible footnote HTML markup.</p>
<pre class="language-js" tabindex="0"><code class="language-js"><span class="token comment">// markdown-it plugins</span>
<span class="token keyword">const</span> markdownIt <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"markdown-it"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> markdownItFootnote <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"markdown-it-footnote"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> markdownLibrary<span class="token punctuation">;</span>
module<span class="token punctuation">.</span><span class="token function-variable function">exports</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">eleventyConfig</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">/* Markdown Overrides */</span>
markdownLibrary <span class="token operator">=</span> <span class="token function">markdownIt</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
<span class="token literal-property property">html</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>markdownItFootnote<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// Configure markdown-it-footnote</span>
markdownLibrary<span class="token punctuation">.</span>renderer<span class="token punctuation">.</span>rules<span class="token punctuation">.</span><span class="token function-variable function">footnote_block_open</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">(</span>
<span class="token string">'<hr class="footnotes-sep">\n'</span> <span class="token operator">+</span>
<span class="token string">'<section class="footnotes">\n'</span> <span class="token operator">+</span>
<span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string"><h2>Footnotes</h2>\n</span><span class="token template-punctuation string">`</span></span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
markdownLibrary<span class="token punctuation">.</span>renderer<span class="token punctuation">.</span>rules<span class="token punctuation">.</span><span class="token function-variable function">footnote_anchor</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">tokens<span class="token punctuation">,</span> idx<span class="token punctuation">,</span> options<span class="token punctuation">,</span> env<span class="token punctuation">,</span> slf</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">let</span> id <span class="token operator">=</span> slf<span class="token punctuation">.</span>rules<span class="token punctuation">.</span><span class="token function">footnote_anchor_name</span><span class="token punctuation">(</span>tokens<span class="token punctuation">,</span> idx<span class="token punctuation">,</span> options<span class="token punctuation">,</span> env<span class="token punctuation">,</span> slf<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>tokens<span class="token punctuation">[</span>idx<span class="token punctuation">]</span><span class="token punctuation">.</span>meta<span class="token punctuation">.</span>subId <span class="token operator">></span> <span class="token number">0</span><span class="token punctuation">)</span> id <span class="token operator">+=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">:</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>tokens<span class="token punctuation">[</span>idx<span class="token punctuation">]</span><span class="token punctuation">.</span>meta<span class="token punctuation">.</span>subId<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
<span class="token comment">/* ↩ with escape code to prevent display as Apple Emoji on iOS */</span>
<span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string"> <a aria-label="Back to reference #</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>id<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">" href="#fnref</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>id<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">" class="footnote-backref">\u21a9\uFE0E</a></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> renderRules <span class="token operator">=</span> <span class="token punctuation">{</span>
<span class="token literal-property property">footnote_caption</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'['</span><span class="token punctuation">,</span> <span class="token string">'[<span class="visually-hidden">Footnote #</span>'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
Object<span class="token punctuation">.</span><span class="token function">keys</span><span class="token punctuation">(</span>renderRules<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token parameter">rule</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">let</span> defaultRender <span class="token operator">=</span> markdownLibrary<span class="token punctuation">.</span>renderer<span class="token punctuation">.</span>rules<span class="token punctuation">[</span>rule<span class="token punctuation">]</span><span class="token punctuation">;</span>
markdownLibrary<span class="token punctuation">.</span>renderer<span class="token punctuation">.</span>rules<span class="token punctuation">[</span>rule<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">tokens<span class="token punctuation">,</span> idx<span class="token punctuation">,</span> options<span class="token punctuation">,</span> env<span class="token punctuation">,</span> self</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token function">defaultRender</span><span class="token punctuation">(</span>tokens<span class="token punctuation">,</span> idx<span class="token punctuation">,</span> options<span class="token punctuation">,</span> env<span class="token punctuation">,</span> self<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token operator">...</span>renderRules<span class="token punctuation">[</span>rule<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">/* This is the part that tells 11ty to swap to our custom config */</span>
eleventyConfig<span class="token punctuation">.</span><span class="token function">setLibrary</span><span class="token punctuation">(</span><span class="token string">"md"</span><span class="token punctuation">,</span> markdownLibrary<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>If you are a fellow Eleventy user, feel free to borrow my markdown-it-footnote configurations in your own. Make sure you install markdown-it-footnote first by keying in the installation command in the terminal:</p>
<pre class="language-powershell" tabindex="0"><code class="language-powershell">npm install markdown-it-footnote <span class="token operator">--</span>save</code></pre>
<div class="heading-wrapper h2">
<h2 id="bonus-alternatives-to-footnotes">Bonus: Alternatives to Footnotes</h2>
<a class="heading-anchor" href="https://leilukin.com/articles/accessible-footnotes/#bonus-alternatives-to-footnotes" aria-labelledby="bonus-alternatives-to-footnotes"><span hidden="">#</span></a></div>
<p>As you likely have realised, footnotes are really tricky to implement on web pages, so you may be wondering: is there any alternative to footnotes?</p>
<p>For extra comments and tangents, by favourite approach is using HTML's details disclosure element with the <code><details></code> tag, with a <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/summary"><code><summary></code></a> element and a sibling element wrapping the content displayed when the disclosure is expanded.</p>
<p>I have been using the disclosure element for additional comments or information on this website, like in my blog post, <a href="https://leilukin.com/blog/posts/2024-06-24-cassette-beasts-fanlisting-approved/">"My Cassette Beasts Fanlisting Application has been Approved"</a>. As for the styling, initially I indented the content inside the disclosure to differentiate the disclosure content from the rest of the content of the page, but recently I switched to adding top and bottom borders after being inspired by <a href="https://starbreaker.org/">Starbreaker</a>'s website, who also has a post about footnotes, <a href="https://starbreaker.org/blog/tech/footnotes-no-fun-to-create-either/index.html">"Footnotes: No Fun to Create, Either"</a>.</p>
<details class="content-disclosure">
<summary class="content-disclosure__summary">More ways to use <code><details></code> and <code><summary></code> elements</summary>
<div class="content-disclosure__content"><p><code><details></code> and <code><summary></code> have become among my favourite HTML elements due to how useful they are. In addition to extra comments and info, Leilukin's Hub has also used the elements for the following purposes:</p>
<ul>
<li>Table of contents, like the one this very article has</li>
<li>Hiding spoilers, like in my <cite>Cassette Beasts</cite> shrine article, <a href="https://leilukin.com/shrines/cassettebeasts/articles/cassette-beasts-more-than-a-pokemon-clone/">"How Cassette Beasts is Much More than a Pokémon Clone"</a></li>
<li>Content warnings, like in my <a href="https://leilukin.com/shrines/asummersend/gallery/"><cite>A Summer’s End — Hong Kong 1986</cite> shrine's gallery page</a>, with its styling being inspired by another Kitty Giraudel's blog post, <a href="https://kittygiraudel.com/2022/09/04/a-content-warning-component/">"A content warning component"</a></li>
</ul>
</div>
</details>
<p>As for citing sources, the simplest way would be naming and linking to the source in the main text of your page, though it does mean you may end up repeating the title of the source if you want to attribute to it more than once on your page. This was once the approach of my shrine pages, though I found the pages looked rather cluttered, so I eventually chose to use markdown-it-footnote alongside Eleventy.</p>
<div class="heading-wrapper h2">
<h2 id="wrapping-up">Wrapping Up</h2>
<a class="heading-anchor" href="https://leilukin.com/articles/accessible-footnotes/#wrapping-up" aria-labelledby="wrapping-up"><span hidden="">#</span></a></div>
<p>Creating and maintaining footnotes on web pages is tricky, so I hope my article about accessible footnotes is helpful if you want to create them.</p>
<p>I am still not completely certain if my method is the best, although I tried to the best of my abilities, so I am interested in hearing feedback for my way of implementing accessible footnotes.</p>
Changelog: 2 August 20242024-08-02T07:42:00Zhttps://leilukin.com/<ul>
<li>Added my first publicly released code snippet on this website: <a href="https://leilukin.com/projects/snippets/disability-pride-flag-background">Responsive Disability Pride Flag CSS Background</a>.</li>
</ul>
Leilukin's Hub Has Migrated to Hostinger | Blog2024-07-26T16:44:00Zhttps://leilukin.com/blog/posts/2024-07-27-hostinger-migration-leilukins-hub/<p>Starting with 25 July 2024, Leilukin's Hub and all its subsites, including its <a href="https://tumbleblog.leilukin.com/">tumbleblog</a> and <a href="https://fan.leilukin.com/">fanlisting collective</a>, have been migrated to <a href="https://www.hostinger.my/">Hostinger</a>. In other words, I have moved hosts again almost two months after <a href="https://leilukin.com/blog/posts/2024-05-31-domain-name-hosting-change-leilukins-hub">moving Leilukin's Hub to Netlify</a>.</p>
<p>Before talking about why I chose Hostinger as my new website host, I want to talk about why I was considering to move hosts again.</p>
<div class="heading-wrapper h2">
<h2 id="why-decided-to-move-hosts-again">Why Decided to Move Hosts Again</h2>
<a class="heading-anchor" href="https://leilukin.com/blog/posts/2024-07-27-hostinger-migration-leilukins-hub/#why-decided-to-move-hosts-again" aria-labelledby="why-decided-to-move-hosts-again"><span hidden="">#</span></a></div>
<div class="heading-wrapper h3">
<h3 id="owning-both-static-and-dynamic-sites">Owning Both Static and Dynamic Sites</h3>
<a class="heading-anchor" href="https://leilukin.com/blog/posts/2024-07-27-hostinger-migration-leilukins-hub/#owning-both-static-and-dynamic-sites" aria-labelledby="owning-both-static-and-dynamic-sites"><span hidden="">#</span></a></div>
<p>The first major reason is that leilukin.com has evolved into more than a static site; since I have also begun to dip my toe into PHP to build dynamic sites, including a tumbleblog, fanlistings and a fanlisting.</p>
<p><a href="https://www.netlify.com/">Netlify</a>, which previously hosted the main site of Leilukin's Hub, does not support PHP hosting, so I hosted my tumbleblog and fanlisting collective on <a href="https://www.infinityfree.com/">InfinityFree</a>, one of the very few platforms to provide PHP and MySQL website hosting for free. InfinityFree has been a decent platform for PHP and MySQL beginners to experiment with the languages, however as you might have expected, its free hosting plan comes with limitations.</p>
<div class="heading-wrapper h3">
<h3 id="limitations-of-infinityfrees-free-hosting">Limitations of InfinityFree's Free Hosting</h3>
<a class="heading-anchor" href="https://leilukin.com/blog/posts/2024-07-27-hostinger-migration-leilukins-hub/#limitations-of-infinityfrees-free-hosting" aria-labelledby="limitations-of-infinityfrees-free-hosting"><span hidden="">#</span></a></div>
<p>InfinityFree places <a href="https://forum.infinityfree.com/docs?topic=49356">their own security measures</a> on websites on their free hosting plan to ensure <a href="https://forum.infinityfree.com/docs?topic=49353">only regular browsers can access these websites</a>. While it is understandable to apply these security measures on free websites to prevent abuse, it can be a dealbreaker depending on your needs.</p>
<p>In my case, the thing that frustrated me the most about InfinityFree's security system on their free websites is the fact that my tumbleblog was unable to provide RSS feed in a usual way. <a href="https://chyrplite.net/">Chyrp Lite</a>, which powers my tumbleblog, includes the feature of providing blog RSS feeds, but InfinityFree's security system blocks feed readers from reading feeds from websites on their free hosting, so I had to use Feedburner to proxy my tumbleblog's feeds to get around it.</p>
<div class="heading-wrapper h3">
<h3 id="invested-in-webmastery-enough-to-spend-money">Invested in Webmastery Enough to Spend Money</h3>
<a class="heading-anchor" href="https://leilukin.com/blog/posts/2024-07-27-hostinger-migration-leilukins-hub/#invested-in-webmastery-enough-to-spend-money" aria-labelledby="invested-in-webmastery-enough-to-spend-money"><span hidden="">#</span></a></div>
<p>Lastly, I am invested in building my own websites enough to spend money on them, as already evident in my purchase and registration of a custom domain name leilukin.com for this website.</p>
<p>That said, I do need to consider carefully about how much money I am going to spend on my hobbies, which factors in why I eventually chose Hostinger to host my websites.</p>
<div class="heading-wrapper h2">
<h2 id="why-hostinger">Why Hostinger</h2>
<a class="heading-anchor" href="https://leilukin.com/blog/posts/2024-07-27-hostinger-migration-leilukins-hub/#why-hostinger" aria-labelledby="why-hostinger"><span hidden="">#</span></a></div>
<div class="heading-wrapper h3">
<h3 id="affordable-price-with-regional-pricing">Affordable Price with Regional Pricing</h3>
<a class="heading-anchor" href="https://leilukin.com/blog/posts/2024-07-27-hostinger-migration-leilukins-hub/#affordable-price-with-regional-pricing" aria-labelledby="affordable-price-with-regional-pricing"><span hidden="">#</span></a></div>
<p>The biggest draw about Hostinger is its pricing — it is not only cheap, but also offering regional pricing. This is a huge deal for people who live in countries with weaker currencies than US Dollars and Euro, as the pricing scales to the level we are more comfortable spending, without worrying about currency conversion rates.</p>
<p>For reference, as of this writing, 1 USD equals approximately 4.6 Malaysian Ringgit (MYR), while the minimum wage in Malaysia is 1,500 MYR, which approximately equals to 321.03 USD, per month. Therefore, if a Malaysian like me is going to spend money, every USD counts.</p>
<p>Compare the pricing of the 48-month Premium Shared Hosting plan, which was what I ended up spending to host my websites, of <a href="https://www.hostinger.my/">Hostinger.my</a> to <a href="https://www.hostinger.com/">Hostinger.com</a>: The plan costs 7.99 per month in MYR (approximately 1.71 USD), while 2.99 per month in USD (approximately 13.97 MYR). This means I ended up saving almost 6 MYR per month by purchasing the plan on the Malaysian branch of Hostinger. This is just comparing Hostinger's own hosting plan with different currencies, let alone comparing Hostinger's hosting plan to its competitors.</p>
<p>As a bonus, being able to purchase Hostinger's hosting plans in Malaysian Ringgit means I can pay by directly transferring money from a Malaysian bank account.</p>
<p>Being cheap is not even the only reason I chose Hostinger; what is better than being cheap is to provide many, many features at the same time.</p>
<div class="heading-wrapper h3">
<h3 id="many-many-features-at-a-cheap-price">Many, Many Features at a Cheap Price</h3>
<a class="heading-anchor" href="https://leilukin.com/blog/posts/2024-07-27-hostinger-migration-leilukins-hub/#many-many-features-at-a-cheap-price" aria-labelledby="many-many-features-at-a-cheap-price"><span hidden="">#</span></a></div>
<p>The cheap price of the Premium Shared Hosting Plan of Hostinger is jam-packed with many features, including but not limited to:</p>
<ul>
<li>Ability to create up to 100 websites (Netlify allows you to deploy 500 sites, but 100 sites are still significantly more than enough for average users)</li>
<li>100 GB SSD storage</li>
<li>Unlimited bandwidth (InfinityFree's free hosting also allows unlimited bandwidth, but Netlify has a limit of 100GB per month)</li>
<li>Unlimited MySQL databases (while Infinity has a limit of 400 databases)</li>
<li>Email accounts included for free</li>
<li>Built-in Git support, which allows me to continue deploying my main site from its Git repository</li>
<li>And more!</li>
</ul>
<p>On the subject of email accounts, it is worth pointing out that Hostinger's Premium Shared Hosting plan allows you to create an email account for each website you made, and you can have up to 100 addresses and forwarders for each email account.</p>
<div class="heading-wrapper h2">
<h2 id="a-birthday-present-for-myself">A Birthday Present for Myself</h2>
<a class="heading-anchor" href="https://leilukin.com/blog/posts/2024-07-27-hostinger-migration-leilukins-hub/#a-birthday-present-for-myself" aria-labelledby="a-birthday-present-for-myself"><span hidden="">#</span></a></div>
<p>Last but not least, another motivator for me to purchase a premium website hosting plan for my websites now is the fact that my birthday is coming soon on July 28, so I spent money on premium hosting for my websites as a birthday present for myself this year.</p>
<div class="heading-wrapper h2">
<h2 id="domain-names-remaining-at-porkbun">Domain Names Remaining at Porkbun</h2>
<a class="heading-anchor" href="https://leilukin.com/blog/posts/2024-07-27-hostinger-migration-leilukins-hub/#domain-names-remaining-at-porkbun" aria-labelledby="domain-names-remaining-at-porkbun"><span hidden="">#</span></a></div>
<p>While Hostinger provides domain registration and transfer service, I chose to have the leilukin.com domain name stay with <a href="https://porkbun.com/">Porkbun</a>, because I already spent money on the domain name, so Hostinger's hosting plan providing domain name registration for free for the first year does not benefit me.</p>
<p>In addition, Porkbun's renewal rate for domain names is cheaper than Hostinger. For example, Porkbun renews the <code>.com</code> domain extension at 10.37 USD per year, while Hostinger renews at 15.99 USD per year. Even the Malaysian Ringgit pricing of Hostinger's domain renewal rate for <code>.com</code>, 55.99 MYR per year, is still more expansive than Porkbun's approximately 48.3 MYR per year rate.</p>
<div class="heading-wrapper h2">
<h2 id="wrapping-up">Wrapping Up</h2>
<a class="heading-anchor" href="https://leilukin.com/blog/posts/2024-07-27-hostinger-migration-leilukins-hub/#wrapping-up" aria-labelledby="wrapping-up"><span hidden="">#</span></a></div>
<p>Leilukin's Hub's migration to Hostinger has been smooth. There was no significant change on the front end of my websites after the switch, aside from changing the theme of my tumbleblog, so my websites will continue to operate as usual, as well as improved site performance for my tumbleblog and fanlisting collective by loading custom web fonts faster to the extent I intended by <a href="https://web.dev/articles/codelab-preload-web-fonts">preloading the fonts</a>.</p>
<p>Moving hosts for my website again reminds me of one of the benefits of owning a custom domain name of making the host migration more seamless, since it saves the trouble of having to change and update my website's address every time I move hosts.</p>
Changelog: 27 July 20242024-07-26T16:32:00Zhttps://leilukin.com/<ul>
<li>Leilukin's Hub and all its subsites have been migrated to <a href="https://www.hostinger.my/">Hostinger</a></li>
<li>New blog post: <a href="https://leilukin.com/blog/posts/2024-07-27-hostinger-migration-leilukins-hub">Leilukin's Hub Has Migrated to Hostinger</a></li>
<li>Change the theme of <a href="https://tumbleblog.leilukin.com/">Leilukin's Hub Tumbleblog</a> to a custom theme based on the Umbra theme from Chyrp Lite</li>
<li>Add a link to contact me via email to the website's footer</li>
</ul>
Changelog: 22 July 20242024-07-22T01:35:00Zhttps://leilukin.com/<ul>
<li>Add a <a href="https://zine.kalechips.net/index">Salad Magazine</a> section to my <a href="https://leilukin.com/adoptables">Adoptables pages</a>.</li>
</ul>