<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet href="/pretty-feed.xsl" type="text/xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Blog posts by Saneef</title>
  
    <link href="https://saneef.com/feed.xml" rel="self" />
    <link href="https://saneef.com" rel="alternate" type="text/html" />
    <updated
      >2024-02-16T14:33:03Z</updated
    >
    <id>https://saneef.com/</id>
    <author>
      <name>Saneef H. Ansari</name>
      <email>hello@saneef.com</email>
    </author><entry>
        <title>Disable built-in DNS clients in Chromium based apps</title>
        <link href="https://saneef.com/blog/disable-built-in-dns-clients-in-chromium-based-apps/" />
        <published>2024-02-16T15:30:00Z</published>
        <updated
          >2024-02-16T14:33:03Z</updated
        >
        <id>https://saneef.com/blog/disable-built-in-dns-clients-in-chromium-based-apps/</id>
        <content type="html"
          ><![CDATA[<p>All Chromium-based apps such a Google Chrome, Obsidian have a built-in DNS client.
I have set up <a href="https://nextdns.io/">NextDNS</a> on my computer to block ads and trackers.
The built-in DNS clients by pass the NextDNS, which I don’t want.</p>
<p>On top of built-in DNS is switched on by default, there is no way to switch it off using the UI.
I found a way to switch it off using the command line<sup class="footnote-ref"><a href="https://saneef.com/blog/disable-built-in-dns-clients-in-chromium-based-apps/#fn1" id="fnref1">[1]</a></sup>.</p>
<p>First, you need the bundle identifier of the Chromium-based app.
I have listed bundle identifiers of popular apps towards <a href="https://saneef.com/blog/disable-built-in-dns-clients-in-chromium-based-apps/#popular-chromium-apps">the end of the page</a>.
Otherwise, use the <code>mdls</code> command to get the bundle identifier.</p>
<pre class="language-sh" tabindex="0"><code class="language-sh"><span class="token comment"># Run this command in Terminal.app</span><br />mdls <span class="token parameter variable">-name</span> kMDItemCFBundleIdentifier <span class="token parameter variable">-r</span> <span class="token operator">&lt;</span>path/to/chromium-app.app<span class="token operator">></span><br /><br /><span class="token comment"># Example:</span><br /><span class="token comment"># $ mdls -name kMDItemCFBundleIdentifier \</span><br /><span class="token comment">#        -r /Applications/Google\ Chrome.app/</span><br /><span class="token comment"># com.google.Chrome</span></code></pre>
<p>Once you have the bundle identifier, use the <code>defaults</code> command to set <code>BuiltInDnsClientEnabled</code> to <code>false</code>.</p>
<pre class="language-sh" tabindex="0"><code class="language-sh"><span class="token comment"># Run this command in Terminal.app</span><br />defaults <span class="token function">write</span> <span class="token operator">&lt;</span>bundle-identifier<span class="token operator">></span> BuiltInDnsClientEnabled <span class="token parameter variable">-boolean</span> <span class="token boolean">false</span><br /><br /><span class="token comment"># Example:</span><br /><span class="token comment"># defaults write org.chromium.Chromium \</span><br /><span class="token comment">#          BuiltInDnsClientEnabled -boolean false</span></code></pre>
<p>Make sure to restart the app after you run the <code>defaults</code> command.
You can use <a href="https://www.dnsleaktest.com/">dnsleaktest.com</a> to check which DNS server is used by the Chromium browser.</p>
<p>You can revert to using the built-in DNS client by deleting the <code>BuiltInDnsClientEnabled</code> preference.</p>
<pre class="language-sh" tabindex="0"><code class="language-sh"><span class="token comment"># Run this command in Terminal.app</span><br />defaults delete <span class="token operator">&lt;</span>bundle-identifier<span class="token operator">></span> BuiltInDnsClientEnabled<br /><br /><span class="token comment"># Example:</span><br /><span class="token comment"># defaults delete org.chromium.Chromium \</span><br /><span class="token comment">#          BuiltInDnsClientEnabled</span></code></pre>
<h2 id="popular-chromium-apps" tabindex="-1">Popular Chromium Apps<a class="link link--anchor" href="https://saneef.com/blog/disable-built-in-dns-clients-in-chromium-based-apps/#popular-chromium-apps" aria-hidden="true" tabindex="-1"></a></h2>
<table>
<thead>
<tr>
<th style="text-align:left">Application</th>
<th style="text-align:left">Bundle Identifier</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left">Chromium</td>
<td style="text-align:left"><code>org.chromium.Chromium</code></td>
</tr>
<tr>
<td style="text-align:left">Google Chrome</td>
<td style="text-align:left"><code>com.google.Chrome</code></td>
</tr>
<tr>
<td style="text-align:left">Obsidian</td>
<td style="text-align:left"><code>md.obsidian</code></td>
</tr>
<tr>
<td style="text-align:left">Visual Studio Code</td>
<td style="text-align:left"><code>com.microsoft.VSCode</code></td>
</tr>
<tr>
<td style="text-align:left">Vivaldi Browser</td>
<td style="text-align:left"><code>com.vivaldi.Vivaldi</code></td>
</tr>
</tbody>
</table>
<hr class="footnotes-sep" />
<section class="footnotes">
<ol class="footnotes-list">
<li id="fn1" class="footnote-item"><p>I learned about this preference from <a href="https://discourse.pi-hole.net/t/disable-async-dns-resolver-in-google-chrome/9500/8">this comment</a> on <a href="https://discourse.pi-hole.net/">discourse.pi-hole.net</a> <a href="https://saneef.com/blog/disable-built-in-dns-clients-in-chromium-based-apps/#fnref1" class="footnote-backref">↩︎</a></p>
</li>
</ol>
</section>

          


          ]]></content
        >
      </entry><entry>
        <title>Website for my 7-year-old kid’s drawings</title>
        <link href="https://saneef.com/blog/website-for-my-7-year-old-kids-drawings/" />
        <published>2024-02-09T10:18:02Z</published>
        <updated
          >2024-02-09T11:35:45Z</updated
        >
        <id>https://saneef.com/blog/website-for-my-7-year-old-kids-drawings/</id>
        <content type="html"
          ><![CDATA[<p>Last week, I made <a href="https://shiro.ws/">a website</a> for my 7-year-old kid to put up his drawing online.
I was amazed at how my kid convinced me to build one.
I thought the website will be a medium for my kid to share drawings with cousins and grandparents.
Later, I posted our conversation with a link to the website on Mastodon.</p>
<blockquote>
<p>7-year-old: Can I put my drawing videos on YouTube?<br />
Me: No.</p>
<p>7-year-old: Can I put my drawings on Instagram?<br />
Me: No way.</p>
<p>7-year-old: Can you make me a website for my drawings?<br />
Me: (after thinking for a moment) Okay. That I can do!</p>
<p>…</p>
<p>After a day <a href="https://shiro.ws/">shiro.ws</a>!</p>
<p>It’s a bunch of HTML pages generated by <a href="https://front-end.social/@eleventy@fosstodon.org">@eleventy</a>. The content is fetched from a Notion Table. Notion allows me or my spouse to add images and text. I have created an iOS Shortcut to publish – rebuild – on Netlify.</p>
<p>—<cite>Saneef Ansari (<a href="https://front-end.social/@saneef">@saneef@front-end.social</a>) on <a href="https://front-end.social/@saneef/111868783885697884">3<sup>rd</sup> February, 2024</a></cite></p>
</blockquote>
<p>After posting on Mastodon, it was full of surprises for us.
Many folks sent emails, long ones, to my kid.
Those were the very first emails my kid got.
It was fun for me to explain what are emails, and to type out the replies.</p>
<p><em>Thank you to all who took out time to write those emails to our kid.</em></p>

          


          ]]></content
        >
      </entry><entry>
        <title>Format Nunjucks files with Prettier</title>
        <link href="https://saneef.com/blog/format-nunjucks-files-with-prettier/" />
        <published>2024-02-08T20:45:40Z</published>
        <updated
          >2024-02-12T03:03:59Z</updated
        >
        <id>https://saneef.com/blog/format-nunjucks-files-with-prettier/</id>
        <content type="html"
          ><![CDATA[<p>I have been using Nunjucks with Eleventy for years.
Until today, I haven’t found a Prettier plugin to format Nunjucks files.
Today I came across <a href="https://indieweb.social/@lyzadanger/111896326815571364">a toot</a> by Lyza Gardner.
In one of the replies, Zach pointed out to try <a href="https://github.com/davidodenwald/prettier-plugin-jinja-template">Jinja Prettier Plugin</a> to format Nunjucks, since Nunjucks is very similar to Jinja.</p>
<p>The plugin works perfectly!
I haven’t found any problems so far.</p>
<pre class="language-js" tabindex="0"><code class="language-js"><span class="token comment">// prettier.config.js</span><br /><br /><span class="token keyword">const</span> config <span class="token operator">=</span> <span class="token punctuation">{</span><br />  <span class="token literal-property property">plugins</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">"prettier-plugin-jinja-template"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><br />  <span class="token literal-property property">overrides</span><span class="token operator">:</span> <span class="token punctuation">[</span><br />    <span class="token punctuation">{</span><br />      <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">"*.njk"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><br />      <span class="token literal-property property">options</span><span class="token operator">:</span> <span class="token punctuation">{</span><br />        <span class="token literal-property property">parser</span><span class="token operator">:</span> <span class="token string">"jinja-template"</span><span class="token punctuation">,</span><br />      <span class="token punctuation">}</span><span class="token punctuation">,</span><br />    <span class="token punctuation">}</span><span class="token punctuation">,</span><br />  <span class="token punctuation">]</span><span class="token punctuation">,</span><br /><span class="token punctuation">}</span><span class="token punctuation">;</span><br /><br /><span class="token keyword">export</span> <span class="token keyword">default</span> config<span class="token punctuation">;</span></code></pre>
<p>Like me, if you use <a href="https://packagecontrol.io/packages/JsPrettier">JsPrettier</a> with Sublime Text, you may want to add <code>njk</code> to JsPrettier’s <code>custom_file_extensions</code> to format with Prettier.</p>
<!-- prettier-ignore -->
<pre class="language-js" tabindex="0"><code class="language-js"><span class="token comment">// ~/Application Support/Sublime Text/Packages/User/JsPrettier.sublime-settings</span><br /><br /><span class="token punctuation">{</span><br />  <span class="token string-property property">"auto_format_on_save"</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span><br />  <span class="token string-property property">"custom_file_extensions"</span><span class="token operator">:</span> <span class="token punctuation">[</span><br />    <span class="token string">"sublime-settings"</span><span class="token punctuation">,</span><br />    <span class="token string">"sublime-project"</span><span class="token punctuation">,</span><br />    <span class="token string">"njk"</span><br />  <span class="token punctuation">]</span><span class="token punctuation">,</span><br />  <span class="token string-property property">"additional_cli_args"</span><span class="token operator">:</span> <span class="token punctuation">{</span><br />    <span class="token comment">// Forces JsPrettier to use Prettier config</span><br />    <span class="token comment">// in the project folder</span><br />    <span class="token string-property property">"--config-precedence"</span><span class="token operator">:</span> <span class="token string">"file-override"</span><br />  <span class="token punctuation">}</span><br /><span class="token punctuation">}</span></code></pre>

          


          ]]></content
        >
      </entry><entry>
        <title>What content should I post on my site?</title>
        <link href="https://saneef.com/blog/content-for-your-website/" />
        <published>2024-01-15T00:00:00Z</published>
        <updated
          >2024-02-09T07:40:14Z</updated
        >
        <id>https://saneef.com/blog/content-for-your-website/</id>
        <content type="html"
          ><![CDATA[<blockquote>
<p>…just post whatever you like. Isn’t that what makes having a personal website so beautiful, after all? It’s yours and you can do and explore whatever you want. Just make sure that this decision is a conscious decision and not just the most comfortable one because you are avoiding to be specific. Being specific about what your site is for also means that you will have more clarity about what it is not for. Suddenly, it will be much easier to leave out the things that are non-essential, allowing you to put your energy into the things that matter most and that truly reflect who you are and what you want your site to be.</p>
<p>—<cite><a href="https://buttondown.email/ownyourweb/archive/issue-07/">Matthias Ott, Own Your Web – Issue 7: What Is It For?</a></cite></p>
</blockquote>

          

  <p>
    <a href="https://saneef.com/blog/content-for-your-website/" title="Direct link to featured article">Direct Link to Article</a>
    &#8212; <a href="https://saneef.com/blog/content-for-your-website/">Permalink</a>
  </p>


          ]]></content
        >
      </entry><entry>
        <title>Tessellated tangrams</title>
        <link href="https://saneef.com/blog/tessellated-tangrams/" />
        <published>2024-01-14T00:00:00Z</published>
        <updated
          >2024-02-09T07:40:14Z</updated
        >
        <id>https://saneef.com/blog/tessellated-tangrams/</id>
        <content type="html"
          ><![CDATA[<style>
  .article .tt-gallery {
    padding-left: 0;
  }

  .tt-gallery {
    --auto-grid-min-size: 18rem;
  }

  .tt-gallery li {
    display: block;
    list-style: none;
  }

  .tt-gallery img {
    width: 100%;
  }
</style>
<p>A collection of patterns generated from repeating an 8-piece tangram arranged as an equilateral triangle.</p>
<h2 id="contents" tabindex="-1">Contents<a class="link link--anchor" href="https://saneef.com/blog/tessellated-tangrams/#contents" aria-hidden="true" tabindex="-1"></a></h2>
<ul>
  <li><a href="https://saneef.com/blog/tessellated-tangrams/#process">Process</a></li>
  <li><a href="https://saneef.com/blog/tessellated-tangrams/#generated-patterns">Generated patterns</a></li>
  <ul>
    <li><a href="https://saneef.com/blog/tessellated-tangrams/#my-favorites">My favorites</a></li>
    <li><a href="https://saneef.com/blog/tessellated-tangrams/#all-of-them">All of them</a></li>
  </ul>
  <li><a href="https://saneef.com/blog/tessellated-tangrams/#inspiration">Inspiration</a></li>
</ul>
<h2 id="process" tabindex="-1">Process<a class="link link--anchor" href="https://saneef.com/blog/tessellated-tangrams/#process" aria-hidden="true" tabindex="-1"></a></h2>
<p>The basic part is an equilateral triangle composed of eight shapes.</p>
<figure>
  <img src="https://saneef.com/images/tessellated-tangrams/8-piece-tangram.png" alt="An equilateral triangle composed of 8 shapes. Each shape is assigned a letter from A to H." />
  <figcaption>Equilateral triangle composed of 8 shapes</figcaption>
</figure>
<p>Each shape of the triangle is assigned an alphabet.
So, to generate the combination AB, the shapes A and B are drawn with a solid colour and the rest of the shapes are not drawn.</p>
<p>The triangle is duplicated by rotating at a vertex, creating a hexagon shape.
This hexagon tile is repeated to create a pattern.
By changing the vertex of rotation of the triangle, we can generate a different hexagon tile.</p>
<figure class="wide">
  <img src="https://saneef.com/images/tessellated-tangrams/process.png" alt="Illustrates the process of generating a pattern from the triangle from the combination ABC." sizes="(min-width: 820px) calc(36.01vw + 451px), 93.4vw" />
  <figcaption>Generating a pattern for the shape combination ABC and rotating at vertex <code>1</code>.</figcaption>
</figure>
<p>Using the eight shapes and rotating the triangle on each of the vertices, we can combine them to create <strong>762 unique patterns</strong>.</p>
<p>I have created the patterns as SVG files using JavaScript.
You can explore my code in <a href="https://observablehq.com/@saneef/067-tessellated-tangrams">this Observable notebook</a>.</p>
<h2 id="generated-patterns" tabindex="-1">Generated patterns<a class="link link--anchor" href="https://saneef.com/blog/tessellated-tangrams/#generated-patterns" aria-hidden="true" tabindex="-1"></a></h2>
<h3 id="my-favorites" tabindex="-1">My favorites<a class="link link--anchor" href="https://saneef.com/blog/tessellated-tangrams/#my-favorites" aria-hidden="true" tabindex="-1"></a></h3>
<p>These are my favourites from generated 762 patterns.</p>
<ul class="[ tt-gallery ][ auto-grid auto-grid-s wide ]" role="list">
<li>
  <img src="https://saneef.com/images/tessellated-tangrams/favourites/3-aefh.svg" loading="lazy" decoding="async" width="240" height="240" alt="Preview of generated artwork 'Tessellated tangrams, Variation: 3-AEFH'" sizes="(min-width: 2880px) calc(8.33vw + 122px), (min-width: 1840px) calc(11.96vw + 142px), (min-width: 800px) calc(17.94vw + 219px), calc(95.83vw - 16px)" data-img2picture-widths="960,810,660,510,360" />
</li><li>
  <img src="https://saneef.com/images/tessellated-tangrams/favourites/3-adefh.svg" loading="lazy" decoding="async" width="240" height="240" alt="Preview of generated artwork 'Tessellated tangrams, Variation: 3-ADEFH'" sizes="(min-width: 2880px) calc(8.33vw + 122px), (min-width: 1840px) calc(11.96vw + 142px), (min-width: 800px) calc(17.94vw + 219px), calc(95.83vw - 16px)" data-img2picture-widths="960,810,660,510,360" />
</li><li>
  <img src="https://saneef.com/images/tessellated-tangrams/favourites/2-acdh.svg" loading="lazy" decoding="async" width="240" height="240" alt="Preview of generated artwork 'Tessellated tangrams, Variation: 2-ACDH'" sizes="(min-width: 2880px) calc(8.33vw + 122px), (min-width: 1840px) calc(11.96vw + 142px), (min-width: 800px) calc(17.94vw + 219px), calc(95.83vw - 16px)" data-img2picture-widths="960,810,660,510,360" />
</li><li>
  <img src="https://saneef.com/images/tessellated-tangrams/favourites/1-begh.svg" loading="lazy" decoding="async" width="240" height="240" alt="Preview of generated artwork 'Tessellated tangrams, Variation: 1-BEGH'" sizes="(min-width: 2880px) calc(8.33vw + 122px), (min-width: 1840px) calc(11.96vw + 142px), (min-width: 800px) calc(17.94vw + 219px), calc(95.83vw - 16px)" data-img2picture-widths="960,810,660,510,360" />
</li><li>
  <img src="https://saneef.com/images/tessellated-tangrams/favourites/1-acdefh.svg" loading="lazy" decoding="async" width="240" height="240" alt="Preview of generated artwork 'Tessellated tangrams, Variation: 1-ACDEFH'" sizes="(min-width: 2880px) calc(8.33vw + 122px), (min-width: 1840px) calc(11.96vw + 142px), (min-width: 800px) calc(17.94vw + 219px), calc(95.83vw - 16px)" data-img2picture-widths="960,810,660,510,360" />
</li><li>
  <img src="https://saneef.com/images/tessellated-tangrams/favourites/1-ace.svg" loading="lazy" decoding="async" width="240" height="240" alt="Preview of generated artwork 'Tessellated tangrams, Variation: 1-ACE'" sizes="(min-width: 2880px) calc(8.33vw + 122px), (min-width: 1840px) calc(11.96vw + 142px), (min-width: 800px) calc(17.94vw + 219px), calc(95.83vw - 16px)" data-img2picture-widths="960,810,660,510,360" />
</li><li>
  <img src="https://saneef.com/images/tessellated-tangrams/favourites/1-adfh.svg" loading="lazy" decoding="async" width="240" height="240" alt="Preview of generated artwork 'Tessellated tangrams, Variation: 1-ADFH'" sizes="(min-width: 2880px) calc(8.33vw + 122px), (min-width: 1840px) calc(11.96vw + 142px), (min-width: 800px) calc(17.94vw + 219px), calc(95.83vw - 16px)" data-img2picture-widths="960,810,660,510,360" />
</li><li>
  <img src="https://saneef.com/images/tessellated-tangrams/favourites/1-bcdf.svg" loading="lazy" decoding="async" width="240" height="240" alt="Preview of generated artwork 'Tessellated tangrams, Variation: 1-BCDF'" sizes="(min-width: 2880px) calc(8.33vw + 122px), (min-width: 1840px) calc(11.96vw + 142px), (min-width: 800px) calc(17.94vw + 219px), calc(95.83vw - 16px)" data-img2picture-widths="960,810,660,510,360" />
</li><li>
  <img src="https://saneef.com/images/tessellated-tangrams/favourites/1-bd.svg" loading="lazy" decoding="async" width="240" height="240" alt="Preview of generated artwork 'Tessellated tangrams, Variation: 1-BD'" sizes="(min-width: 2880px) calc(8.33vw + 122px), (min-width: 1840px) calc(11.96vw + 142px), (min-width: 800px) calc(17.94vw + 219px), calc(95.83vw - 16px)" data-img2picture-widths="960,810,660,510,360" />
</li><li>
  <img src="https://saneef.com/images/tessellated-tangrams/favourites/1-bdegh.svg" loading="lazy" decoding="async" width="240" height="240" alt="Preview of generated artwork 'Tessellated tangrams, Variation: 1-BDEGH'" sizes="(min-width: 2880px) calc(8.33vw + 122px), (min-width: 1840px) calc(11.96vw + 142px), (min-width: 800px) calc(17.94vw + 219px), calc(95.83vw - 16px)" data-img2picture-widths="960,810,660,510,360" />
</li><li>
  <img src="https://saneef.com/images/tessellated-tangrams/favourites/1-bdg.svg" loading="lazy" decoding="async" width="240" height="240" alt="Preview of generated artwork 'Tessellated tangrams, Variation: 1-BDG'" sizes="(min-width: 2880px) calc(8.33vw + 122px), (min-width: 1840px) calc(11.96vw + 142px), (min-width: 800px) calc(17.94vw + 219px), calc(95.83vw - 16px)" data-img2picture-widths="960,810,660,510,360" />
</li><li>
  <img src="https://saneef.com/images/tessellated-tangrams/favourites/1-befg.svg" loading="lazy" decoding="async" width="240" height="240" alt="Preview of generated artwork 'Tessellated tangrams, Variation: 1-BEFG'" sizes="(min-width: 2880px) calc(8.33vw + 122px), (min-width: 1840px) calc(11.96vw + 142px), (min-width: 800px) calc(17.94vw + 219px), calc(95.83vw - 16px)" data-img2picture-widths="960,810,660,510,360" />
</li><li>
  <img src="https://saneef.com/images/tessellated-tangrams/favourites/1-ce.svg" loading="lazy" decoding="async" width="240" height="240" alt="Preview of generated artwork 'Tessellated tangrams, Variation: 1-CE'" sizes="(min-width: 2880px) calc(8.33vw + 122px), (min-width: 1840px) calc(11.96vw + 142px), (min-width: 800px) calc(17.94vw + 219px), calc(95.83vw - 16px)" data-img2picture-widths="960,810,660,510,360" />
</li><li>
  <img src="https://saneef.com/images/tessellated-tangrams/favourites/2-abcfh.svg" loading="lazy" decoding="async" width="240" height="240" alt="Preview of generated artwork 'Tessellated tangrams, Variation: 2-ABCFH'" sizes="(min-width: 2880px) calc(8.33vw + 122px), (min-width: 1840px) calc(11.96vw + 142px), (min-width: 800px) calc(17.94vw + 219px), calc(95.83vw - 16px)" data-img2picture-widths="960,810,660,510,360" />
</li><li>
  <img src="https://saneef.com/images/tessellated-tangrams/favourites/2-abcg.svg" loading="lazy" decoding="async" width="240" height="240" alt="Preview of generated artwork 'Tessellated tangrams, Variation: 2-ABCG'" sizes="(min-width: 2880px) calc(8.33vw + 122px), (min-width: 1840px) calc(11.96vw + 142px), (min-width: 800px) calc(17.94vw + 219px), calc(95.83vw - 16px)" data-img2picture-widths="960,810,660,510,360" />
</li><li>
  <img src="https://saneef.com/images/tessellated-tangrams/favourites/2-abdef.svg" loading="lazy" decoding="async" width="240" height="240" alt="Preview of generated artwork 'Tessellated tangrams, Variation: 2-ABDEF'" sizes="(min-width: 2880px) calc(8.33vw + 122px), (min-width: 1840px) calc(11.96vw + 142px), (min-width: 800px) calc(17.94vw + 219px), calc(95.83vw - 16px)" data-img2picture-widths="960,810,660,510,360" />
</li><li>
  <img src="https://saneef.com/images/tessellated-tangrams/favourites/2-ade.svg" loading="lazy" decoding="async" width="240" height="240" alt="Preview of generated artwork 'Tessellated tangrams, Variation: 2-ADE'" sizes="(min-width: 2880px) calc(8.33vw + 122px), (min-width: 1840px) calc(11.96vw + 142px), (min-width: 800px) calc(17.94vw + 219px), calc(95.83vw - 16px)" data-img2picture-widths="960,810,660,510,360" />
</li><li>
  <img src="https://saneef.com/images/tessellated-tangrams/favourites/2-adg.svg" loading="lazy" decoding="async" width="240" height="240" alt="Preview of generated artwork 'Tessellated tangrams, Variation: 2-ADG'" sizes="(min-width: 2880px) calc(8.33vw + 122px), (min-width: 1840px) calc(11.96vw + 142px), (min-width: 800px) calc(17.94vw + 219px), calc(95.83vw - 16px)" data-img2picture-widths="960,810,660,510,360" />
</li><li>
  <img src="https://saneef.com/images/tessellated-tangrams/favourites/2-bg.svg" loading="lazy" decoding="async" width="240" height="240" alt="Preview of generated artwork 'Tessellated tangrams, Variation: 2-BG'" sizes="(min-width: 2880px) calc(8.33vw + 122px), (min-width: 1840px) calc(11.96vw + 142px), (min-width: 800px) calc(17.94vw + 219px), calc(95.83vw - 16px)" data-img2picture-widths="960,810,660,510,360" />
</li><li>
  <img src="https://saneef.com/images/tessellated-tangrams/favourites/3-abdefg.svg" loading="lazy" decoding="async" width="240" height="240" alt="Preview of generated artwork 'Tessellated tangrams, Variation: 3-ABDEFG'" sizes="(min-width: 2880px) calc(8.33vw + 122px), (min-width: 1840px) calc(11.96vw + 142px), (min-width: 800px) calc(17.94vw + 219px), calc(95.83vw - 16px)" data-img2picture-widths="960,810,660,510,360" />
</li><li>
  <img src="https://saneef.com/images/tessellated-tangrams/favourites/3-abdg.svg" loading="lazy" decoding="async" width="240" height="240" alt="Preview of generated artwork 'Tessellated tangrams, Variation: 3-ABDG'" sizes="(min-width: 2880px) calc(8.33vw + 122px), (min-width: 1840px) calc(11.96vw + 142px), (min-width: 800px) calc(17.94vw + 219px), calc(95.83vw - 16px)" data-img2picture-widths="960,810,660,510,360" />
</li><li>
  <img src="https://saneef.com/images/tessellated-tangrams/favourites/3-abe.svg" loading="lazy" decoding="async" width="240" height="240" alt="Preview of generated artwork 'Tessellated tangrams, Variation: 3-ABE'" sizes="(min-width: 2880px) calc(8.33vw + 122px), (min-width: 1840px) calc(11.96vw + 142px), (min-width: 800px) calc(17.94vw + 219px), calc(95.83vw - 16px)" data-img2picture-widths="960,810,660,510,360" />
</li><li>
  <img src="https://saneef.com/images/tessellated-tangrams/favourites/3-acdefh.svg" loading="lazy" decoding="async" width="240" height="240" alt="Preview of generated artwork 'Tessellated tangrams, Variation: 3-ACDEFH'" sizes="(min-width: 2880px) calc(8.33vw + 122px), (min-width: 1840px) calc(11.96vw + 142px), (min-width: 800px) calc(17.94vw + 219px), calc(95.83vw - 16px)" data-img2picture-widths="960,810,660,510,360" />
</li><li>
  <img src="https://saneef.com/images/tessellated-tangrams/favourites/3-begh.svg" loading="lazy" decoding="async" width="240" height="240" alt="Preview of generated artwork 'Tessellated tangrams, Variation: 3-BEGH'" sizes="(min-width: 2880px) calc(8.33vw + 122px), (min-width: 1840px) calc(11.96vw + 142px), (min-width: 800px) calc(17.94vw + 219px), calc(95.83vw - 16px)" data-img2picture-widths="960,810,660,510,360" />
</li>
</ul>
<h3 id="all-of-them" tabindex="-1">All of them<a class="link link--anchor" href="https://saneef.com/blog/tessellated-tangrams/#all-of-them" aria-hidden="true" tabindex="-1"></a></h3>
<p>You can download all of the 762 patterns as SVG files. <a href="https://d.pr/f/2ubo2p">Download <code>tessellated-tangrams.zip</code></a></p>
<h2 id="inspiration" tabindex="-1">Inspiration<a class="link link--anchor" href="https://saneef.com/blog/tessellated-tangrams/#inspiration" aria-hidden="true" tabindex="-1"></a></h2>
<p>This works is my attempt at <a href="https://dev.to/rickluevanos/copy-code-to-accelerate-learning-583p">copy coding</a>
of the work <a href="https://www.s-ings.com/projects/theodorus-tiles/">Theodorus Tiles</a> by <a href="https://www.s-ings.com/">Smart Things</a>.</p>

          


          ]]></content
        >
      </entry><entry>
        <title>Spam calls and SMSs</title>
        <link href="https://saneef.com/blog/spam/" />
        <published>2024-01-09T00:00:00Z</published>
        <updated
          >2024-01-11T03:33:21Z</updated
        >
        <id>https://saneef.com/blog/spam/</id>
        <content type="html"
          ><![CDATA[<p>I hate spam calls and SMSs.
I don’t trust spam blocking apps where you need to upload all your contacts or SMSs.
All I could do is block the caller.
I have hope that things will get better in the future.</p>
<p>In India, the regulatory body Telecom Regulatory Authority of India (TRAI) has set guidelines for the telecom operators to manage spam.
The primary mechanism is <a href="https://trai.gov.in/preference-registration">a registry</a> that has to be maintained by telecom operators.
The idea is that the owner of a mobile number can give consent to receive promotional communication.
It is not straightforward, I’ll get to it later.
The subscriber can fine tune the consent based on category of business (like banking, tourism, or entertainment), mode of communication, time of day, or day of the week.</p>
<p>Unfortunately, when a new mobile number is issued, all promotional communications are allowed to the new number.
That is, each new subscriber is consented to receive spam.
One has to opt out of all communications or partially based on one’s interest.</p>
<p>I have opted out of all promotional communications.
But still, I get spam calls and SMSs.
I diligently report the offenders.
That’s one of my hobbies.</p>
<figure>
  <img src="https://saneef.com/images/spam-calls-actions-taken-chart.svg" alt="Dot chart showing spam communication complaints I have filed since November 2020. The numbers are higher in 2022 and 2023." />
  <figcaption>My complaints since November 2020 and the steps taken by telecom providers.</figcaption>
</figure>
<p>About a quarter of my complaints were ignored by the operators stating silly justifications, the communication was not found to be unsolicited (I would be the judge of that), or it was a service communication. But weirdest of all is:</p>
<blockquote>
<p>The sender number’s operator has reported that the reported call/SMS could not be located in their call records.</p>
</blockquote>
<p>I don’t know how a call or SMS reaches my phone without a trace in systems of the telecom operator.</p>
<p>Anyway, in the majority of cases they have given warning to the offenders.
In the case of repeated offenders, they enforce restricted use for a month or six months.
In 11 cases, the operators have disconnected mobile and blacklisted the offenders!</p>
<figure>
  <img src="https://saneef.com/images/spam-calls-distribution-of-actions-taken.svg" alt="Bar chart showing the steps taken by the telecom operators based on my complaints. Ignored 31 of my complaints. Issued warning in 116 cases, and disconnected the offender's connection in 11 cases." />
  <figcaption>The distribution of measures taken by telecom providers in response to my complaints.</figcaption>
</figure>
<p>So far, I’m happy with the results.
I’ll continue to file complaints as one of my hobbies.</p>

          


          ]]></content
        >
      </entry><entry>
        <title>You might be looking for HTML article, not section</title>
        <link href="https://saneef.com/blog/html-article/" />
        <published>2023-12-18T00:00:00Z</published>
        <updated
          >2024-02-09T07:40:14Z</updated
        >
        <id>https://saneef.com/blog/html-article/</id>
        <content type="html"
          ><![CDATA[<p>In many projects, I see the <code>&lt;section&gt;</code> HTML elements are used to create <em>sections</em> within web pages.
Isn’t it straightforward to use <code>&lt;section&gt;</code> to create a section on a page?
Surprisingly, that is not the case.</p>
<p>The <code>&lt;section&gt;</code> element was originally meant as a wrapper for HTML headings, in order for browsers to determine the HTML5 document outline.
But, none of the browsers implemented the document outlining algorithm, making the <code>&lt;section&gt;</code> element kind of useless to create sections on a page.</p>
<p>The right element for creating sections is <code>&lt;article&gt;</code>.
The below analogy by Bruce will help in alleviating the discrepancy a bit.</p>
<blockquote>
<p>…think of <code>&lt;article&gt;</code> not just as a newspaper article, or a blog post, but as an article of clothing — a discrete entity that can be reused in another context. So your trousers are an article, and you can wear them with a different outfit; your shirt is an article, and can be worn with different trousers; your knee-length patent leather stiletto boots are an article (you wouldn’t wear just one of them, would you?).</p>
<p>—<cite>Bruce Lawson, <a href="https://www.smashingmagazine.com/2020/01/html5-article-section/">Why You Should Choose HTML5 <code>article</code> Over <code>section</code></a></cite></p>
</blockquote>

          


          ]]></content
        >
      </entry><entry>
        <title>Drop cap</title>
        <link href="https://saneef.com/blog/drop-cap/" />
        <published>2023-12-04T00:00:00Z</published>
        <updated
          >2024-02-09T07:40:14Z</updated
        >
        <id>https://saneef.com/blog/drop-cap/</id>
        <content type="html"
          ><![CDATA[<p>The article ‘<a href="https://www.sarahgebauer.com/post/day-2-drop-a-cap/">Drop a cap?</a>’ by Sarah Gebauer reminded me that it is possible to have a drop cap (or <a href="https://en.wikipedia.org/wiki/Initial">initial letter</a>) without hacks like wrapping the first letter in a <code>span</code>.</p>
<p>The effect is achieved using two CSS features.
First, using the <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/::first-letter"><code>::first-letter</code></a> peudo-element, we can target the first letter of the first line of <em>a block container.</em>
Then with <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/initial-letter"><code>initial-letter</code></a> property we can set size, and vertical shift of the initial letter.</p>
<!-- prettier-ignore-start -->
<pre class="language-css" tabindex="0"><code class="language-css"><span class="token selector">p::first-letter</span> <span class="token punctuation">{</span><br />  <span class="token comment">/* Initial letter occupies height of 3 lines,<br />   * and baseline will move down by 3 lines<br />   */</span><br />  <span class="token property">initial-letter</span><span class="token punctuation">:</span> 3<span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token selector">p::first-letter</span> <span class="token punctuation">{</span><br />  <span class="token comment">/* Initial letter occupies height of 3 lines,<br />   * and baseline will move down by 2 lines<br />   */</span><br />  <span class="token property">initial-letter</span><span class="token punctuation">:</span> 3 2<span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<!-- prettier-ignore-end -->
<p>As of writing, Firefox doesn’t support <code>intial-letter</code>.
So, with the help of <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/@supports"><code>@support</code></a> rule, we can write styles with fallback.</p>
<!-- prettier-ignore-start -->
<style>

.drop-cap-demo {
  --drop-cap-lines: 3;
  --drop-cap-color: rgb(226, 98, 87);
}

/* Styles for browsers which don't support 'initial-letter' */
.drop-cap-demo section p:first-of-type:first-letter {
  font-size: 150%;
  font-weight: bold;
  color: var(--drop-cap-color);
}

@supports (-webkit-initial-letter: 2) or (initial-letter: 2) {
  .drop-cap-demo section p:first-of-type:first-letter {
    -webkit-initial-letter: var(--drop-cap-lines);
    initial-letter: var(--drop-cap-lines);

    margin-inline-end: 0.125em;

    /* Reset fallback styles */
    font-weight: normal;
    font-size: inherit;
  }
}

/* Presentational styles */

.drop-cap-demo section {
  font-family: Baskerville, Baskerville Old Face, Hoefler Text, Garamond,
    Times New Roman, serif;
}

.drop-cap-demo code {
  font-family: var(--font-family-monospace);
}

.drop-cap-demo hr,
.drop-cap-demo section {
  margin-top: var(--space-m);
}


.drop-cap-demo section,
.drop-cap-demo-not-supported-alert {
  max-width: 23rem;
  margin-inline: auto;
}

.drop-cap-demo em {
  font-style: italic;
}

.drop-cap-demo-not-supported-alert {
  padding: 1rem;
  background-color: wheat;
  text-shadow: var(--text-shadow-light);
}

@supports (-webkit-initial-letter: 2) or (initial-letter: 2) {
  .drop-cap-demo-not-supported-alert{
    display: none;
  }
}

</style>
<details class="code-demo__collapse" open="true">
  <summary class="code-demo__collapse-title">CSS</summary>
  <div class="code-demo__code">
    <pre class="language-css" tabindex="0"><code class="language-css"><span class="token selector">.drop-cap-demo</span> <span class="token punctuation">{</span><br />  <span class="token property">--drop-cap-lines</span><span class="token punctuation">:</span> 3<span class="token punctuation">;</span><br />  <span class="token property">--drop-cap-color</span><span class="token punctuation">:</span> <span class="token function">rgb</span><span class="token punctuation">(</span>226<span class="token punctuation">,</span> 98<span class="token punctuation">,</span> 87<span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token comment">/* Styles for browsers which don't support 'initial-letter' */</span><br /><span class="token selector">.drop-cap-demo section p:first-of-type:first-letter</span> <span class="token punctuation">{</span><br />  <span class="token property">font-size</span><span class="token punctuation">:</span> 150%<span class="token punctuation">;</span><br />  <span class="token property">font-weight</span><span class="token punctuation">:</span> bold<span class="token punctuation">;</span><br />  <span class="token property">color</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--drop-cap-color<span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token atrule"><span class="token rule">@supports</span> <span class="token punctuation">(</span><span class="token property">-webkit-initial-letter</span><span class="token punctuation">:</span> 2<span class="token punctuation">)</span> <span class="token keyword">or</span> <span class="token punctuation">(</span><span class="token property">initial-letter</span><span class="token punctuation">:</span> 2<span class="token punctuation">)</span></span> <span class="token punctuation">{</span><br />  <span class="token selector">.drop-cap-demo section p:first-of-type:first-letter</span> <span class="token punctuation">{</span><br />    <span class="token property">-webkit-initial-letter</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--drop-cap-lines<span class="token punctuation">)</span><span class="token punctuation">;</span><br />    <span class="token property">initial-letter</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--drop-cap-lines<span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br />    <span class="token property">margin-inline-end</span><span class="token punctuation">:</span> 0.125em<span class="token punctuation">;</span><br /><br />    <span class="token comment">/* Reset fallback styles */</span><br />    <span class="token property">font-weight</span><span class="token punctuation">:</span> normal<span class="token punctuation">;</span><br />    <span class="token property">font-size</span><span class="token punctuation">:</span> inherit<span class="token punctuation">;</span><br />  <span class="token punctuation">}</span><br /><span class="token punctuation">}</span><br /><br /><span class="token comment">/* Presentational styles */</span><br /><br /><span class="token selector">.drop-cap-demo section</span> <span class="token punctuation">{</span><br />  <span class="token property">font-family</span><span class="token punctuation">:</span> Baskerville<span class="token punctuation">,</span> Baskerville Old Face<span class="token punctuation">,</span> Hoefler Text<span class="token punctuation">,</span> Garamond<span class="token punctuation">,</span><br />    Times New Roman<span class="token punctuation">,</span> serif<span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token selector">.drop-cap-demo code</span> <span class="token punctuation">{</span><br />  <span class="token property">font-family</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--font-family-monospace<span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token selector">.drop-cap-demo hr,<br />.drop-cap-demo section</span> <span class="token punctuation">{</span><br />  <span class="token property">margin-top</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--space-m<span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><br /><span class="token selector">.drop-cap-demo section,<br />.drop-cap-demo-not-supported-alert</span> <span class="token punctuation">{</span><br />  <span class="token property">max-width</span><span class="token punctuation">:</span> 23rem<span class="token punctuation">;</span><br />  <span class="token property">margin-inline</span><span class="token punctuation">:</span> auto<span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token selector">.drop-cap-demo em</span> <span class="token punctuation">{</span><br />  <span class="token property">font-style</span><span class="token punctuation">:</span> italic<span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token selector">.drop-cap-demo-not-supported-alert</span> <span class="token punctuation">{</span><br />  <span class="token property">padding</span><span class="token punctuation">:</span> 1rem<span class="token punctuation">;</span><br />  <span class="token property">background-color</span><span class="token punctuation">:</span> wheat<span class="token punctuation">;</span><br />  <span class="token property">text-shadow</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--text-shadow-light<span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token atrule"><span class="token rule">@supports</span> <span class="token punctuation">(</span><span class="token property">-webkit-initial-letter</span><span class="token punctuation">:</span> 2<span class="token punctuation">)</span> <span class="token keyword">or</span> <span class="token punctuation">(</span><span class="token property">initial-letter</span><span class="token punctuation">:</span> 2<span class="token punctuation">)</span></span> <span class="token punctuation">{</span><br />  <span class="token selector">.drop-cap-demo-not-supported-alert</span><span class="token punctuation">{</span><br />    <span class="token property">display</span><span class="token punctuation">:</span> none<span class="token punctuation">;</span><br />  <span class="token punctuation">}</span><br /><span class="token punctuation">}</span></code></pre>
  </div>
</details>
<details class="code-demo__collapse">
  <summary class="code-demo__collapse-title">HTML</summary>
  <div class="code-demo__code">
    <pre class="language-html" tabindex="0"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</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>drop-cap-demo<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br />  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</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>drop-cap-demo-not-supported-alert<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br />    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">></span></span>CSS property <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>code</span><span class="token punctuation">></span></span>initial-letter<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>code</span><span class="token punctuation">></span></span> is not supported in this browser. Try with latest Google Chrome or Apple Safari.<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">></span></span><br />  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span><br /><br />  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>section</span><span class="token punctuation">></span></span><br />    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">></span></span>A professional case of great gravity was engaging my own attention at the time, and the whole of next day I was busy at the bedside of the sufferer. It was not until close upon six o'clock that I found myself free and was able to spring into a hansom and drive to Baker Street, half afraid that I might be too late to assist at the dénouement of the little mystery.<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">></span></span><br />    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</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>drop-cap-demo-legend<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br />      <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>code</span><span class="token punctuation">></span></span>initial-letter: 3<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>code</span><span class="token punctuation">></span></span><br />    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span><br />  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>section</span><span class="token punctuation">></span></span><br /><br />  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>hr</span><span class="token punctuation">></span></span><br /><br />  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>section</span> <span class="token special-attr"><span class="token attr-name">style</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token value css language-css"><span class="token property">--drop-cap-lines</span><span class="token punctuation">:</span> 3 2<span class="token punctuation">;</span></span><span class="token punctuation">"</span></span></span><span class="token punctuation">></span></span><br />    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">></span></span>A professional case of great gravity was engaging my own attention at the time, and the whole of next day I was busy at the bedside of the sufferer. It was not until close upon six o'clock that I found myself free and was able to spring into a hansom and drive to Baker Street, half afraid that I might be too late to assist at the dénouement of the little mystery. <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">></span></span><br />    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</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>drop-cap-demo-legend<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br />      <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>code</span><span class="token punctuation">></span></span>initial-letter: 3 2;<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>code</span><span class="token punctuation">></span></span><br />    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span><br />  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>section</span><span class="token punctuation">></span></span><br /><br />  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>hr</span><span class="token punctuation">></span></span><br /><br />  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>section</span> <span class="token special-attr"><span class="token attr-name">style</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token value css language-css"><span class="token property">--drop-cap-lines</span><span class="token punctuation">:</span> 2.5 2<span class="token punctuation">;</span></span><span class="token punctuation">"</span></span></span><span class="token punctuation">></span></span><br />    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">></span></span>A professional case of great gravity was engaging my own attention at the time, and the whole of next day I was busy at the bedside of the sufferer. It was not until close upon six o'clock that I found myself free and was able to spring into a hansom and drive to Baker Street, half afraid that I might be too late to assist at the dénouement of the little mystery. <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">></span></span><br />    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</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>drop-cap-demo-legend<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br />      <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>code</span><span class="token punctuation">></span></span>initial-letter: 2.5 2;<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>code</span><span class="token punctuation">></span></span><br />      <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>em</span><span class="token punctuation">></span></span>Vertical alignment might be broken in Google Chrome. Works fine in Apple Safari.<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>em</span><span class="token punctuation">></span></span><br />    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span><br />  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>section</span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span></code></pre>
  </div>
</details>
<details class="code-demo__collapse" open="true">
  <summary class="code-demo__collapse-title">Preview</summary>
  <div class="code-demo__output">
<div class="drop-cap-demo">
  <div class="drop-cap-demo-not-supported-alert">
    <p>CSS property <code>initial-letter</code> is not supported in this browser. Try with latest Google Chrome or Apple Safari.</p>
  </div>
  <section>
    <p>A professional case of great gravity was engaging my own attention at the time, and the whole of next day I was busy at the bedside of the sufferer. It was not until close upon six o'clock that I found myself free and was able to spring into a hansom and drive to Baker Street, half afraid that I might be too late to assist at the dénouement of the little mystery.</p>
    <div class="drop-cap-demo-legend">
      <code>initial-letter: 3</code>
    </div>
  </section>
  <hr />
  <section style="--drop-cap-lines: 3 2;">
    <p>A professional case of great gravity was engaging my own attention at the time, and the whole of next day I was busy at the bedside of the sufferer. It was not until close upon six o'clock that I found myself free and was able to spring into a hansom and drive to Baker Street, half afraid that I might be too late to assist at the dénouement of the little mystery. </p>
    <div class="drop-cap-demo-legend">
      <code>initial-letter: 3 2;</code>
    </div>
  </section>
  <hr />
  <section style="--drop-cap-lines: 2.5 2;">
    <p>A professional case of great gravity was engaging my own attention at the time, and the whole of next day I was busy at the bedside of the sufferer. It was not until close upon six o'clock that I found myself free and was able to spring into a hansom and drive to Baker Street, half afraid that I might be too late to assist at the dénouement of the little mystery. </p>
    <div class="drop-cap-demo-legend">
      <code>initial-letter: 2.5 2;</code>
      <em>Vertical alignment might be broken in Google Chrome. Works fine in Apple Safari.</em>
    </div>
  </section>
</div>
  </div>
</details>
  <form action="https://codepen.io/pen/define" method="POST" target="_blank">
        <input type="hidden" name="data" value='{"title":"Saneef.com - Drop cap","description":"Generated from: https://saneef.com/blog/drop-cap/","tags":["saneef.com"],"editors":"110","layout":"left","html":"<!-- Saneef.com - Drop cap\nGenerated from: https://saneef.com/blog/drop-cap/ -->\n<div class=\"drop-cap-demo\">\n  <div class=\"drop-cap-demo-not-supported-alert\">\n    <p>CSS property <code>initial-letter</code> is not supported in this browser. Try with latest Google Chrome or Apple Safari.</p>\n  </div>\n\n  <section>\n    <p>A professional case of great gravity was engaging my own attention at the time, and the whole of next day I was busy at the bedside of the sufferer. It was not until close upon six o&apos;clock that I found myself free and was able to spring into a hansom and drive to Baker Street, half afraid that I might be too late to assist at the dénouement of the little mystery.</p>\n    <div class=\"drop-cap-demo-legend\">\n      <code>initial-letter: 3</code>\n    </div>\n  </section>\n\n  <hr>\n\n  <section style=\"--drop-cap-lines: 3 2;\">\n    <p>A professional case of great gravity was engaging my own attention at the time, and the whole of next day I was busy at the bedside of the sufferer. It was not until close upon six o&apos;clock that I found myself free and was able to spring into a hansom and drive to Baker Street, half afraid that I might be too late to assist at the dénouement of the little mystery. </p>\n    <div class=\"drop-cap-demo-legend\">\n      <code>initial-letter: 3 2;</code>\n    </div>\n  </section>\n\n  <hr>\n\n  <section style=\"--drop-cap-lines: 2.5 2;\">\n    <p>A professional case of great gravity was engaging my own attention at the time, and the whole of next day I was busy at the bedside of the sufferer. It was not until close upon six o&apos;clock that I found myself free and was able to spring into a hansom and drive to Baker Street, half afraid that I might be too late to assist at the dénouement of the little mystery. </p>\n    <div class=\"drop-cap-demo-legend\">\n      <code>initial-letter: 2.5 2;</code>\n      <em>Vertical alignment might be broken in Google Chrome. Works fine in Apple Safari.</em>\n    </div>\n  </section>\n</div>\n","html_pre_processor":"none","css":"/* Box sizing rules */\n*,\n*::before,\n*::after {\n  box-sizing: border-box;\n}\n\n/* Remove default margin */\nbody,\nh1,\nh2,\nh3,\nh4,\np {\n  margin: 0;\n}\n\n/* Set core body defaults */\nbody {\n  min-height: 100vh;\n  text-rendering: optimizeSpeed;\n  line-height: 1.5;\n  font-family: system-ui, sans-serif;\n}\n\n/* Make images easier to work with */\nimg {\n  display: block;\n  max-width: 100%;\n}\n\n/***\n 🟣 Saneef.com Demo Styles\n */\n\n.drop-cap-demo {\n  --drop-cap-lines: 3;\n  --drop-cap-color: rgb(226, 98, 87);\n}\n\n/* Styles for browsers which don&apos;t support &apos;initial-letter&apos; */\n.drop-cap-demo section p:first-of-type:first-letter {\n  font-size: 150%;\n  font-weight: bold;\n  color: var(--drop-cap-color);\n}\n\n@supports (-webkit-initial-letter: 2) or (initial-letter: 2) {\n  .drop-cap-demo section p:first-of-type:first-letter {\n    -webkit-initial-letter: var(--drop-cap-lines);\n    initial-letter: var(--drop-cap-lines);\n\n    margin-inline-end: 0.125em;\n\n    /* Reset fallback styles */\n    font-weight: normal;\n    font-size: inherit;\n  }\n}\n\n/* Presentational styles */\n\n.drop-cap-demo section {\n  font-family: Baskerville, Baskerville Old Face, Hoefler Text, Garamond,\n    Times New Roman, serif;\n}\n\n.drop-cap-demo code {\n  font-family: var(--font-family-monospace);\n}\n\n.drop-cap-demo hr,\n.drop-cap-demo section {\n  margin-top: var(--space-m);\n}\n\n\n.drop-cap-demo section,\n.drop-cap-demo-not-supported-alert {\n  max-width: 23rem;\n  margin-inline: auto;\n}\n\n.drop-cap-demo em {\n  font-style: italic;\n}\n\n.drop-cap-demo-not-supported-alert {\n  padding: 1rem;\n  background-color: wheat;\n  text-shadow: var(--text-shadow-light);\n}\n\n@supports (-webkit-initial-letter: 2) or (initial-letter: 2) {\n  .drop-cap-demo-not-supported-alert{\n    display: none;\n  }\n}\n","css_pre_processor":"scss","css_starter":"neither","css_prefix":"autoprefixer","head":"<meta name=&apos;viewport&apos; content=&apos;width=device-width, initial-scale=1&apos;>"}' />
        <button class="button" type="submit" data-name="Drop cap" aria-label="Open Drop cap in CodePen"><span class="button__icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" aria-hidden="true" focusable="false">
      <path d="M32 10.909l-0.024-0.116-0.023-0.067c-0.013-0.032-0.024-0.067-0.040-0.1-0.004-0.024-0.020-0.045-0.027-0.067l-0.047-0.089-0.040-0.067-0.059-0.080-0.061-0.060-0.080-0.060-0.061-0.040-0.080-0.059-0.059-0.053-0.020-0.027-14.607-9.772c-0.463-0.309-1.061-0.309-1.523 0l-14.805 9.883-0.051 0.053-0.067 0.075-0.049 0.060-0.067 0.080c-0.027 0.023-0.040 0.040-0.040 0.061l-0.067 0.080-0.027 0.080c-0.027 0.013-0.027 0.053-0.040 0.093l-0.013 0.067c-0.025 0.041-0.025 0.081-0.025 0.121v9.996c0 0.059 0.004 0.12 0.013 0.18l0.013 0.061c0.007 0.040 0.013 0.080 0.027 0.115l0.020 0.067c0.013 0.036 0.021 0.071 0.036 0.1l0.029 0.067c0 0.013 0.020 0.053 0.040 0.080l0.040 0.053c0.020 0.013 0.040 0.053 0.060 0.080l0.040 0.053 0.053 0.053c0.013 0.017 0.013 0.040 0.040 0.040l0.080 0.056 0.053 0.040 0.013 0.019 14.627 9.773c0.219 0.16 0.5 0.217 0.76 0.217s0.52-0.080 0.76-0.24l14.877-9.875 0.069-0.077 0.044-0.060 0.053-0.080 0.040-0.067 0.040-0.093 0.021-0.069 0.040-0.103 0.020-0.060 0.040-0.107v-10c0-0.067 0-0.127-0.021-0.187l-0.019-0.060 0.059 0.004zM16.013 19.283l-4.867-3.253 4.867-3.256 4.867 3.253-4.867 3.253zM14.635 10.384l-5.964 3.987-4.817-3.221 10.781-7.187v6.424zM6.195 16.028l-3.443 2.307v-4.601l3.443 2.301zM8.671 17.695l5.964 3.987v6.427l-10.781-7.188 4.824-3.223v-0.005zM17.387 21.681l5.965-3.973 4.817 3.227-10.783 7.187v-6.427zM25.827 16.041l3.444-2.293v4.608l-3.444-2.307zM23.353 14.388l-5.964-3.988v-6.44l10.78 7.187-4.816 3.224z"></path>
    </svg></span> Open in CodePen</button>
        </form>
<!-- prettier-ignore-end -->

          


          ]]></content
        >
      </entry><entry>
        <title>Home for my generative art</title>
        <link href="https://saneef.com/blog/generative-art/" />
        <published>2023-11-04T00:00:00Z</published>
        <updated
          >2023-11-05T14:18:21Z</updated
        >
        <id>https://saneef.com/blog/generative-art/</id>
        <content type="html"
          ><![CDATA[<p>I have moved some of my favourite generative artworks from Observable notebooks to my domain, <a href="https://art.saneef.com/">art.saneef.com</a>.</p>
<p>I have been publishing generative art notebooks on <a href="https://observablehq.com/collection/@saneef/re-plicas-mixes">Observable</a> since some time.
It is not something I do regularly.
I do when I see <em>something</em> which I really want to replicate in code, or when some random idea pops up in my mind.
Some works are clones of others work.</p>
<p><a href="https://saneef.com/blog/observable/">I love Observable</a> for its notebook nature.
Others can look under the hood and see how everything works.
At least that’s how learned about many concepts.</p>
<p>But.</p>
<p>I’m not comfortable keeping my work on a platform.
Who knows, that website might stop working one day.</p>
<p>Friends have asked me if there is a way to buy the prints of the works.
On, <a href="https://art.saneef.com/">art.saneef.com</a>, you can print the artwork you generate.</p>
<p>The concept of having my own generative gallery was sparked when I saw Heydon Pickering’s <a href="https://mutable.gallery/">Mutable Gallery</a> some years ago.
That’s where I first encountered the print on-demand service <a href="https://www.peecho.com/">Peecho</a>.</p>
<p>Conventionally, print on-demand services expect me to have premade graphics, create and maintain inventory, and handle my payments.
With Peecho, I can provide a high-quality image, and they will take care of the whole checkout: selection of prints, payments, and shipping.
Once an order is fulfilled, they will pay me a part of the payment as a licensing fee.
I can transfer the fund to my bank account when a minimum value of €100 is reached.
It’s simple.</p>
<p>Have you seen a service like Peecho that makes T-shirts or other products?</p>

          


          ]]></content
        >
      </entry><entry>
        <title>What I love about Observable</title>
        <link href="https://saneef.com/blog/observable/" />
        <published>2022-12-29T00:00:00Z</published>
        <updated
          >2022-12-29T20:00:49Z</updated
        >
        <id>https://saneef.com/blog/observable/</id>
        <content type="html"
          ><![CDATA[<p>When I’m looking at a data visualisation, or a generative art notebook at <a href="https://observablehq.com/explore">Observable</a>, it is so easy to look under the hood.
I can read the whole code.
I can tinker with it.
It is fun to learn by meddling with other’s code.</p>
<p>I can insert an output, or invoke a piece of code from any public notebooks into my notebook through <a href="https://observablehq.com/@observablehq/import?collection=@observablehq/notebook-fundamentals">Imports</a>.
I can use NPM packages; without any build tools!
All imports are links.
I can find the source code easily.</p>
<p>I’m lucky to be part of <a href="https://observablehq.com/ambassadors">a lovely community</a>.
Thank you <a href="https://observablehq.com/@fil">Fil</a>, <a href="https://observablehq.com/@mootari">Fabian</a>, <a href="https://observablehq.com/@aaronkyle">Aaron</a>, <a href="https://observablehq.com/@tomlarkworthy">Tom</a>, fellow members, and folks at Observable for helping me with my rookie questions.</p>
<p>Observable is magic! Give <a href="https://observablehq.com/@observablehq/a-taste-of-observable?collection=@observablehq/getting-started">it a taste</a>.</p>
<p><a href="mailto:hello@saneef.com?subject=Hey%20Saneef,%20I%20need%20company%20to%20explore%20Observable.">Hit me up</a> if you need company to explore.</p>

          


          ]]></content
        >
      </entry><entry>
        <title>Things to get you started with generative art</title>
        <link href="https://saneef.com/blog/generative-art-resources/" />
        <published>2022-04-22T00:00:00Z</published>
        <updated
          >2024-02-09T07:40:14Z</updated
        >
        <id>https://saneef.com/blog/generative-art-resources/</id>
        <content type="html"
          ><![CDATA[<p>I have been drawing with code since some time. Usually, I code and publish on <a href="https://observablehq.com/collection/@saneef/re-plicas-mixes">Observable</a>. Seeing some of my work, a couple of folks asked me, are there any resources to get started with generative art. Here are some that helped me:</p>
<ul>
<li><strong><a href="https://programmingdesignsystems.com/">Programming Design Systems</a> by <a href="https://twitter.com/runemadsen">Rune Madsen</a>:</strong> A good from the scratch guide to draw with code. The code examples are in <a href="https://p5js.org/">p5.js</a>.</li>
<li><strong><a href="https://generativeartistry.com/tutorials/">generative artistry tutorials</a> by <a href="https://twitter.com/Rumyra">Ruth</a> and <a href="https://twitter.com/twholman">Tim</a>:</strong> A handful of easy to follow tutorials for drawing the classics from generative art. The code examples are in JavaScript.</li>
<li><strong><a href="https://thecodingtrain.com/">The Coding Train</a> by <a href="https://twitter.com/shiffman">Daniel Shiffman</a>:</strong> An exhaustive collection of resources. You’ll find tutorials from using a variable to neural networks. This is my first destination to learn about any new concepts.</li>
<li><strong>Resources by <a href="https://twitter.com/mattdesl">Matt DesLauriers</a>:</strong>
<ul>
<li><strong><a href="https://frontendmasters.com/courses/canvas-webgl/">Creative Coding with Canvas &amp; WebGL</a> workshop on FrontendMasters (Paid):</strong> This workshop taught me how to structure the idea (and code) while making these graphics. For example, separate the data from the drawing logic. It helps you to experiment by replacing the drawing logic to make something different with the same data. Or, you can swap non-random data with random data to create something different. This helped me to do more and more graphics.</li>
<li><strong><a href="https://github.com/mattdesl/canvas-sketch">canvas-sketch</a>:</strong> This collection of tools gets you started with an environment with live reloading, print-friendly graphics, export to video and many.</li>
<li><strong><a href="https://github.com/mattdesl/canvas-sketch-util/">canvas-sketch-util</a>:</strong> This is a collection of utility functions related to Random (noise), Maths, Geometry, and others. I use one or the other function from this collection every time I do generative art.</li>
</ul>
</li>
<li><strong>Books:</strong> I haven’t followed them from start to end. But, I have learned some tricks by skimming these:
<ul>
<li><a href="https://natureofcode.com/">Nature of Code</a> by Daniel Shiffman</li>
<li><a href="http://www.generative-gestaltung.de/2/">Generative Design: Visualize, Program, and Create with Processing</a></li>
</ul>
</li>
</ul>
<p>Good luck with your generative art journey. If you have any questions while learning generative art, feel free to <a href="mailto:hello@saneef.com?subject=Hey%20Saneef,%20I%20have%20a%20question">mail me</a>.</p>

          


          ]]></content
        >
      </entry><entry>
        <title>Syntax highlighting for AsciiDoc with Eleventy</title>
        <link href="https://saneef.com/blog/asciidoc-syntax-highlighting/" />
        <published>2022-04-12T00:00:00Z</published>
        <updated
          >2023-12-20T04:53:48Z</updated
        >
        <id>https://saneef.com/blog/asciidoc-syntax-highlighting/</id>
        <content type="html"
          ><![CDATA[<p>I created a AsciiDoc plugin for Eleventy to use <code>.adoc</code> files directly, like <code>.md</code> files. Since it uses Eleventy’s <a href="https://www.11ty.dev/docs/languages/custom/">new custom template API</a>, you cannot use the official <a href="https://www.11ty.dev/docs/plugins/syntaxhighlight/">Eleventy syntax highlighting plugin</a>, at least directly. I’ll walk you through the steps to add syntax highlight to your Eleventy-AsciiDoc blog.</p>
<p>The libraries like <a href="https://prismjs.com/">Prism.js</a> and <a href="https://highlightjs.org/">Highlight.js</a> parses the code blocks, and breaks down into keywords and symbols. Then they will wrap each keyword and symbol with a <code>&lt;span&gt;</code> together with certain class names. Through these class names, CSS styles are applied. You can do this process of parsing and wrapping keywords at client-side as well as at build-time. Allow me to show both approaches.</p>
<p>I will be using Prism.js to make code transformations, since it is used in the Eleventy syntax highlighting plugin. You can replace it with Highlight.js without much ado.</p>
<p>To test our changes, in one of your AsciiDoc files, add a sample code block:</p>
<pre class="language-asciidoc" tabindex="0"><code class="language-asciidoc"><span class="token attributes"><span class="token punctuation">[</span><span class="token attr-value">source</span><span class="token punctuation">,</span><span class="token attr-value">html</span><span class="token punctuation">]</span></span><br /><span class="token literal-block"><span class="token punctuation">----</span><br />&lt;body><br />  &lt;p>This is some HTML&lt;/p><br />&lt;/body><br /><span class="token punctuation">----</span></span></code></pre>
<h2 id="1.-client-side-transformation" tabindex="-1">1. Client-side transformation<a class="link link--anchor" href="https://saneef.com/blog/asciidoc-syntax-highlighting/#1.-client-side-transformation" aria-hidden="true" tabindex="-1"></a></h2>
<p>We will load Prism.js JavaScript and CSS files from CDN. In the base layout, usually <code>_includes/layouts/base.njk</code> add these lines:</p>
<pre class="language-diff-html" tabindex="0"><code class="language-diff-html"><span class="token unchanged language-html"><span class="token prefix unchanged"> </span> <span class="token doctype"><span class="token punctuation">&lt;!</span><span class="token doctype-tag">DOCTYPE</span> <span class="token name">html</span><span class="token punctuation">></span></span><br /><span class="token prefix unchanged"> </span> <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>html</span><span class="token punctuation">></span></span><br /><span class="token prefix unchanged"> </span> <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>head</span><span class="token punctuation">></span></span><br /><span class="token prefix unchanged"> </span>   ...<br /></span><span class="token inserted-sign inserted language-html"><span class="token prefix inserted">+</span>   <span class="token comment">&lt;!-- Within &lt;head>, add Prism.js CSS files --></span><br /><span class="token prefix inserted">+</span>   <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>link</span> <span class="token attr-name">rel</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>stylesheet<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>https://cdnjs.cloudflare.com/ajax/libs/prism/1.27.0/themes/prism.min.css<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><br /></span><br /><span class="token inserted-sign inserted language-html"><span class="token prefix inserted">+</span>   <span class="token comment">&lt;!-- Optional, if you want to highlight diff syntax, add this too --></span><br /><span class="token prefix inserted">+</span>   <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>link</span> <span class="token attr-name">rel</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>stylesheet<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>https://cdnjs.cloudflare.com/ajax/libs/prism/1.27.0/plugins/diff-highlight/prism-diff-highlight.min.css<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><br /></span><span class="token unchanged language-html"><span class="token prefix unchanged"> </span> <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>head</span><span class="token punctuation">></span></span><br /><span class="token prefix unchanged"> </span> <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>body</span><span class="token punctuation">></span></span><br /><span class="token prefix unchanged"> </span>   ...<br /></span><br /><span class="token inserted-sign inserted language-html"><span class="token prefix inserted">+</span>   <span class="token comment">&lt;!-- At the end of &lt;body>, add Prism.js JavaScript files --></span><br /><span class="token prefix inserted">+</span>   <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>https://cdnjs.cloudflare.com/ajax/libs/prism/1.27.0/components/prism-core.min.js<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token script"></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">></span></span><br /><span class="token prefix inserted">+</span>   <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>https://cdnjs.cloudflare.com/ajax/libs/prism/1.27.0/plugins/autoloader/prism-autoloader.min.js<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token script"></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">></span></span><br /></span><span class="token unchanged language-html"><span class="token prefix unchanged"> </span> <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>body</span><span class="token punctuation">></span></span><br /><span class="token prefix unchanged"> </span> <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>html</span><span class="token punctuation">></span></span><br /></span></code></pre>
<p>Prism.js provides other themes too. You can replace the default CSS file with a theme based from <a href="https://cdnjs.com/libraries/prism">the CDN</a>. Look for files with path like <code>/themes/prism-{theme-name}.min.css</code>.</p>
<p>That’s all you need to get syntax highlighting. I have created a sample Eleventy setup with AsciiDoc and client-side syntax highlighting <a href="https://github.com/saneef/eleventy-plugin-asciidoc-tester/tree/client-side-syntax-highlighting">on GitHub</a>.</p>
<p>The downside of this approach is that you need JavaScript to see highlighted syntax. You can do these transformations during build time and only require CSS at the client side to view transformed code. Let me explain how you can do that next.</p>
<h2 id="2.-build-time-transformation" tabindex="-1">2. Build-time transformation<a class="link link--anchor" href="https://saneef.com/blog/asciidoc-syntax-highlighting/#2.-build-time-transformation" aria-hidden="true" tabindex="-1"></a></h2>
<p>We will use <a href="https://www.11ty.dev/docs/plugins/syntaxhighlight/">the official Eleventy Syntax Highlight plugin</a> with <a href="https://github.com/saneef/eleventy-plugin-asciidoc">AsciiDoc plugin</a> to transform code blocks during build-time.</p>
<p>First, install syntax highlight plugin using:</p>
<pre class="language-shell" tabindex="0"><code class="language-shell">$ <span class="token function">npm</span> <span class="token function">install</span> <span class="token parameter variable">--save</span> @11ty/eleventy-plugin-syntaxhighlight</code></pre>
<p>Then, create a folder, <code>asciidoc-templates</code>, in the folder as you have <code>.eleventy.js</code>. This allows us to override any <a href="https://docs.asciidoctor.org/asciidoctor.js/latest/extend/converter/template-converter/">default templates</a> with which Asciidoctor.js render nodes.</p>
<p>Open your <code>.eleventy.js</code>, and add <code>template_dir</code> entry in AsciiDoc plugin options:</p>
<pre class="language-diff-js" tabindex="0"><code class="language-diff-js"><span class="token unchanged language-js"><span class="token prefix unchanged"> </span> <span class="token keyword">const</span> eleventyAsciidoc <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"eleventy-plugin-asciidoc"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /></span><br /><span class="token unchanged language-js"><span class="token prefix unchanged"> </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><br /><span class="token prefix unchanged"> </span>   <span class="token comment">//...</span><br /></span><br /><span class="token unchanged language-js"><span class="token prefix unchanged"> </span>   eleventyConfig<span class="token punctuation">.</span><span class="token function">addPlugin</span><span class="token punctuation">(</span>eleventyAsciidoc<span class="token punctuation">,</span> <span class="token punctuation">{</span><br /></span><span class="token inserted-sign inserted language-js"><span class="token prefix inserted">+</span>       <span class="token literal-property property">template_dir</span><span class="token operator">:</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>__dirname<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">/asciidoc-templates</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">,</span><br /></span><span class="token unchanged language-js"><span class="token prefix unchanged"> </span>   <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /></span><br /><span class="token unchanged language-js"><span class="token prefix unchanged"> </span>   <span class="token comment">//...</span><br /><span class="token prefix unchanged"> </span> <span class="token punctuation">}</span><span class="token punctuation">;</span><br /></span></code></pre>
<p>Next, create a file <code>./asciidoc-templates/listing.js</code> and add this code:</p>
<pre class="language-js" tabindex="0"><code class="language-js"><span class="token keyword">const</span> <span class="token punctuation">{</span> pairedShortcode <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"@11ty/eleventy-plugin-syntaxhighlight"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /><span class="token comment">// These are default options from Eleventy Syntax Highlight plugin</span><br /><span class="token keyword">const</span> options <span class="token operator">=</span> <span class="token punctuation">{</span><br />  <span class="token literal-property property">alwaysWrapLineHighlights</span><span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span><br />  <span class="token literal-property property">lineSeparator</span><span class="token operator">:</span> <span class="token string">"&lt;br>"</span><span class="token punctuation">,</span><br />  <span class="token literal-property property">preAttributes</span><span class="token operator">:</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span><br />  <span class="token literal-property property">codeAttributes</span><span class="token operator">:</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span><br /><span class="token punctuation">}</span><span class="token punctuation">;</span><br /><br />module<span class="token punctuation">.</span><span class="token function-variable function">exports</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> node <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br />  <span class="token keyword">const</span> level <span class="token operator">=</span> node<span class="token punctuation">.</span><span class="token function">getLevel</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token number">2</span><span class="token punctuation">;</span><br />  <span class="token keyword">const</span> title <span class="token operator">=</span> node<span class="token punctuation">.</span><span class="token function">getTitle</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br />  <span class="token keyword">const</span> style <span class="token operator">=</span> node<span class="token punctuation">.</span><span class="token function">getStyle</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br />  <span class="token keyword">const</span> content <span class="token operator">=</span> node<span class="token punctuation">.</span><span class="token function">getSource</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br />  <span class="token keyword">let</span> titleEl <span class="token operator">=</span> <span class="token string">""</span><span class="token punctuation">;</span><br />  <span class="token keyword">if</span> <span class="token punctuation">(</span>title<span class="token punctuation">)</span> <span class="token punctuation">{</span><br />    titleEl <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">&lt;h</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>level<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> class="listingblock-title"></span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>title<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">&lt;/h</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>level<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span><br />  <span class="token punctuation">}</span><br /><br />  <span class="token keyword">if</span> <span class="token punctuation">(</span>style <span class="token operator">===</span> <span class="token string">"source"</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br />    <span class="token keyword">const</span> lang <span class="token operator">=</span> node<span class="token punctuation">.</span><span class="token function">getAttribute</span><span class="token punctuation">(</span><span class="token string">"language"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br />    <span class="token keyword">if</span> <span class="token punctuation">(</span>lang <span class="token operator">&amp;&amp;</span> lang <span class="token operator">!==</span> <span class="token string">"text"</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br />      <span class="token keyword">const</span> highlightedContent <span class="token operator">=</span> <span class="token function">pairedShortcode</span><span class="token punctuation">(</span>content<span class="token punctuation">,</span> lang<span class="token punctuation">,</span> <span class="token string">""</span><span class="token punctuation">,</span> options<span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br />      <span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>titleEl<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">\n</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>highlightedContent<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span><br />    <span class="token punctuation">}</span><br />  <span class="token punctuation">}</span><br /><br />  <span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>titleEl<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">\n&lt;pre></span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>content<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">&lt;/pre></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre>
<p>We overrode the default <code>listing</code> node. We are transforming the code blocks during the markup generation of <code>listing</code> node.</p>
<p>Now, only thing left is to add Prism.js CSS file. In your base layout, usually <code>_includes/layouts/base.njk</code> add this line:</p>
<pre class="language-diff-html" tabindex="0"><code class="language-diff-html"><span class="token unchanged language-html"><span class="token prefix unchanged"> </span> <span class="token doctype"><span class="token punctuation">&lt;!</span><span class="token doctype-tag">DOCTYPE</span> <span class="token name">html</span><span class="token punctuation">></span></span><br /><span class="token prefix unchanged"> </span> <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>html</span><span class="token punctuation">></span></span><br /><span class="token prefix unchanged"> </span> <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>head</span><span class="token punctuation">></span></span><br /><span class="token prefix unchanged"> </span>   ...<br /></span><span class="token inserted-sign inserted language-html"><span class="token prefix inserted">+</span>   <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>link</span> <span class="token attr-name">rel</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>stylesheet<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>https://cdnjs.cloudflare.com/ajax/libs/prism/1.27.0/themes/prism.min.css<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><br /></span><span class="token unchanged language-html"><span class="token prefix unchanged"> </span> <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>head</span><span class="token punctuation">></span></span><br /><span class="token prefix unchanged"> </span> <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>body</span><span class="token punctuation">></span></span><br /><span class="token prefix unchanged"> </span>   ...<br /><span class="token prefix unchanged"> </span> <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>body</span><span class="token punctuation">></span></span><br /><span class="token prefix unchanged"> </span> <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>html</span><span class="token punctuation">></span></span><br /></span></code></pre>
<p>If you prefer, you can download that CSS file, and include with your CSS code. It will help you to override any styles to match your site’s styles.</p>
<p>With that, you have build-time syntax rendering!</p>
<p>You can find the sample project with build-time syntax highlighting <a href="https://github.com/saneef/eleventy-plugin-asciidoc-tester/">on GitHub</a>.</p>

          


          ]]></content
        >
      </entry><entry>
        <title>Fix dates on Eleventy RSS feeds</title>
        <link href="https://saneef.com/blog/fix-dates-on-eleventy-rss-feeds/" />
        <published>2021-08-20T00:00:00Z</published>
        <updated
          >2024-02-09T22:20:29Z</updated
        >
        <id>https://saneef.com/blog/fix-dates-on-eleventy-rss-feeds/</id>
        <content type="html"
          ><![CDATA[<p>The official way to generate RSS feed in Eleventy is to use filters from <a href="https://github.com/11ty/eleventy-plugin-rss"><code>eleventy-plugin-rss</code></a> plugin. The <a href="https://www.11ty.dev/docs/plugins/rss/#sample-atom-feed-template">sample RSS template</a> from the plugin’s documentation is a good starter. I use the same code to generate RSS feeds on my website.</p>
<p>The RSS feeds made by the official method has one problem, <code>&lt;updated&gt;</code> fields use <code>date</code> from the page object. The <code>date</code> don’t change when you make any changes to the content. RSS feed readers rely on <code>&lt;updated&gt;</code> fields to pick up any changes in the post since it is originally published.</p>
<figure class="wide">
  <img src="https://saneef.com/images/feedbin.com-post-diff.png" alt="Screengrab of feedbin.com showing changes since original" />
  <figcaption>The RSS reader, <a href="https://feedbin.com/">Feedbin.com</a> highlights changes since original.</figcaption>
</figure>
<p>The Eleventy provides <code>Last Modified</code> function for the <code>date</code> field, but you’ll lose out on the fixed creation date or published date. Moreover, last modified date is <a href="https://www.11ty.dev/docs/dates/#collections-out-of-order-when-you-run-eleventy-on-your-server">unreliable like creation date</a> on CI environments.</p>
<h2 id="git-commit-time" tabindex="-1">Git commit time<a class="link link--anchor" href="https://saneef.com/blog/fix-dates-on-eleventy-rss-feeds/#git-commit-time" aria-hidden="true" tabindex="-1"></a></h2>
<p>The creator of the Eleventy, Zach, suggests <a href="https://github.com/11ty/eleventy/issues/142">Git commit time</a> as a reliable time to use as modified or last updated time. It will stay the same across machines. This is the approach I’m going to use to fix the dates on the RSS feed.</p>
<p>I have created a plugin <a href="https://github.com/saneef/eleventy-plugin-git-commit-date"><code>eleventy-plugin-git-commit-date</code></a>, to get Git commit time from a file path. The plugin also provide a template filter to get the latest Git commit time from a collection.</p>
<h2 id="rss-feed-with-git-commit-time" tabindex="-1">RSS feed with Git commit time<a class="link link--anchor" href="https://saneef.com/blog/fix-dates-on-eleventy-rss-feeds/#rss-feed-with-git-commit-time" aria-hidden="true" tabindex="-1"></a></h2>
<p>First, you need to install the plugin, <code>npm install --save eleventy-plugin-git-commit-date</code>. This plugin is a companion to the official <a href="https://github.com/11ty/eleventy-plugin-rss"><code>eleventy-plugin-rss</code></a> plugin. So, if you haven’t installed RSS plugin, you have to install and enable that too.</p>
<p>Next, enable the plugin in <code>.eleventy.js</code>.</p>
<pre class="language-js" tabindex="0"><code class="language-js"><span class="token comment">// .eleventy.js</span><br /><span class="token keyword">const</span> pluginGitCommitDate <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"eleventy-plugin-git-commit-date"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br />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><br />  eleventyConfig<span class="token punctuation">.</span><span class="token function">addPlugin</span><span class="token punctuation">(</span>pluginGitCommitDate<span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre>
<p>Now, you should be able to access filters <code>getGitCommitDateFromPath</code> and <code>getCollectionNewestGitCommitDate</code> in your templates.</p>
<p>Firstly, let’s create a data file, <code>src/_data/config.js</code> with these contents.</p>
<pre class="language-js" tabindex="0"><code class="language-js"><span class="token comment">// src/_data/config.js</span><br />module<span class="token punctuation">.</span>exports <span class="token operator">=</span> <span class="token punctuation">{</span><br />  <span class="token literal-property property">now</span><span class="token operator">:</span> <span class="token keyword">new</span> <span class="token class-name">Date</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span><br /><span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre>
<p>The data <code>now</code> will have the time at which you run <code>eleventy</code>. This will come handy later.</p>
<p>Now, update your feed template using filters from the plugin</p>
<pre class="language-diff-xml" tabindex="0"><code class="language-diff-xml"><span class="token unchanged language-xml"><span class="token prefix unchanged"> </span> ---json<br /><span class="token prefix unchanged"> </span> {<br /><span class="token prefix unchanged"> </span>   "permalink": "feed.xml",<br /><span class="token prefix unchanged"> </span>   "eleventyExcludeFromCollections": true,<br /><span class="token prefix unchanged"> </span>   "metadata": {<br /><span class="token prefix unchanged"> </span>     "title": "My Blog about Boats",<br /><span class="token prefix unchanged"> </span>     "subtitle": "I am writing about my experiences as a naval navel-gazer.",<br /><span class="token prefix unchanged"> </span>     "url": "https://example.com/",<br /><span class="token prefix unchanged"> </span>     "feedUrl": "https://example.com/feed.xml",<br /><span class="token prefix unchanged"> </span>     "author": {<br /><span class="token prefix unchanged"> </span>       "name": "Boaty McBoatFace",<br /><span class="token prefix unchanged"> </span>       "email": "me@example.com"<br /><span class="token prefix unchanged"> </span>     }<br /><span class="token prefix unchanged"> </span>   }<br /><span class="token prefix unchanged"> </span> }<br /><span class="token prefix unchanged"> </span> ---<br /><span class="token prefix unchanged"> </span> <span class="token prolog">&lt;?xml version="1.0" encoding="utf-8"?></span><br /><span class="token prefix unchanged"> </span> <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>feed</span> <span class="token attr-name">xmlns</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>http://www.w3.org/2005/Atom<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /><span class="token prefix unchanged"> </span>   <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>title</span><span class="token punctuation">></span></span>{{ metadata.title }}<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>title</span><span class="token punctuation">></span></span><br /><span class="token prefix unchanged"> </span>   <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>subtitle</span><span class="token punctuation">></span></span>{{ metadata.subtitle }}<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>subtitle</span><span class="token punctuation">></span></span><br /><span class="token prefix unchanged"> </span>   <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>link</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>{{ metadata.feedUrl }}<span class="token punctuation">"</span></span> <span class="token attr-name">rel</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>self<span class="token punctuation">"</span></span><span class="token punctuation">/></span></span><br /><span class="token prefix unchanged"> </span>   <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>link</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>{{ metadata.url }}<span class="token punctuation">"</span></span><span class="token punctuation">/></span></span><br /></span><span class="token deleted-sign deleted language-xml"><span class="token prefix deleted">-</span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>updated</span><span class="token punctuation">></span></span>{{ collections.posts | getNewestCollectionItemDate | dateToRfc3339 }}<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>updated</span><span class="token punctuation">></span></span><br /></span><span class="token inserted-sign inserted language-xml"><span class="token prefix inserted">+</span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>updated</span><span class="token punctuation">></span></span>{{ collections.posts | getCollectionNewestGitCommitDate | default(config.now) | dateToRfc3339 }}<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>updated</span><span class="token punctuation">></span></span><br /></span><span class="token unchanged language-xml"><span class="token prefix unchanged"> </span>   <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>id</span><span class="token punctuation">></span></span>{{ metadata.url }}<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>id</span><span class="token punctuation">></span></span><br /><span class="token prefix unchanged"> </span>   <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>author</span><span class="token punctuation">></span></span><br /><span class="token prefix unchanged"> </span>     <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>name</span><span class="token punctuation">></span></span>{{ metadata.author.name }}<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>name</span><span class="token punctuation">></span></span><br /><span class="token prefix unchanged"> </span>     <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>email</span><span class="token punctuation">></span></span>{{ metadata.author.email }}<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>email</span><span class="token punctuation">></span></span><br /><span class="token prefix unchanged"> </span>   <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>author</span><span class="token punctuation">></span></span><br /><span class="token prefix unchanged"> </span>   {%- for post in collections.posts %}<br /><span class="token prefix unchanged"> </span>   {% set absolutePostUrl %}{{ post.url | absoluteUrl(metadata.url) }}{% endset %}<br /><span class="token prefix unchanged"> </span>   <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>entry</span><span class="token punctuation">></span></span><br /><span class="token prefix unchanged"> </span>     <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>title</span><span class="token punctuation">></span></span>{{ post.data.title }}<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>title</span><span class="token punctuation">></span></span><br /><span class="token prefix unchanged"> </span>     <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>link</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>{{ absolutePostUrl }}<span class="token punctuation">"</span></span><span class="token punctuation">/></span></span><br /></span><span class="token deleted-sign deleted language-xml"><span class="token prefix deleted">-</span>      <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>updated</span><span class="token punctuation">></span></span>{{ post.date | dateToRfc3339 }}<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>updated</span><span class="token punctuation">></span></span><br /></span><span class="token inserted-sign inserted language-xml"><span class="token prefix inserted">+</span>      <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>updated</span><span class="token punctuation">></span></span>{{ post.inputPath | getGitCommitDateFromPath | default(post.date) | dateToRfc3339 }}<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>updated</span><span class="token punctuation">></span></span><br /></span><span class="token unchanged language-xml"><span class="token prefix unchanged"> </span>     <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>id</span><span class="token punctuation">></span></span>{{ absolutePostUrl }}<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>id</span><span class="token punctuation">></span></span><br /><span class="token prefix unchanged"> </span>     <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>content</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>html<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>{{ post.templateContent | htmlToAbsoluteUrls(absolutePostUrl) }}<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>content</span><span class="token punctuation">></span></span><br /><span class="token prefix unchanged"> </span>   <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>entry</span><span class="token punctuation">></span></span><br /><span class="token prefix unchanged"> </span>   {%- endfor %}<br /><span class="token prefix unchanged"> </span> <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>feed</span><span class="token punctuation">></span></span><br /></span></code></pre>
<p>You need to update the two <code>&lt;updated&gt;</code> fields. The first <code>&lt;updated&gt;</code> is for the whole feed. Here, we need to populate the Git commit date from the recently committed file from the collection. <code>getCollectionNewestGitCommitDate</code> returns Git commit date of recently committed file. In case, you haven’t committed any posts to Git, this filter will return <code>undefined</code>. The <a href="https://mozilla.github.io/nunjucks/templating.html#default-value-default-boolean"><code>default</code></a> will return the provided value in case the value before the filter is <code>undefined</code>. When prior filter to <code>default(config.now)</code> return <code>undefined</code> will return <code>config.now</code> which is the current time. Lastly, we use <code>dateToRfc3339</code> from Eleventy RSS plugin to format the date.</p>
<p>The second <code>&lt;updated&gt;</code> field is for each post. In case the current post file is not committed to Git, the <code>getGitCommitDateFromPath</code> returns <code>undefined</code>. So, to handle that case, we are using <code>default(post.date)</code> to populate with date from the file or front-matter.</p>
<p>That’s all you need to do to fix dates in the RSS feeds.</p>

          


          ]]></content
        >
      </entry><entry>
        <title>Enhance hashtag links with CSS</title>
        <link href="https://saneef.com/blog/hashtag-links/" />
        <published>2021-08-18T00:00:00Z</published>
        <updated
          >2023-12-20T04:53:48Z</updated
        >
        <id>https://saneef.com/blog/hashtag-links/</id>
        <content type="html"
          ><![CDATA[<p>Any element in an HTML document with an <code>id</code> attribute can be referenced in the URL using a <code>#</code> symbol followed by the <code>id</code> of the element. The part after the <code>#</code> is officially called <a href="https://url.spec.whatwg.org/#concept-url-fragment">fragment of the URL</a>. Unofficially, it is called hashtag.</p>
<p>The browser uses the part before the fragment to load the page, then uses the fragment to bring the <em>target element</em> into the view. When a user inputs a URL <code>https://example.com/#usage</code> into the address bar of a browser, the browser loads the page, then brings the element with <code>id=&quot;usage&quot;</code> in to the view. Or, as many say, <em>the browser scrolls to the element</em>.</p>
<p>We can use only the fragment to reference elements within the current page. When a user clicks on a link, <code>&lt;a href=&quot;#getting-started&quot;&gt;Getting started&lt;/a&gt;</code>, the browser scrolls to the element with <code>id=getting-started</code>. You’ll find this pattern used in table of contents, footnotes, and other internal references in the HTML documents.</p>
<p>Even the browsers from the early days of the web supports URL fragments. The URL fragment works without any CSS or JavaScript. We could sprinkle some CSS to improve the experience.</p>
<h2 id="improve-scroll-spacing" tabindex="-1">Improve scroll spacing<a class="link link--anchor" href="https://saneef.com/blog/hashtag-links/#improve-scroll-spacing" aria-hidden="true" tabindex="-1"></a></h2>
<p>When the browser scrolls to the target element, it tries to keep the element towards the top of the viewport, or the container element. There might be cases you might want to leave a bit of room between the top edge of the viewport and target element. If you have any fixed elements (like navigation or header) the spacing is a must.</p>
<p>You can use CSS property <a href="http://developer.mozilla.org/en-US/docs/Web/CSS/scroll-margin"><code>scroll-margin</code></a> to set scroll offsets. The most common scenario is to set offset for vertical scrolling. We can use <a href="http://developer.mozilla.org/en-US/docs/Web/CSS/scroll-margin-top"><code>scroll-margin-top</code></a> to set the top offset.</p>
<figure class="wide">
  <div class="[ aspect-ratio aspect-ratio--16-9 ][ bg-em ]">
    <iframe height="300" style="width: 100%;" scrolling="no" title="" src="https://codepen.io/saneef/embed/poPmmqr?default-tab=css%2Cresult" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
      See the Pen <a href="https://codepen.io/saneef/pen/poPmmqr">
      </a> by Saneef Ansari (<a href="https://codepen.io/saneef">@saneef</a>)
      on <a href="https://codepen.io/">CodePen</a>.
    </iframe>
  </div>
  <figcaption>The navigation is fixed to top and covers the content. The target element is positioned below the navigation using <code>scroll-margin-top</code> when hashtag links are clicked.</figcaption>
</figure>
<h2 id="smoothen-scroll" tabindex="-1">Smoothen scroll<a class="link link--anchor" href="https://saneef.com/blog/hashtag-links/#smoothen-scroll" aria-hidden="true" tabindex="-1"></a></h2>
<p>The default behaviour by the browser when a user clicks on a fragment URL is to instantaneously scroll to the target element. If you prefer to scroll smoothly to the target element, you can use <a href="http://developer.mozilla.org/en-US/docs/Web/CSS/scroll-behavior"><code>scroll-behavior: smooth</code></a>. Usually, this is set on the document, <code>html</code>. If you want to change scroll behaviour within a child container, you can set the <code>scroll-behavior</code> property of that element.</p>
<p>⚠️ <span class="type-s"><code>scroll-behavior</code> is not yet supported in Safari.</span></p>
<figure class="wide">
  <div class="[ aspect-ratio aspect-ratio--16-9 ][ bg-em ]">
    <iframe height="300" style="width: 100%;" scrolling="no" title="Hashtag links: Improve scroll spacing" src="https://codepen.io/saneef/embed/BaRegjp?default-tab=css%2Cresult" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
      See the Pen <a href="https://codepen.io/saneef/pen/BaRegjp">
      Hashtag links: Improve scroll spacing</a> by Saneef Ansari (<a href="https://codepen.io/saneef">@saneef</a>)
      on <a href="https://codepen.io/">CodePen</a>.
    </iframe>
  </div>
</figure>
<h2 id="style-the-target-element" tabindex="-1">Style the target element<a class="link link--anchor" href="https://saneef.com/blog/hashtag-links/#style-the-target-element" aria-hidden="true" tabindex="-1"></a></h2>
<p>Every so often, you like to highlight the target element. CSS provides the <a href="http://developer.mozilla.org/en-US/docs/Web/CSS/:target"><code>:target</code></a> pseudo selector, just for that. This comes handy when linking a heading from a table of contents, or linking to a footnote.</p>
<figure class="wide">
  <div class="[ aspect-ratio aspect-ratio--16-9 ][ bg-em ]">
    <iframe height="300" style="width: 100%;" scrolling="no" title="Hashtag links: Style the target element" src="https://codepen.io/saneef/embed/PomvrbW?default-tab=css%2Cresult" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
      See the Pen <a href="https://codepen.io/saneef/pen/PomvrbW">
      Hashtag links: Style the target element</a> by Saneef Ansari (<a href="https://codepen.io/saneef">@saneef</a>)
      on <a href="https://codepen.io/">CodePen</a>.
    </iframe>
  </div>
</figure>

          


          ]]></content
        >
      </entry><entry>
        <title>Language sensitive list formatting in JavaScript</title>
        <link href="https://saneef.com/blog/language-sensitive-list/" />
        <published>2021-08-11T00:00:00Z</published>
        <updated
          >2024-02-09T07:40:14Z</updated
        >
        <id>https://saneef.com/blog/language-sensitive-list/</id>
        <content type="html"
          ><![CDATA[<p>Occasionally, we have to generate comma separated lists like ‘Alice, Bob and Carol’ and ‘Alice, Bob or Carol’ from arrays. Instead of writing duct tape code using <code>Array.join()</code> or third-party libraries, we can use native <a href="http://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/ListFormat/ListFormat"><code>Intl.ListFormat</code></a>. It is part of the <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl">ECMAScript Internationalization API</a>.</p>
<p>The <code>Intl.ListFormat</code> constructor accepts two parameters, <code>locale</code> and <code>options</code>, and returns an object. Use the <code>locale</code> to specify the language. Use <code>options</code> to set two key parameters, <code>type</code> and <code>style</code>. To generate and-based lists use <code>type: conjunction</code> and for or-based lists use <code>type: disjunction</code>. The possible values for <code>style</code> are <code>long</code> and <code>short</code>. In English locale, <code>style: long</code> with <code>type: conjunction</code> generates a list with <code>and</code>, whereas <code>style: short</code> generates a list with <code>&amp;</code>.</p>
<p>The returned object exposes <code>format()</code> with which we can convert arrays to lists.</p>
<h2>List with ‘and’ (conjunction)</h2>
<!-- prettier-ignore-start -->
<pre class="language-js" tabindex="0"><code class="language-js"><span class="token keyword">const</span> names <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token string">"Alice"</span><span class="token punctuation">,</span> <span class="token string">"Bob"</span><span class="token punctuation">,</span> <span class="token string">"Carol"</span><span class="token punctuation">,</span> <span class="token string">"Dan"</span><span class="token punctuation">]</span><span class="token punctuation">;</span><br /><br /><span class="token keyword">const</span> formatterEnLong <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Intl<span class="token punctuation">.</span>ListFormat</span><span class="token punctuation">(</span><span class="token string">"en"</span><span class="token punctuation">,</span> <span class="token punctuation">{</span><br />  <span class="token literal-property property">style</span><span class="token operator">:</span> <span class="token string">"long"</span><span class="token punctuation">,</span><br />  <span class="token literal-property property">type</span><span class="token operator">:</span> <span class="token string">"conjunction"</span><span class="token punctuation">,</span><br /><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br />console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>formatterEnLong<span class="token punctuation">.</span><span class="token function">format</span><span class="token punctuation">(</span>names<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token comment">// Output: Alice, Bob, Carol, and Dan</span><br /><br /><span class="token keyword">const</span> formatterEnShort <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Intl<span class="token punctuation">.</span>ListFormat</span><span class="token punctuation">(</span><span class="token string">"en"</span><span class="token punctuation">,</span> <span class="token punctuation">{</span><br />  <span class="token literal-property property">style</span><span class="token operator">:</span> <span class="token string">"short"</span><span class="token punctuation">,</span><br />  <span class="token literal-property property">type</span><span class="token operator">:</span> <span class="token string">"conjunction"</span><span class="token punctuation">,</span><br /><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br />console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>formatterEnShort<span class="token punctuation">.</span><span class="token function">format</span><span class="token punctuation">(</span>names<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token comment">// Output: Alice, Bob, Carol, &amp; Dan</span><br /><br /><span class="token keyword">const</span> formatterFr <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Intl<span class="token punctuation">.</span>ListFormat</span><span class="token punctuation">(</span><span class="token string">"fr"</span><span class="token punctuation">,</span> <span class="token punctuation">{</span><br />  <span class="token literal-property property">style</span><span class="token operator">:</span> <span class="token string">"long"</span><span class="token punctuation">,</span><br />  <span class="token literal-property property">type</span><span class="token operator">:</span> <span class="token string">"conjunction"</span><span class="token punctuation">,</span><br /><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br />console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>formatterFr<span class="token punctuation">.</span><span class="token function">format</span><span class="token punctuation">(</span>names<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token comment">// Output: Alice, Bob, Carol et Dan</span></code></pre>
<!-- prettier-ignore-end -->
<h2 id="list-with-%E2%80%98or%E2%80%99-(disjunction)" tabindex="-1">List with ‘or’ (disjunction)<a class="link link--anchor" href="https://saneef.com/blog/language-sensitive-list/#list-with-%E2%80%98or%E2%80%99-(disjunction)" aria-hidden="true" tabindex="-1"></a></h2>
<!-- prettier-ignore-start -->
<pre class="language-js" tabindex="0"><code class="language-js"><span class="token keyword">const</span> names <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token string">"Alice"</span><span class="token punctuation">,</span> <span class="token string">"Bob"</span><span class="token punctuation">,</span> <span class="token string">"Carol"</span><span class="token punctuation">,</span> <span class="token string">"Dan"</span><span class="token punctuation">]</span><span class="token punctuation">;</span><br /><br /><span class="token keyword">const</span> formatterEn <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Intl<span class="token punctuation">.</span>ListFormat</span><span class="token punctuation">(</span><span class="token string">"en"</span><span class="token punctuation">,</span> <span class="token punctuation">{</span><br />  <span class="token literal-property property">style</span><span class="token operator">:</span> <span class="token string">"long"</span><span class="token punctuation">,</span><br />  <span class="token literal-property property">type</span><span class="token operator">:</span> <span class="token string">"disjunction"</span><span class="token punctuation">,</span><br /><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br />console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>formatterEn<span class="token punctuation">.</span><span class="token function">format</span><span class="token punctuation">(</span>names<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token comment">// Output: Alice, Bob, Carol, or Dan</span><br /><br /><span class="token keyword">const</span> formatterFr <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Intl<span class="token punctuation">.</span>ListFormat</span><span class="token punctuation">(</span><span class="token string">"fr"</span><span class="token punctuation">,</span> <span class="token punctuation">{</span><br />  <span class="token literal-property property">style</span><span class="token operator">:</span> <span class="token string">"long"</span><span class="token punctuation">,</span><br />  <span class="token literal-property property">type</span><span class="token operator">:</span> <span class="token string">"disjunction"</span><span class="token punctuation">,</span><br /><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br />console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>formatterFr<span class="token punctuation">.</span><span class="token function">format</span><span class="token punctuation">(</span>names<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token comment">// Output: Alice, Bob, Carol ou Dan</span></code></pre>
<!-- prettier-ignore-end -->
<p><code>Intl.ListFormat</code> is supported in all <a href="https://caniuse.com/mdn-javascript_builtins_intl_listformat_format">modern browsers</a> and Node.js <code>v13+</code>.</p>

          


          ]]></content
        >
      </entry><entry>
        <title>Styling &lt;code&gt; within an anchor element</title>
        <link href="https://saneef.com/blog/styling-code-within-an-anchor/" />
        <published>2021-06-17T00:00:00Z</published>
        <updated
          >2024-02-09T07:40:14Z</updated
        >
        <id>https://saneef.com/blog/styling-code-within-an-anchor/</id>
        <content type="html"
          ><![CDATA[<p>I faced a snag in one of my recent projects, while styling a <code>&lt;code&gt;</code> element within a <code>&lt;a&gt;</code> element. The project uses <a href="https://www.markdownguide.org/">Markdown</a> to write contents, and uses <a href="http://11ty.dev/">Eleventy</a> to render contents into HTML pages.</p>
<p>In Markdown, you write the code within an anchor like:</p>
<pre class="language-md" tabindex="0"><code class="language-md"><span class="token url">[<span class="token content"><span class="token code-snippet code keyword">`box-sizing`</span></span>](<span class="token url">https://developer.mozilla.org/en-US/docs/Web/CSS/box-sizing</span>)</span></code></pre>
<p>…and, it generates HTML like:</p>
<pre class="language-html" tabindex="0"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</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>https://developer.mozilla.org/en-US/docs/Web/CSS/box-sizing<span class="token punctuation">"</span></span><br />  <span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>code</span><span class="token punctuation">></span></span>box-sizing<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>code</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><br /><span class="token punctuation">></span></span></code></pre>
<p>We were styling all <code>&lt;a&gt;</code> elements with an underline, and all <code>code</code> elements with a light background colour. When putting them together, we didn’t want the <code>code</code> elements within <code>&lt;a&gt;</code> to have an underline, instead a border to indicate that it is clickable. Seems straightforward and we wrote the code:</p>
<!-- prettier-ignore-start -->
<style>

.fail-demo-prose a {
  color: rgb(139, 92, 246);
  text-decoration: underline;
}

.fail-demo-prose a:hover,
.fail-demo-prose a:active,
.fail-demo-prose a:focus {
  text-decoration: none;
}

.fail-demo-prose a code {
  padding: 0.0625em 0.25em;
  border: 1px solid;
  background: rgb(237, 233, 254);

  text-decoration: none; /* 😢 This don't work! */
}

.fail-demo-prose a:hover code,
.fail-demo-prose a:active code,
.fail-demo-prose a:focus code {
  color: rgb(237, 233, 254);
  background-color: rgb(139, 92, 246);
  border-color: rgb(139, 92, 246);
}

/* Presentational styles */
.fail-demo-prose > * + * {
  margin-top: 1em;
}

.fail-demo-prose code {
  text-shadow: none;
}

</style>
<details class="code-demo__collapse" open="true">
  <summary class="code-demo__collapse-title">CSS</summary>
  <div class="code-demo__code">
    <pre class="language-css" tabindex="0"><code class="language-css"><span class="token selector">.fail-demo-prose a</span> <span class="token punctuation">{</span><br />  <span class="token property">color</span><span class="token punctuation">:</span> <span class="token function">rgb</span><span class="token punctuation">(</span>139<span class="token punctuation">,</span> 92<span class="token punctuation">,</span> 246<span class="token punctuation">)</span><span class="token punctuation">;</span><br />  <span class="token property">text-decoration</span><span class="token punctuation">:</span> underline<span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token selector">.fail-demo-prose a:hover,<br />.fail-demo-prose a:active,<br />.fail-demo-prose a:focus</span> <span class="token punctuation">{</span><br />  <span class="token property">text-decoration</span><span class="token punctuation">:</span> none<span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token selector">.fail-demo-prose a code</span> <span class="token punctuation">{</span><br />  <span class="token property">padding</span><span class="token punctuation">:</span> 0.0625em 0.25em<span class="token punctuation">;</span><br />  <span class="token property">border</span><span class="token punctuation">:</span> 1px solid<span class="token punctuation">;</span><br />  <span class="token property">background</span><span class="token punctuation">:</span> <span class="token function">rgb</span><span class="token punctuation">(</span>237<span class="token punctuation">,</span> 233<span class="token punctuation">,</span> 254<span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br />  <span class="token property">text-decoration</span><span class="token punctuation">:</span> none<span class="token punctuation">;</span> <span class="token comment">/* 😢 This don't work! */</span><br /><span class="token punctuation">}</span><br /><br /><span class="token selector">.fail-demo-prose a:hover code,<br />.fail-demo-prose a:active code,<br />.fail-demo-prose a:focus code</span> <span class="token punctuation">{</span><br />  <span class="token property">color</span><span class="token punctuation">:</span> <span class="token function">rgb</span><span class="token punctuation">(</span>237<span class="token punctuation">,</span> 233<span class="token punctuation">,</span> 254<span class="token punctuation">)</span><span class="token punctuation">;</span><br />  <span class="token property">background-color</span><span class="token punctuation">:</span> <span class="token function">rgb</span><span class="token punctuation">(</span>139<span class="token punctuation">,</span> 92<span class="token punctuation">,</span> 246<span class="token punctuation">)</span><span class="token punctuation">;</span><br />  <span class="token property">border-color</span><span class="token punctuation">:</span> <span class="token function">rgb</span><span class="token punctuation">(</span>139<span class="token punctuation">,</span> 92<span class="token punctuation">,</span> 246<span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token comment">/* Presentational styles */</span><br /><span class="token selector">.fail-demo-prose > * + *</span> <span class="token punctuation">{</span><br />  <span class="token property">margin-top</span><span class="token punctuation">:</span> 1em<span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token selector">.fail-demo-prose code</span> <span class="token punctuation">{</span><br />  <span class="token property">text-shadow</span><span class="token punctuation">:</span> none<span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
  </div>
</details>
<details class="code-demo__collapse">
  <summary class="code-demo__collapse-title">HTML</summary>
  <div class="code-demo__code">
    <pre class="language-html" tabindex="0"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</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>fail-demo-prose<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br />  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</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>#<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>A regular link<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">></span></span><br />  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</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>#<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>code</span><span class="token punctuation">></span></span>'code' element within a link<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>code</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span> 😢<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span></code></pre>
  </div>
</details>
<details class="code-demo__collapse" open="true">
  <summary class="code-demo__collapse-title">Preview</summary>
  <div class="code-demo__output code-demo__output--no-resize">
<div class="fail-demo-prose">
  <p><a href="https://saneef.com/blog/styling-code-within-an-anchor/#">A regular link</a></p>
  <p><a href="https://saneef.com/blog/styling-code-within-an-anchor/#"><code>'code' element within a link</code></a> 😢</p>
</div>
  </div>
</details>
<!-- prettier-ignore-end -->
<p>But, the underline on the <code>code</code> is still there! Bummer.</p>
<p>That’s when we learned the <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/text-decoration"><code>text-decoration</code></a> is applied to all descendant inline text elements. And, styling child elements with <code>text-decoration: none</code> would not cause any change.</p>
<p>And we figured the fix is to make the <code>&lt;code&gt;</code> an <code>inline-block</code>! If you like to know why this works, <a href="https://www.w3.org/TR/CSS21/text.html#lining-striking-props">go over the CSS spec</a>.</p>
<!-- prettier-ignore-start -->
<style>

.demo-prose a {
  color: rgb(139, 92, 246);
  text-decoration: underline;
}

.demo-prose a:hover,
.demo-prose a:active,
.demo-prose a:focus {
  text-decoration: none;
}

.demo-prose a code {
  display: inline-block; /* 🔨 Whack! */
  padding: 0.0625em 0.25em;
  border: 1px solid;
  background: rgb(237, 233, 254);

  /* text-decoration: none; */ /* 👀 This is not required any more. */
}

.demo-prose a:hover code,
.demo-prose a:active code,
.demo-prose a:focus code {
  color: rgb(237, 233, 254);
  background-color: rgb(139, 92, 246);
  border-color: rgb(139, 92, 246);
}

/* Presentational styles */
.demo-prose > * + * {
  margin-top: 1em;
}

.demo-prose code {
  text-shadow: none;
}

</style>
<details class="code-demo__collapse" open="true">
  <summary class="code-demo__collapse-title">CSS</summary>
  <div class="code-demo__code">
    <pre class="language-css" tabindex="0"><code class="language-css"><span class="token selector">.demo-prose a</span> <span class="token punctuation">{</span><br />  <span class="token property">color</span><span class="token punctuation">:</span> <span class="token function">rgb</span><span class="token punctuation">(</span>139<span class="token punctuation">,</span> 92<span class="token punctuation">,</span> 246<span class="token punctuation">)</span><span class="token punctuation">;</span><br />  <span class="token property">text-decoration</span><span class="token punctuation">:</span> underline<span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token selector">.demo-prose a:hover,<br />.demo-prose a:active,<br />.demo-prose a:focus</span> <span class="token punctuation">{</span><br />  <span class="token property">text-decoration</span><span class="token punctuation">:</span> none<span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token selector">.demo-prose a code</span> <span class="token punctuation">{</span><br />  <span class="token property">display</span><span class="token punctuation">:</span> inline-block<span class="token punctuation">;</span> <span class="token comment">/* 🔨 Whack! */</span><br />  <span class="token property">padding</span><span class="token punctuation">:</span> 0.0625em 0.25em<span class="token punctuation">;</span><br />  <span class="token property">border</span><span class="token punctuation">:</span> 1px solid<span class="token punctuation">;</span><br />  <span class="token property">background</span><span class="token punctuation">:</span> <span class="token function">rgb</span><span class="token punctuation">(</span>237<span class="token punctuation">,</span> 233<span class="token punctuation">,</span> 254<span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br />  <span class="token comment">/* text-decoration: none; */</span> <span class="token comment">/* 👀 This is not required any more. */</span><br /><span class="token punctuation">}</span><br /><br /><span class="token selector">.demo-prose a:hover code,<br />.demo-prose a:active code,<br />.demo-prose a:focus code</span> <span class="token punctuation">{</span><br />  <span class="token property">color</span><span class="token punctuation">:</span> <span class="token function">rgb</span><span class="token punctuation">(</span>237<span class="token punctuation">,</span> 233<span class="token punctuation">,</span> 254<span class="token punctuation">)</span><span class="token punctuation">;</span><br />  <span class="token property">background-color</span><span class="token punctuation">:</span> <span class="token function">rgb</span><span class="token punctuation">(</span>139<span class="token punctuation">,</span> 92<span class="token punctuation">,</span> 246<span class="token punctuation">)</span><span class="token punctuation">;</span><br />  <span class="token property">border-color</span><span class="token punctuation">:</span> <span class="token function">rgb</span><span class="token punctuation">(</span>139<span class="token punctuation">,</span> 92<span class="token punctuation">,</span> 246<span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token comment">/* Presentational styles */</span><br /><span class="token selector">.demo-prose > * + *</span> <span class="token punctuation">{</span><br />  <span class="token property">margin-top</span><span class="token punctuation">:</span> 1em<span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token selector">.demo-prose code</span> <span class="token punctuation">{</span><br />  <span class="token property">text-shadow</span><span class="token punctuation">:</span> none<span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
  </div>
</details>
<details class="code-demo__collapse">
  <summary class="code-demo__collapse-title">HTML</summary>
  <div class="code-demo__code">
    <pre class="language-html" tabindex="0"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</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>demo-prose<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br />  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</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>#<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>A regular link<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">></span></span><br />  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</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>#<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>code</span><span class="token punctuation">></span></span>'code' element within a link<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>code</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span> 🎉<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span></code></pre>
  </div>
</details>
<details class="code-demo__collapse" open="true">
  <summary class="code-demo__collapse-title">Preview</summary>
  <div class="code-demo__output code-demo__output--no-resize">
<div class="demo-prose">
  <p><a href="https://saneef.com/blog/styling-code-within-an-anchor/#">A regular link</a></p>
  <p><a href="https://saneef.com/blog/styling-code-within-an-anchor/#"><code>'code' element within a link</code></a> 🎉</p>
</div>
  </div>
</details>
  <form action="https://codepen.io/pen/define" method="POST" target="_blank">
        <input type="hidden" name="data" value='{"title":"Saneef.com - Styling <code> within an anchor element","description":"Generated from: https://saneef.com/blog/styling-code-within-an-anchor/","tags":["saneef.com"],"editors":"110","layout":"left","html":"<!-- Saneef.com - Styling <code> within an anchor element\nGenerated from: https://saneef.com/blog/styling-code-within-an-anchor/ -->\n<div class=\"demo-prose\">\n  <p><a href=\"#\">A regular link</a></p>\n  <p><a href=\"#\"><code>&apos;code&apos; element within a link</code></a> 🎉</p>\n</div>\n","html_pre_processor":"none","css":"/* Box sizing rules */\n*,\n*::before,\n*::after {\n  box-sizing: border-box;\n}\n\n/* Remove default margin */\nbody,\nh1,\nh2,\nh3,\nh4,\np {\n  margin: 0;\n}\n\n/* Set core body defaults */\nbody {\n  min-height: 100vh;\n  text-rendering: optimizeSpeed;\n  line-height: 1.5;\n  font-family: system-ui, sans-serif;\n}\n\n/* Make images easier to work with */\nimg {\n  display: block;\n  max-width: 100%;\n}\n\n/***\n 🟣 Saneef.com Demo Styles\n */\n\n.demo-prose a {\n  color: rgb(139, 92, 246);\n  text-decoration: underline;\n}\n\n.demo-prose a:hover,\n.demo-prose a:active,\n.demo-prose a:focus {\n  text-decoration: none;\n}\n\n.demo-prose a code {\n  display: inline-block; /* 🔨 Whack! */\n  padding: 0.0625em 0.25em;\n  border: 1px solid;\n  background: rgb(237, 233, 254);\n\n  /* text-decoration: none; */ /* 👀 This is not required any more. */\n}\n\n.demo-prose a:hover code,\n.demo-prose a:active code,\n.demo-prose a:focus code {\n  color: rgb(237, 233, 254);\n  background-color: rgb(139, 92, 246);\n  border-color: rgb(139, 92, 246);\n}\n\n/* Presentational styles */\n.demo-prose > * + * {\n  margin-top: 1em;\n}\n\n.demo-prose code {\n  text-shadow: none;\n}\n","css_pre_processor":"scss","css_starter":"neither","css_prefix":"autoprefixer","head":"<meta name=&apos;viewport&apos; content=&apos;width=device-width, initial-scale=1&apos;>"}' />
        <button class="button" type="submit" data-name="Styling <code> within an anchor element" aria-label="Open Styling <code> within an anchor element in CodePen"><span class="button__icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" aria-hidden="true" focusable="false">
      <path d="M32 10.909l-0.024-0.116-0.023-0.067c-0.013-0.032-0.024-0.067-0.040-0.1-0.004-0.024-0.020-0.045-0.027-0.067l-0.047-0.089-0.040-0.067-0.059-0.080-0.061-0.060-0.080-0.060-0.061-0.040-0.080-0.059-0.059-0.053-0.020-0.027-14.607-9.772c-0.463-0.309-1.061-0.309-1.523 0l-14.805 9.883-0.051 0.053-0.067 0.075-0.049 0.060-0.067 0.080c-0.027 0.023-0.040 0.040-0.040 0.061l-0.067 0.080-0.027 0.080c-0.027 0.013-0.027 0.053-0.040 0.093l-0.013 0.067c-0.025 0.041-0.025 0.081-0.025 0.121v9.996c0 0.059 0.004 0.12 0.013 0.18l0.013 0.061c0.007 0.040 0.013 0.080 0.027 0.115l0.020 0.067c0.013 0.036 0.021 0.071 0.036 0.1l0.029 0.067c0 0.013 0.020 0.053 0.040 0.080l0.040 0.053c0.020 0.013 0.040 0.053 0.060 0.080l0.040 0.053 0.053 0.053c0.013 0.017 0.013 0.040 0.040 0.040l0.080 0.056 0.053 0.040 0.013 0.019 14.627 9.773c0.219 0.16 0.5 0.217 0.76 0.217s0.52-0.080 0.76-0.24l14.877-9.875 0.069-0.077 0.044-0.060 0.053-0.080 0.040-0.067 0.040-0.093 0.021-0.069 0.040-0.103 0.020-0.060 0.040-0.107v-10c0-0.067 0-0.127-0.021-0.187l-0.019-0.060 0.059 0.004zM16.013 19.283l-4.867-3.253 4.867-3.256 4.867 3.253-4.867 3.253zM14.635 10.384l-5.964 3.987-4.817-3.221 10.781-7.187v6.424zM6.195 16.028l-3.443 2.307v-4.601l3.443 2.301zM8.671 17.695l5.964 3.987v6.427l-10.781-7.188 4.824-3.223v-0.005zM17.387 21.681l5.965-3.973 4.817 3.227-10.783 7.187v-6.427zM25.827 16.041l3.444-2.293v4.608l-3.444-2.307zM23.353 14.388l-5.964-3.988v-6.44l10.78 7.187-4.816 3.224z"></path>
    </svg></span> Open in CodePen</button>
        </form>
<!-- prettier-ignore-end -->

          


          ]]></content
        >
      </entry><entry>
        <title>Repair edges of wrapped inline elements</title>
        <link href="https://saneef.com/blog/repair-edges-of-wrapped-inline-elements/" />
        <published>2021-05-26T00:00:00Z</published>
        <updated
          >2024-02-09T07:40:14Z</updated
        >
        <id>https://saneef.com/blog/repair-edges-of-wrapped-inline-elements/</id>
        <content type="html"
          ><![CDATA[<p>The CSS <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/box-decoration-break"><code>box-decoration-break</code></a> property controls the rendering of fragments of HTML elements. It is useful to fix styles at the edges where inline elements wrap.</p>
<p>Below you can find an example with two inline lists of emojis. In the second, <code>box-decoration-break</code> is set to <code>clone</code>. It fixes edges, retaining <code>padding</code> and <code>border-radius</code> styles.</p>
<p>All major browsers except Firefox need vendor prefixed property, <code>-webkit-box-decoration-break</code> to work.</p>
<!-- prettier-ignore-start -->
<style>

.box-decoration-break--clone {
  -webkit-box-decoration-break: clone;
          box-decoration-break: clone;
}

/* Presentational styles */

.font-xl {
  font-size: 2em;
}

ul.tags {
  font-size: 2rem;
  line-height: 2;
  padding: 0.25em;
  display: inline;
  list-style-type: none;
  background-color: hsla(204, 86%, 40%, .15);
  border-radius: 2000px;
}

.tags li {
  display: inline-flex;
  justify-content: center;
  align-items: center;
  width: 1.2em;
  height: 1.2em;
  background-color: hsla(204, 86%, 40%, .5);
  border-radius: 2000px;
  vertical-align: 0.1em;
}

.tags span {
  position: relative;
  font-size: 0.75em;
  line-height: 1;
  top: 0.0625em;
}

.block {
  padding: 1em;
  text-align:center;
  background-color: hsla(40, 92%, 94%, 0.50);
  border-radius: 0.25em;
}

.block > * + * {
  margin-top: 1rem;
}

.block code {
  font-size: 0.75em;
}

.container {
  display: grid;
  grid-template-columns: repeat(auto-fill, 24ch);
  gap: 1em;
  width: 100%;
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

*,
*::before,
*::after {
  margin: 0;
}

</style>
<details class="code-demo__collapse" open="true">
  <summary class="code-demo__collapse-title">CSS</summary>
  <div class="code-demo__code">
    <pre class="language-css" tabindex="0"><code class="language-css"><span class="token selector">.box-decoration-break--clone</span> <span class="token punctuation">{</span><br />  <span class="token property">-webkit-box-decoration-break</span><span class="token punctuation">:</span> clone<span class="token punctuation">;</span><br />          <span class="token property">box-decoration-break</span><span class="token punctuation">:</span> clone<span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token comment">/* Presentational styles */</span><br /><br /><span class="token selector">.font-xl</span> <span class="token punctuation">{</span><br />  <span class="token property">font-size</span><span class="token punctuation">:</span> 2em<span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token selector">ul.tags</span> <span class="token punctuation">{</span><br />  <span class="token property">font-size</span><span class="token punctuation">:</span> 2rem<span class="token punctuation">;</span><br />  <span class="token property">line-height</span><span class="token punctuation">:</span> 2<span class="token punctuation">;</span><br />  <span class="token property">padding</span><span class="token punctuation">:</span> 0.25em<span class="token punctuation">;</span><br />  <span class="token property">display</span><span class="token punctuation">:</span> inline<span class="token punctuation">;</span><br />  <span class="token property">list-style-type</span><span class="token punctuation">:</span> none<span class="token punctuation">;</span><br />  <span class="token property">background-color</span><span class="token punctuation">:</span> <span class="token function">hsla</span><span class="token punctuation">(</span>204<span class="token punctuation">,</span> 86%<span class="token punctuation">,</span> 40%<span class="token punctuation">,</span> .15<span class="token punctuation">)</span><span class="token punctuation">;</span><br />  <span class="token property">border-radius</span><span class="token punctuation">:</span> 2000px<span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token selector">.tags li</span> <span class="token punctuation">{</span><br />  <span class="token property">display</span><span class="token punctuation">:</span> inline-flex<span class="token punctuation">;</span><br />  <span class="token property">justify-content</span><span class="token punctuation">:</span> center<span class="token punctuation">;</span><br />  <span class="token property">align-items</span><span class="token punctuation">:</span> center<span class="token punctuation">;</span><br />  <span class="token property">width</span><span class="token punctuation">:</span> 1.2em<span class="token punctuation">;</span><br />  <span class="token property">height</span><span class="token punctuation">:</span> 1.2em<span class="token punctuation">;</span><br />  <span class="token property">background-color</span><span class="token punctuation">:</span> <span class="token function">hsla</span><span class="token punctuation">(</span>204<span class="token punctuation">,</span> 86%<span class="token punctuation">,</span> 40%<span class="token punctuation">,</span> .5<span class="token punctuation">)</span><span class="token punctuation">;</span><br />  <span class="token property">border-radius</span><span class="token punctuation">:</span> 2000px<span class="token punctuation">;</span><br />  <span class="token property">vertical-align</span><span class="token punctuation">:</span> 0.1em<span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token selector">.tags span</span> <span class="token punctuation">{</span><br />  <span class="token property">position</span><span class="token punctuation">:</span> relative<span class="token punctuation">;</span><br />  <span class="token property">font-size</span><span class="token punctuation">:</span> 0.75em<span class="token punctuation">;</span><br />  <span class="token property">line-height</span><span class="token punctuation">:</span> 1<span class="token punctuation">;</span><br />  <span class="token property">top</span><span class="token punctuation">:</span> 0.0625em<span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token selector">.block</span> <span class="token punctuation">{</span><br />  <span class="token property">padding</span><span class="token punctuation">:</span> 1em<span class="token punctuation">;</span><br />  <span class="token property">text-align</span><span class="token punctuation">:</span>center<span class="token punctuation">;</span><br />  <span class="token property">background-color</span><span class="token punctuation">:</span> <span class="token function">hsla</span><span class="token punctuation">(</span>40<span class="token punctuation">,</span> 92%<span class="token punctuation">,</span> 94%<span class="token punctuation">,</span> 0.50<span class="token punctuation">)</span><span class="token punctuation">;</span><br />  <span class="token property">border-radius</span><span class="token punctuation">:</span> 0.25em<span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token selector">.block > * + *</span> <span class="token punctuation">{</span><br />  <span class="token property">margin-top</span><span class="token punctuation">:</span> 1rem<span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token selector">.block code</span> <span class="token punctuation">{</span><br />  <span class="token property">font-size</span><span class="token punctuation">:</span> 0.75em<span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token selector">.container</span> <span class="token punctuation">{</span><br />  <span class="token property">display</span><span class="token punctuation">:</span> grid<span class="token punctuation">;</span><br />  <span class="token property">grid-template-columns</span><span class="token punctuation">:</span> <span class="token function">repeat</span><span class="token punctuation">(</span>auto-fill<span class="token punctuation">,</span> 24ch<span class="token punctuation">)</span><span class="token punctuation">;</span><br />  <span class="token property">gap</span><span class="token punctuation">:</span> 1em<span class="token punctuation">;</span><br />  <span class="token property">width</span><span class="token punctuation">:</span> 100%<span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token selector">*,<br />*::before,<br />*::after</span> <span class="token punctuation">{</span><br />  <span class="token property">box-sizing</span><span class="token punctuation">:</span> border-box<span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token selector">*,<br />*::before,<br />*::after</span> <span class="token punctuation">{</span><br />  <span class="token property">margin</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
  </div>
</details>
<details class="code-demo__collapse">
  <summary class="code-demo__collapse-title">HTML</summary>
  <div class="code-demo__code">
    <pre class="language-html" tabindex="0"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</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>container<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br />  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</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>block<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br />    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">></span></span>An inline list of Emojis. It comes with <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>code</span><span class="token punctuation">></span></span>box-decoration-break: slice;<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>code</span><span class="token punctuation">></span></span> applied by default.<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">></span></span><br />    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span><span class="token punctuation">></span></span><br />      <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>ul</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>tags<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br />        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>li</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span><span class="token punctuation">></span></span>❤️<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>li</span><span class="token punctuation">></span></span><br />        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>li</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span><span class="token punctuation">></span></span>👍<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>li</span><span class="token punctuation">></span></span><br />        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>li</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span><span class="token punctuation">></span></span>👎<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>li</span><span class="token punctuation">></span></span><br />        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>li</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span><span class="token punctuation">></span></span>😂<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>li</span><span class="token punctuation">></span></span><br />        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>li</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span><span class="token punctuation">></span></span>😮<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>li</span><span class="token punctuation">></span></span><br />        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>li</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span><span class="token punctuation">></span></span>😢<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>li</span><span class="token punctuation">></span></span><br />      <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>ul</span><span class="token punctuation">></span></span><br />    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span><br />    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</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>font-xl<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>⛔️ 😔<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">></span></span><br /><br />  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span><br /><br />  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</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>block<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br />    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">></span></span>Improving the edges of the fragments using <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>code</span><span class="token punctuation">></span></span>box-decoration-break: clone;<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>code</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">></span></span><br />    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span><span class="token punctuation">></span></span><br />      <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>ul</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>tags box-decoration-break--clone<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br />        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>li</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span><span class="token punctuation">></span></span>❤️<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>li</span><span class="token punctuation">></span></span><br />        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>li</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span><span class="token punctuation">></span></span>👍<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>li</span><span class="token punctuation">></span></span><br />        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>li</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span><span class="token punctuation">></span></span>👎<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>li</span><span class="token punctuation">></span></span><br />        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>li</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span><span class="token punctuation">></span></span>😂<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>li</span><span class="token punctuation">></span></span><br />        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>li</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span><span class="token punctuation">></span></span>😮<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>li</span><span class="token punctuation">></span></span><br />        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>li</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span><span class="token punctuation">></span></span>😢<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>li</span><span class="token punctuation">></span></span><br />      <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>ul</span><span class="token punctuation">></span></span><br />    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span><br />    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</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>font-xl<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>✅ 🤗<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">></span></span><br />  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span></code></pre>
  </div>
</details>
<details class="code-demo__collapse" open="true">
  <summary class="code-demo__collapse-title">Preview</summary>
  <div class="code-demo__output code-demo__output--no-resize">
<div class="container">
  <div class="block">
    <p>An inline list of Emojis. It comes with <code>box-decoration-break: slice;</code> applied by default.</p>
    <div>
      <ul class="tags">
        <li><span>❤️</span></li>
        <li><span>👍</span></li>
        <li><span>👎</span></li>
        <li><span>😂</span></li>
        <li><span>😮</span></li>
        <li><span>😢</span></li>
      </ul>
    </div>
    <p class="font-xl">⛔️ 😔</p>
  </div>
  <div class="block">
    <p>Improving the edges of the fragments using <code>box-decoration-break: clone;</code></p>
    <div>
      <ul class="tags box-decoration-break--clone">
        <li><span>❤️</span></li>
        <li><span>👍</span></li>
        <li><span>👎</span></li>
        <li><span>😂</span></li>
        <li><span>😮</span></li>
        <li><span>😢</span></li>
      </ul>
    </div>
    <p class="font-xl">✅ 🤗</p>
  </div>
</div>
  </div>
</details>
  <form action="https://codepen.io/pen/define" method="POST" target="_blank">
        <input type="hidden" name="data" value='{"title":"Saneef.com - Repair edges of wrapped inline elements","description":"Generated from: https://saneef.com/blog/repair-edges-of-wrapped-inline-elements/","tags":["saneef.com"],"editors":"110","layout":"left","html":"<!-- Saneef.com - Repair edges of wrapped inline elements\nGenerated from: https://saneef.com/blog/repair-edges-of-wrapped-inline-elements/ -->\n<div class=\"container\">\n  <div class=\"block\">\n    <p>An inline list of Emojis. It comes with <code>box-decoration-break: slice;</code> applied by default.</p>\n    <div>\n      <ul class=\"tags\">\n        <li><span>❤️</span></li>\n        <li><span>👍</span></li>\n        <li><span>👎</span></li>\n        <li><span>😂</span></li>\n        <li><span>😮</span></li>\n        <li><span>😢</span></li>\n      </ul>\n    </div>\n    <p class=\"font-xl\">⛔️ 😔</p>\n\n  </div>\n\n  <div class=\"block\">\n    <p>Improving the edges of the fragments using <code>box-decoration-break: clone;</code></p>\n    <div>\n      <ul class=\"tags box-decoration-break--clone\">\n        <li><span>❤️</span></li>\n        <li><span>👍</span></li>\n        <li><span>👎</span></li>\n        <li><span>😂</span></li>\n        <li><span>😮</span></li>\n        <li><span>😢</span></li>\n      </ul>\n    </div>\n    <p class=\"font-xl\">✅ 🤗</p>\n  </div>\n</div>\n","html_pre_processor":"none","css":"/* Box sizing rules */\n*,\n*::before,\n*::after {\n  box-sizing: border-box;\n}\n\n/* Remove default margin */\nbody,\nh1,\nh2,\nh3,\nh4,\np {\n  margin: 0;\n}\n\n/* Set core body defaults */\nbody {\n  min-height: 100vh;\n  text-rendering: optimizeSpeed;\n  line-height: 1.5;\n  font-family: system-ui, sans-serif;\n}\n\n/* Make images easier to work with */\nimg {\n  display: block;\n  max-width: 100%;\n}\n\n/***\n 🟣 Saneef.com Demo Styles\n */\n\n.box-decoration-break--clone {\n  -webkit-box-decoration-break: clone;\n          box-decoration-break: clone;\n}\n\n/* Presentational styles */\n\n.font-xl {\n  font-size: 2em;\n}\n\nul.tags {\n  font-size: 2rem;\n  line-height: 2;\n  padding: 0.25em;\n  display: inline;\n  list-style-type: none;\n  background-color: hsla(204, 86%, 40%, .15);\n  border-radius: 2000px;\n}\n\n.tags li {\n  display: inline-flex;\n  justify-content: center;\n  align-items: center;\n  width: 1.2em;\n  height: 1.2em;\n  background-color: hsla(204, 86%, 40%, .5);\n  border-radius: 2000px;\n  vertical-align: 0.1em;\n}\n\n.tags span {\n  position: relative;\n  font-size: 0.75em;\n  line-height: 1;\n  top: 0.0625em;\n}\n\n.block {\n  padding: 1em;\n  text-align:center;\n  background-color: hsla(40, 92%, 94%, 0.50);\n  border-radius: 0.25em;\n}\n\n.block > * + * {\n  margin-top: 1rem;\n}\n\n.block code {\n  font-size: 0.75em;\n}\n\n.container {\n  display: grid;\n  grid-template-columns: repeat(auto-fill, 24ch);\n  gap: 1em;\n  width: 100%;\n}\n\n*,\n*::before,\n*::after {\n  box-sizing: border-box;\n}\n\n*,\n*::before,\n*::after {\n  margin: 0;\n}\n","css_pre_processor":"scss","css_starter":"neither","css_prefix":"autoprefixer","head":"<meta name=&apos;viewport&apos; content=&apos;width=device-width, initial-scale=1&apos;>"}' />
        <button class="button" type="submit" data-name="Repair edges of wrapped inline elements" aria-label="Open Repair edges of wrapped inline elements in CodePen"><span class="button__icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" aria-hidden="true" focusable="false">
      <path d="M32 10.909l-0.024-0.116-0.023-0.067c-0.013-0.032-0.024-0.067-0.040-0.1-0.004-0.024-0.020-0.045-0.027-0.067l-0.047-0.089-0.040-0.067-0.059-0.080-0.061-0.060-0.080-0.060-0.061-0.040-0.080-0.059-0.059-0.053-0.020-0.027-14.607-9.772c-0.463-0.309-1.061-0.309-1.523 0l-14.805 9.883-0.051 0.053-0.067 0.075-0.049 0.060-0.067 0.080c-0.027 0.023-0.040 0.040-0.040 0.061l-0.067 0.080-0.027 0.080c-0.027 0.013-0.027 0.053-0.040 0.093l-0.013 0.067c-0.025 0.041-0.025 0.081-0.025 0.121v9.996c0 0.059 0.004 0.12 0.013 0.18l0.013 0.061c0.007 0.040 0.013 0.080 0.027 0.115l0.020 0.067c0.013 0.036 0.021 0.071 0.036 0.1l0.029 0.067c0 0.013 0.020 0.053 0.040 0.080l0.040 0.053c0.020 0.013 0.040 0.053 0.060 0.080l0.040 0.053 0.053 0.053c0.013 0.017 0.013 0.040 0.040 0.040l0.080 0.056 0.053 0.040 0.013 0.019 14.627 9.773c0.219 0.16 0.5 0.217 0.76 0.217s0.52-0.080 0.76-0.24l14.877-9.875 0.069-0.077 0.044-0.060 0.053-0.080 0.040-0.067 0.040-0.093 0.021-0.069 0.040-0.103 0.020-0.060 0.040-0.107v-10c0-0.067 0-0.127-0.021-0.187l-0.019-0.060 0.059 0.004zM16.013 19.283l-4.867-3.253 4.867-3.256 4.867 3.253-4.867 3.253zM14.635 10.384l-5.964 3.987-4.817-3.221 10.781-7.187v6.424zM6.195 16.028l-3.443 2.307v-4.601l3.443 2.301zM8.671 17.695l5.964 3.987v6.427l-10.781-7.188 4.824-3.223v-0.005zM17.387 21.681l5.965-3.973 4.817 3.227-10.783 7.187v-6.427zM25.827 16.041l3.444-2.293v4.608l-3.444-2.307zM23.353 14.388l-5.964-3.988v-6.44l10.78 7.187-4.816 3.224z"></path>
    </svg></span> Open in CodePen</button>
        </form>
<!-- prettier-ignore-end -->

          


          ]]></content
        >
      </entry><entry>
        <title>Hiding posts with future dates in Eleventy</title>
        <link href="https://saneef.com/blog/hiding-posts-with-future-dates-in-eleventy/" />
        <published>2021-05-24T00:00:00Z</published>
        <updated
          >2024-02-09T07:40:14Z</updated
        >
        <id>https://saneef.com/blog/hiding-posts-with-future-dates-in-eleventy/</id>
        <content type="html"
          ><![CDATA[<p>In static site generators like Jekyll, you can generate posts with a future date using a flag. When you build on your local machine, provide that flag to view future posts. Later, when you publish your blog, you can skip future posts. It is a handy feature when you build your website every day using <a href="https://www.11ty.dev/docs/quicktips/netlify-ifttt/">IFTTT</a> or something similar.</p>
<p>In Eleventy, there is no such flag. Here is a technique I use to get a similar result with Eleventy.</p>
<p>Let’s use an environment variable, <code>ELEVENTY_ENV</code>, to distinguish between local machine (development) and blog (production) environment.</p>
<pre class="language-bash" tabindex="0"><code class="language-bash"><span class="token comment"># Development</span><br />$ npx @11ty/eleventy <span class="token parameter variable">--serve</span><br /><br /><span class="token comment"># Production</span><br />$ <span class="token assign-left variable">ELEVENTY_ENV</span><span class="token operator">=</span>production npx @11ty/eleventy</code></pre>
<p>To hide the post, we need to set two data variables on each page, <a href="https://www.11ty.dev/docs/permalinks/"><code>permalink</code></a> and <a href="https://www.11ty.dev/docs/collections/#option-exclude-content-from-collections"><code>eleventyExcludeFromCollections</code></a>, based on the page date and environment:</p>
<ul>
<li>set <code>permalink</code> to <code>false</code> to disable writing the file to the output folder.</li>
<li>set <code>eleventyExcludeFromCollections</code> to <code>true</code>, to exclude from collections as the variable name suggests.</li>
</ul>
<p>We can set these data variables to all pages using <a href="https://www.11ty.dev/docs/data-computed/"><code>eleventyComputed</code></a> feature. Create a JavaScript file in the path <code>_data/eleventyComputed.js</code>, and add these lines:</p>
<pre class="language-js" tabindex="0"><code class="language-js"><span class="token comment">/* _data/eleventyComputed.js */</span><br /><span class="token keyword">const</span> <span class="token function-variable function">isPageFromFuture</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> date <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token operator">=></span><br />  process<span class="token punctuation">.</span>env<span class="token punctuation">.</span><span class="token constant">ELEVENTY_ENV</span> <span class="token operator">===</span> <span class="token string">"production"</span> <span class="token operator">&amp;&amp;</span> date<span class="token punctuation">.</span><span class="token function">getTime</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">></span> Date<span class="token punctuation">.</span><span class="token function">now</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br />module<span class="token punctuation">.</span>exports <span class="token operator">=</span> <span class="token punctuation">{</span><br />  <span class="token function-variable function">permalink</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token parameter">data</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br />    <span class="token keyword">const</span> <span class="token punctuation">{</span> permalink<span class="token punctuation">,</span> page <span class="token punctuation">}</span> <span class="token operator">=</span> data<span class="token punctuation">;</span><br />    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">isPageFromFuture</span><span class="token punctuation">(</span>page<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span><br /><br />    <span class="token keyword">return</span> permalink<span class="token punctuation">;</span><br />  <span class="token punctuation">}</span><span class="token punctuation">,</span><br />  <span class="token function-variable function">eleventyExcludeFromCollections</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token parameter">data</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br />    <span class="token keyword">const</span> <span class="token punctuation">{</span> eleventyExcludeFromCollections<span class="token punctuation">,</span> page <span class="token punctuation">}</span> <span class="token operator">=</span> data<span class="token punctuation">;</span><br />    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">isPageFromFuture</span><span class="token punctuation">(</span>page<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span><br /><br />    <span class="token keyword">return</span> eleventyExcludeFromCollections<span class="token punctuation">;</span><br />  <span class="token punctuation">}</span><span class="token punctuation">,</span><br /><span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre>
<p>The <code>isPageFromFuture()</code> returns <code>true</code> when the environment is <code>production</code>, and the current page has a future date. Based on that value we set <code>permalink</code> and <code>eleventyExcludeFromCollections</code> data variables.</p>
<p>Now, try building your blog with and without the environment variable <code>ELEVENTY_ENV=production</code>.</p>

          


          ]]></content
        >
      </entry><entry>
        <title>CSS Grid areas</title>
        <link href="https://saneef.com/blog/css-grid-areas/" />
        <published>2021-05-22T00:00:00Z</published>
        <updated
          >2024-02-09T07:40:14Z</updated
        >
        <id>https://saneef.com/blog/css-grid-areas/</id>
        <content type="html"
          ><![CDATA[<p>Let’s say you want to build a layout like the one below using CSS Grid. You have two choices, an insane way, and a sane way.</p>
<figure>
  <img src="https://saneef.com/images/tutorials-css-grid-areas-sample-grid-layout.jpg" alt="A sample grid layout" />
  <figcaption>A sample layout which we will try to build in code using CSS Grid</figcaption>
</figure>
<h2 id="the-insane-way" tabindex="-1">The insane way<a class="link link--anchor" href="https://saneef.com/blog/css-grid-areas/#the-insane-way" aria-hidden="true" tabindex="-1"></a></h2>
<p>This method will almost always tip you into the insane spectrum while creating, modifying, or using the grid. I’m not going to show you the method. But, I tell you this, it involves imaginary lines, properties like <code>grid-row</code> and <code>grid-column</code>, and some <code>/</code>s.</p>
<h2 id="the-sane-way" tabindex="-1">The sane way<a class="link link--anchor" href="https://saneef.com/blog/css-grid-areas/#the-sane-way" aria-hidden="true" tabindex="-1"></a></h2>
<p>The sane way utilises the CSS property <code>grid-template-areas</code>.</p>
<!-- prettier-ignore-start -->
<style>

.the-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: 64px 1fr 64px;
  grid-template-areas:
    "header header header header"
    "sidebar content content content"
    "footer footer footer footer";
}

.the-header {
  grid-area: header;
}

.the-sidebar {
  grid-area: sidebar;
}

.the-content {
  grid-area: content;
}

.the-footer {
  grid-area: footer;
}

/* Presentational styles */
.the-page {
  min-height: 480px;
  display: grid;
  place-items: center;
}

.the-grid {
  min-height: 400px;
  min-width: 300px;
  gap: 0.25em;
}

.the-header,
.the-sidebar,
.the-content,
.the-footer {
  --rgb: 0,0,0;
  --opacity: 1;
  --bg-opacity: 0.2;
  padding: 1em;
  border: 1px solid;
  color: rgba(var(--rgb),var(--opacity));
  background-color: rgba(var(--rgb),var(--bg-opacity));
}

.the-header {
  --rgb: 0,122,255;
}

.the-sidebar {
  --rgb: 155,155,155;
}

.the-footer {
  --rgb: 246,83,83;
}

</style>
<details class="code-demo__collapse" open="true">
  <summary class="code-demo__collapse-title">CSS</summary>
  <div class="code-demo__code">
    <pre class="language-css" tabindex="0"><code class="language-css"><span class="token selector">.the-grid</span> <span class="token punctuation">{</span><br />  <span class="token property">display</span><span class="token punctuation">:</span> grid<span class="token punctuation">;</span><br />  <span class="token property">grid-template-columns</span><span class="token punctuation">:</span> <span class="token function">repeat</span><span class="token punctuation">(</span>4<span class="token punctuation">,</span> 1fr<span class="token punctuation">)</span><span class="token punctuation">;</span><br />  <span class="token property">grid-template-rows</span><span class="token punctuation">:</span> 64px 1fr 64px<span class="token punctuation">;</span><br />  <span class="token property">grid-template-areas</span><span class="token punctuation">:</span><br />    <span class="token string">"header header header header"</span><br />    <span class="token string">"sidebar content content content"</span><br />    <span class="token string">"footer footer footer footer"</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token selector">.the-header</span> <span class="token punctuation">{</span><br />  <span class="token property">grid-area</span><span class="token punctuation">:</span> header<span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token selector">.the-sidebar</span> <span class="token punctuation">{</span><br />  <span class="token property">grid-area</span><span class="token punctuation">:</span> sidebar<span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token selector">.the-content</span> <span class="token punctuation">{</span><br />  <span class="token property">grid-area</span><span class="token punctuation">:</span> content<span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token selector">.the-footer</span> <span class="token punctuation">{</span><br />  <span class="token property">grid-area</span><span class="token punctuation">:</span> footer<span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token comment">/* Presentational styles */</span><br /><span class="token selector">.the-page</span> <span class="token punctuation">{</span><br />  <span class="token property">min-height</span><span class="token punctuation">:</span> 480px<span class="token punctuation">;</span><br />  <span class="token property">display</span><span class="token punctuation">:</span> grid<span class="token punctuation">;</span><br />  <span class="token property">place-items</span><span class="token punctuation">:</span> center<span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token selector">.the-grid</span> <span class="token punctuation">{</span><br />  <span class="token property">min-height</span><span class="token punctuation">:</span> 400px<span class="token punctuation">;</span><br />  <span class="token property">min-width</span><span class="token punctuation">:</span> 300px<span class="token punctuation">;</span><br />  <span class="token property">gap</span><span class="token punctuation">:</span> 0.25em<span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token selector">.the-header,<br />.the-sidebar,<br />.the-content,<br />.the-footer</span> <span class="token punctuation">{</span><br />  <span class="token property">--rgb</span><span class="token punctuation">:</span> 0<span class="token punctuation">,</span>0<span class="token punctuation">,</span>0<span class="token punctuation">;</span><br />  <span class="token property">--opacity</span><span class="token punctuation">:</span> 1<span class="token punctuation">;</span><br />  <span class="token property">--bg-opacity</span><span class="token punctuation">:</span> 0.2<span class="token punctuation">;</span><br />  <span class="token property">padding</span><span class="token punctuation">:</span> 1em<span class="token punctuation">;</span><br />  <span class="token property">border</span><span class="token punctuation">:</span> 1px solid<span class="token punctuation">;</span><br />  <span class="token property">color</span><span class="token punctuation">:</span> <span class="token function">rgba</span><span class="token punctuation">(</span><span class="token function">var</span><span class="token punctuation">(</span>--rgb<span class="token punctuation">)</span><span class="token punctuation">,</span><span class="token function">var</span><span class="token punctuation">(</span>--opacity<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br />  <span class="token property">background-color</span><span class="token punctuation">:</span> <span class="token function">rgba</span><span class="token punctuation">(</span><span class="token function">var</span><span class="token punctuation">(</span>--rgb<span class="token punctuation">)</span><span class="token punctuation">,</span><span class="token function">var</span><span class="token punctuation">(</span>--bg-opacity<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token selector">.the-header</span> <span class="token punctuation">{</span><br />  <span class="token property">--rgb</span><span class="token punctuation">:</span> 0<span class="token punctuation">,</span>122<span class="token punctuation">,</span>255<span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token selector">.the-sidebar</span> <span class="token punctuation">{</span><br />  <span class="token property">--rgb</span><span class="token punctuation">:</span> 155<span class="token punctuation">,</span>155<span class="token punctuation">,</span>155<span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token selector">.the-footer</span> <span class="token punctuation">{</span><br />  <span class="token property">--rgb</span><span class="token punctuation">:</span> 246<span class="token punctuation">,</span>83<span class="token punctuation">,</span>83<span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
  </div>
</details>
<details class="code-demo__collapse">
  <summary class="code-demo__collapse-title">HTML</summary>
  <div class="code-demo__code">
    <pre class="language-html" tabindex="0"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</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>the-page<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br />  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</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>the-grid<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br />    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</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>the-header<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Header<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span><br />    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</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>the-sidebar<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Sidebar<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span><br />    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</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>the-content<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Content<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span><br />    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</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>the-footer<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Footer<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span><br />  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span></code></pre>
  </div>
</details>
<details class="code-demo__collapse" open="true">
  <summary class="code-demo__collapse-title">Preview</summary>
  <div class="code-demo__output">
<div class="the-page">
  <div class="the-grid">
    <div class="the-header">Header</div>
    <div class="the-sidebar">Sidebar</div>
    <div class="the-content">Content</div>
    <div class="the-footer">Footer</div>
  </div>
</div>
  </div>
</details>
  <form action="https://codepen.io/pen/define" method="POST" target="_blank">
        <input type="hidden" name="data" value='{"title":"Saneef.com - CSS Grid areas","description":"Generated from: https://saneef.com/blog/css-grid-areas/","tags":["saneef.com"],"editors":"110","layout":"left","html":"<!-- Saneef.com - CSS Grid areas\nGenerated from: https://saneef.com/blog/css-grid-areas/ -->\n<div class=\"the-page\">\n  <div class=\"the-grid\">\n    <div class=\"the-header\">Header</div>\n    <div class=\"the-sidebar\">Sidebar</div>\n    <div class=\"the-content\">Content</div>\n    <div class=\"the-footer\">Footer</div>\n  </div>\n</div>\n","html_pre_processor":"none","css":"/* Box sizing rules */\n*,\n*::before,\n*::after {\n  box-sizing: border-box;\n}\n\n/* Remove default margin */\nbody,\nh1,\nh2,\nh3,\nh4,\np {\n  margin: 0;\n}\n\n/* Set core body defaults */\nbody {\n  min-height: 100vh;\n  text-rendering: optimizeSpeed;\n  line-height: 1.5;\n  font-family: system-ui, sans-serif;\n}\n\n/* Make images easier to work with */\nimg {\n  display: block;\n  max-width: 100%;\n}\n\n/***\n 🟣 Saneef.com Demo Styles\n */\n\n.the-grid {\n  display: grid;\n  grid-template-columns: repeat(4, 1fr);\n  grid-template-rows: 64px 1fr 64px;\n  grid-template-areas:\n    \"header header header header\"\n    \"sidebar content content content\"\n    \"footer footer footer footer\";\n}\n\n.the-header {\n  grid-area: header;\n}\n\n.the-sidebar {\n  grid-area: sidebar;\n}\n\n.the-content {\n  grid-area: content;\n}\n\n.the-footer {\n  grid-area: footer;\n}\n\n/* Presentational styles */\n.the-page {\n  min-height: 480px;\n  display: grid;\n  place-items: center;\n}\n\n.the-grid {\n  min-height: 400px;\n  min-width: 300px;\n  gap: 0.25em;\n}\n\n.the-header,\n.the-sidebar,\n.the-content,\n.the-footer {\n  --rgb: 0,0,0;\n  --opacity: 1;\n  --bg-opacity: 0.2;\n  padding: 1em;\n  border: 1px solid;\n  color: rgba(var(--rgb),var(--opacity));\n  background-color: rgba(var(--rgb),var(--bg-opacity));\n}\n\n.the-header {\n  --rgb: 0,122,255;\n}\n\n.the-sidebar {\n  --rgb: 155,155,155;\n}\n\n.the-footer {\n  --rgb: 246,83,83;\n}\n","css_pre_processor":"scss","css_starter":"neither","css_prefix":"autoprefixer","head":"<meta name=&apos;viewport&apos; content=&apos;width=device-width, initial-scale=1&apos;>"}' />
        <button class="button" type="submit" data-name="CSS Grid areas" aria-label="Open CSS Grid areas in CodePen"><span class="button__icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" aria-hidden="true" focusable="false">
      <path d="M32 10.909l-0.024-0.116-0.023-0.067c-0.013-0.032-0.024-0.067-0.040-0.1-0.004-0.024-0.020-0.045-0.027-0.067l-0.047-0.089-0.040-0.067-0.059-0.080-0.061-0.060-0.080-0.060-0.061-0.040-0.080-0.059-0.059-0.053-0.020-0.027-14.607-9.772c-0.463-0.309-1.061-0.309-1.523 0l-14.805 9.883-0.051 0.053-0.067 0.075-0.049 0.060-0.067 0.080c-0.027 0.023-0.040 0.040-0.040 0.061l-0.067 0.080-0.027 0.080c-0.027 0.013-0.027 0.053-0.040 0.093l-0.013 0.067c-0.025 0.041-0.025 0.081-0.025 0.121v9.996c0 0.059 0.004 0.12 0.013 0.18l0.013 0.061c0.007 0.040 0.013 0.080 0.027 0.115l0.020 0.067c0.013 0.036 0.021 0.071 0.036 0.1l0.029 0.067c0 0.013 0.020 0.053 0.040 0.080l0.040 0.053c0.020 0.013 0.040 0.053 0.060 0.080l0.040 0.053 0.053 0.053c0.013 0.017 0.013 0.040 0.040 0.040l0.080 0.056 0.053 0.040 0.013 0.019 14.627 9.773c0.219 0.16 0.5 0.217 0.76 0.217s0.52-0.080 0.76-0.24l14.877-9.875 0.069-0.077 0.044-0.060 0.053-0.080 0.040-0.067 0.040-0.093 0.021-0.069 0.040-0.103 0.020-0.060 0.040-0.107v-10c0-0.067 0-0.127-0.021-0.187l-0.019-0.060 0.059 0.004zM16.013 19.283l-4.867-3.253 4.867-3.256 4.867 3.253-4.867 3.253zM14.635 10.384l-5.964 3.987-4.817-3.221 10.781-7.187v6.424zM6.195 16.028l-3.443 2.307v-4.601l3.443 2.301zM8.671 17.695l5.964 3.987v6.427l-10.781-7.188 4.824-3.223v-0.005zM17.387 21.681l5.965-3.973 4.817 3.227-10.783 7.187v-6.427zM25.827 16.041l3.444-2.293v4.608l-3.444-2.307zM23.353 14.388l-5.964-3.988v-6.44l10.78 7.187-4.816 3.224z"></path>
    </svg></span> Open in CodePen</button>
        </form>
<!-- prettier-ignore-end -->
<p>Let me take you line by line. Let’s look at the class <code>.the-grid</code>.</p>
<ul>
<li><code>display: grid</code>: sets the element as block element and layout for its children to be grid.</li>
<li><code>grid-template-columns: repeat(4, 1fr)</code>: The value <code>repeat(4, 1fr)</code> is equivalent to <code>1fr 1fr 1fr 1fr</code>. This property tells the browser to have a grid layout of four columns of <code>1fr</code>. If you want to learn more about the <code>fr</code> unit, <a href="https://css-tricks.com/introduction-fr-css-unit/">CSS-Tricks have a good article</a>.</li>
<li><code>grid-template-rows: 64px 1fr 64px</code>: tells the browser to have the grid to three rows, <code>64px</code>, <code>1fr</code>, and <code>64px</code> height respectively.</li>
<li><code>grid-template-areas</code>. Here each quoted text corresponds to each row. Take a look at the first row, <code>&quot;header header header header&quot;</code>, it tells the browser to treat all four columns in the first row as area <code>header</code>. For the second row, <code>&quot;sidebar content content content&quot;</code> treat the first column as <code>sidebar</code> and the rest of the three columns as area <code>content</code>. <em>It’s important that the number of area names in each row should match the number of columns in that row</em>.</li>
</ul>
<!-- prettier-ignore-start -->
<pre class="language-css" tabindex="0"><code class="language-css"><span class="token property">grid-template-areas</span><span class="token punctuation">:</span><br />    <span class="token string">"header header header header"</span><br />    <span class="token string">"sidebar content content content"</span><br />    <span class="token string">"footer footer footer footer"</span><span class="token punctuation">;</span></code></pre>
<!-- prettier-ignore-end -->
<p>Now, let’s place the child elements on the grid. Look at the first child element <code>.the-header</code>. The property <code>grid-area: header;</code> (no need of quotes when specifying area) tells the browser to use area <code>header</code>. Similarly, other children are placed in their corresponding areas.</p>

          


          ]]></content
        >
      </entry><entry>
        <title>Fix our thinking, better solutions will follow</title>
        <link href="https://saneef.com/blog/fix-thinking/" />
        <published>2021-05-20T00:00:00Z</published>
        <updated
          >2021-05-19T21:09:15Z</updated
        >
        <id>https://saneef.com/blog/fix-thinking/</id>
        <content type="html"
          ><![CDATA[<blockquote>
<p>“Clear thinker” is a better compliment than “smart.”—Naval Ravikant</p>
</blockquote>
<p>Tools influence our thinking. Parts we focus on when holding a pencil are different from when keeping a hand on a mouse. We tend to focus on abstract pieces or the bigger picture when having a pencil. Latter, we tend to focus on the little details.</p>
<p>How many times did we all try to resist the itch to pick a better font or a color while doing a mind map or wireframing? We are working against the grain when using the wrong tools.</p>
<p>We need to get to solid concepts or foundation before detailing out. If we go the other way, we tend to produce solutions with hollow foundations.</p>
<p>I see many designers jump on a graphic tool as soon as they are faced a problem, off to hack some solutions. Different part of a problem needs a different set of tools. Sometimes we don’t need any, only some <a href="https://fs.blog/2015/08/how-to-think/" title="How to Think: The Skill You’ve Never Been Taught">good old thinking</a>. Picking the right tool will help us to get into the right-thinking mode. Better solutions will follow.</p>

          


          ]]></content
        >
      </entry>
</feed>

