<?xml version="1.0" encoding="utf-8"?>
  <rss version="2.0"
    xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:wfw="http://wellformedweb.org/CommentAPI/"
    xmlns:dc="http://purl.org/dc/elements/1.1/"
    xmlns:atom="http://www.w3.org/2005/Atom"
    xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
    xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
    xmlns:georss="http://www.georss.org/georss"
    xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#"
  >
    <channel>
      <title>Jhey Tompkins</title>
      <link>https://jhey.dev/</link>
      <atom:link href="https://jhey.dev/rss/writing.xml" rel="self" type="application/rss+xml" />
      <description>The RSS feed for all writing from Jhey Tompkins</description>
      <language>en-us</language>
      <copyright>Jhey Tompkins 2025</copyright>
      <docs>https://www.rssboard.org/rss-specification</docs>
      <pubDate>Mon, 16 Jun 2025 22:21:34 GMT</pubDate>
      <lastBuildDate>Mon, 16 Jun 2025 22:21:34 GMT</lastBuildDate>
      <managingEditor>rss@jhey.dev (Jhey Tompkins)</managingEditor>
      <webMaster>rss@jhey.dev (Jhey Tompkins)</webMaster>
      <image>
        <url>https://jhey.dev/media/image/headshot.jpeg</url>
        <title>Jhey Tompkins</title>
        <link>https://jhey.dev/</link>
      </image>
      
      <item>
        <title>Dynamic open graph images for your site with React and serverless</title>
        <link>https://jhey.dev/cheep/dynamic-open-graph-images-for-your-site</link>
        <author>rss@jhey.dev (Jhey Tompkins)</author>
        <description><![CDATA[<p>Have you ever wanted to lay out some text in a circle but it felt like a lot of prodding in the dark? How might you do it today? Could you do it with CSS alone in an accurate way? Let's take a look at a new way 👀</p>

<p>Ever wondered how people get those nice image cards to show up when they share a link to their site? These images are part of the Open Graph protocol (<a href="https://ogp.me/">https://ogp.me/</a>). You add some metadata to your page in the form of <code>meta</code> tags and that's it.</p>
<pre><code></code></pre>
<p>Today, let's look at how you could deal with that image value.</p>

<h2>Other solutions</h2>
<p>Before going into how they're generated for jhey.dev, there are other ways you could do it. This list isn't exhaustive.</p>
<ul>
<li>Host and curate images yourself for pages. Create your image and point the meta tag at its hosted location.</li>
<li>Generate the images at build time with Node using packages like Puppeteer and Sharp.</li>
<li>Use an image CDN with clever customization tools like those on offer from Cloudinary.</li>
<li>Something like Vercel's <code>@vercel/og</code> if you're using Vercel as your hosting provider.</li>
</ul>
<p>These are all good solutions. I'm sure there are others. It kinda comes down to what's going to suit your design and setup.</p>
<p>Before, jhey.dev used the second of those to create images like this.</p>
<p></p>
<p>It can be quite a weighty solution. I wanted to reflect the article here in the bear's sunglasses though. The idea is that you create some HTML and use Puppeteer to open it and take a screenshot of it. Then save that and host it. This all happens in a node script that could get run post-build.</p>
<p>The use of an image CDN is quite appealing. Jason Lengstorf has a good write-up on using Cloudinary to auto-generate social images. This was the first time I recall seeing it done with generated URLs. It's a lovely solution.</p>
<p>Then Vercel announced <code>@vercel/og</code> built upon <code>satori</code>. This is the one that excited me. It's a balance between the URL solution and the control of HTML. I got a quick taste by integrating it into the Codu community site. And after seeing how good it was, I wanted it for my own site. But, I don't use Vercel. And switching hosting providers for social images seemed extreme. So, how can you do it?</p>
<p></p>
<p><a href="https://www.learnwithjason.dev/blog/auto-generate-social-image/">https://www.learnwithjason.dev/blog/auto-generate-social-image/</a></p>
<p><a href="https://vercel.com/docs/concepts/functions/edge-functions/og-image-generation">https://vercel.com/docs/concepts/functions/edge-functions/og-image-generation</a></p>
<p><a href="https://github.com/codu-code/codu/pull/92">https://github.com/codu-code/codu/pull/92</a></p>
<hr />
<p>That's it! It's wild to think how the web platform is evolving. All these new features and tools that are knocking down hurdles we've faced for some time.</p>
<p><strong>Until next time, stay awesome!</strong></p>
<p></p>
<h2>Further reading</h2>
<ul>
<li><a href="https://blog.stephaniestimac.com/posts/2023/1/css-trigonometric-functions/">An Intro to Trigonometric CSS Functions</a>: Stephanie Stimac</li>
<li><a href="https://css-tricks.com/the-power-and-fun-of-scope-with-css-custom-properties/">The Power (and fun) of Scope with Custom CSS Properties</a>: CSS Tricks</li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/SVG/Element/textPath">textPath</a>: MDN</li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/textLength">textLength</a>: MDN</li>
<li><a href="https://www.smashingmagazine.com/2019/03/svg-circle-decomposition-paths/">SVG circle decomposition to paths</a>: Smashing Magazine</li>
</ul>]]></description>
        <pubDate>Sun, 26 Feb 2023 00:00:00 GMT</pubDate>
        <guid isPermaLink="true">https://jhey.dev/cheep/dynamic-open-graph-images-for-your-site</guid>
        <source url="https://jhey.dev/rss/writing.xml">Jhey Tompkins writing RSS feed</source>
        
          <category>HTML</category>
        
          <category>JavaScript</category>
        
          <category>React</category>
        
          <category>Netlify</category>
        
          <category>Serverless</category>
        
      </item>
    
      <item>
        <title>Rotating gallery with CSS scroll-driven animations</title>
        <link>https://jhey.dev/cheep/rotating-gallery-with-css-scroll-driven-animations</link>
        <author>rss@jhey.dev (Jhey Tompkins)</author>
        <description><![CDATA[<p>Saw this <a href="https://twitter.com/austin_malerba/status/1618380647541932032">neat gallery effect</a> concept over on Twitter. It's built with <a href="https://www.framer.com/">Framer</a>. It got me thinking about how exciting the CSS scroll-driven animations API is going to be. I couldn't resist <a href="https://twitter.com/jh3yy/status/1621564942175322112">building a version</a> taking the API for a spin. And now I'm going to show you how to do it!</p>
<blockquote><p>Check out the <a href="https://codepen.io/jh3y/VwBgPxP">demo pen</a> by Jhey (<a href="https://codepen.io/jh3y">@jh3y</a>) over on <a href="https://codepen.io/jh3y/VwBgPxP">CodePen</a>.</p></blockquote>
<aside>
Sometimes the polyfill doesn't kick in for these embeds. Hit the "Rerun" button and try again if it animates on load.
</aside>
<p>If you're not familiar with this API, I introduced it in "<a href="https://web.dev/building-chrometober/">Building Chrometober</a>". It allows you to drive CSS animations with scroll. The magic part is that this will all happen off the main thread. That means performant scroll-driven animations where JavaScript is optional.</p>
<p>It's currently experimental in Chrome. But, there is a polyfill that you can use. That's what powers today's demo.</p>
<p></p>
<p>The API has been through many changes. The compatibility data from <a href="https://caniuse.com/mdn-css_properties_animation-timeline">MDN is a little inaccurate</a> currently (That's what powers the <code>&lt;BrowserSupport&gt;</code> widget above). I'd recommend keeping an eye on <a href="https://drafts.csswg.org/scroll-animations-1/">the spec</a> or the <a href="https://github.com/flackr/scroll-timeline">polyfill repo</a> if you're interested in keeping up to date with things. Or <a href="https://twitter.com/jh3yy">keep in touch</a> with me!</p>
<h2>Drive type</h2>
<p>At a high level, scroll-driven animations fall into two categories:</p>
<ol>
<li>Those driven by scroll position using <code>scroll-timeline</code>.</li>
<li>Those driven by an element's position within its scroll container (scrollport) using <code>view-timeline</code>.</li>
</ol>
<p>Today, we're concerned with the first of those. Driving animations based on scroll position.</p>
<aside>
<p>Triggering animations on scroll is currently out of scope. For now, using an <a href="https://developer.mozilla.org/docs/Web/API/Intersection_Observer_API">IntersectionObserver</a> or a package like <a href="https://scroll-out.github.io/">ScrollOut</a> is a good option. You could also use <a href="https://greensock.com">GreenSock</a>, more on this later.</p>
</aside>
<h2>Building this demo</h2>
<p>First things first, we need that polyfill. Import this in a way that works for you. Here it is in a <code>script</code> tag.</p>
<pre><code>&lt;script src="https://flackr.github.io/scroll-timeline/dist/scroll-timeline.js"&gt;&lt;/script&gt;
</code></pre>
<p>Up next, you need some elements to animate. A list with some images will work for what we want. For this demo, I've used <a href="https://picsum.photos/">picsum.photos</a> for placeholder images:</p>
<pre><code>&lt;main&gt;
  &lt;ul&gt;
    &lt;li style="--x1: 2; --x2: 6; --y1: 1; --y2: 4;"&gt;
      &lt;img src="https://picsum.photos/600/600?random=1" alt=""&gt;
    &lt;/li&gt;
    &lt;li style="--x1: 6; --x2: 8; --y1: 2; --y2: 4;"&gt;
      &lt;img src="https://picsum.photos/600/600?random=2" alt=""&gt;
    &lt;/li&gt;
    &lt;!-- Obfuscated items --&gt;
  &lt;/ul&gt;
&lt;/main&gt;
</code></pre>
<aside>
<p>Using something like <a href="https://www.emmet.io/">emmett</a> makes generating markup for images a breeze. To get random images in a list:
<code>main&gt;ul&gt;li*10&gt;img[src="<a href="https://picsum.photos/600/600?random=$">https://picsum.photos/600/600?random=$</a>" alt=""]</code>.</p>
</aside>
<p>Now to lay them out in this grid-like manner. You have options here. You could use <code>grid-template-areas</code> and draw the layout in your CSS.</p>
<pre><code>ul {
  grid-template-areas: ". a a a a . . . . ."
                       ". a a a a c c . ."
                       ". a a a a c c . .";
}
li:nth-of-type(1) {
  grid-area: a;
}

</code></pre>
<p>I'm not a huge fan of <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-areas"><code>grid-template-areas</code></a> though. They sometimes <a href="https://github.com/sass/sass/issues/216">don't play nice</a>.</p>
<p>You may have noticed the inline styles in the markup above:</p>
<pre><code>&lt;li style="--x1: 2; --x2: 6; --y1: 1; --y2: 4;"&gt;
  &lt;img src="https://picsum.photos/600/600?random=1" alt=""&gt;
&lt;/li&gt;
</code></pre>
<p>They define the coordinates for grid position. It might seem verbose to write these out. But, I like to lean into the use of custom property scope here. You can likely get away with positioning the main items and then rely on <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/grid-auto-flow"><code>grid-auto-flow: dense</code></a> too. Another approach would be having these coordinates in a JavaScript object. Then you can use whatever templating language you like to generate the markup and inline styles.</p>
<p>Anyway, back to the styles. Taking the custom property approach, you can scope the styles for the items:</p>
<pre><code>ul {
  --big-tile-size: 50vmin;
  --rotation: 270deg;
  --scale: 0.4;
  --tile-size: calc(var(--big-tile-size) / 3);
  display: grid;
  grid-template: repeat(9, var(--tile-size)) / repeat(9, var(--tile-size));
  gap: 1vmin;
  transform:
    translate(-50%, -50%)
    scale(var(--scale))
    rotate(0deg);
}
li {
  grid-column: var(--x1, auto) / var(--x2, auto);
  grid-row: var(--y1, auto) / var(--y2, auto);
}
</code></pre>
<blockquote><p>Check out the <a href="https://codepen.io/jh3y/BaOyjgj">demo pen</a> by Jhey (<a href="https://codepen.io/jh3y">@jh3y</a>) over on <a href="https://codepen.io/jh3y/BaOyjgj">CodePen</a>.</p></blockquote>
<p>Now the grid is starting to take shape. There are custom properties to define the behavior of the grid and it's time for animation. This is where the <code>--scale</code> and <code>--rotation</code> properties are going to come into play.</p>
<p>You need to animate two things:</p>
<ol>
<li>The layout's scale and rotation.</li>
<li>The image rotation to counter the layout rotation.</li>
</ol>
<p>But, you don't need two keyframes for that. You can share one set using custom properties.</p>
<pre><code>@keyframes scale-up {
  0% {
    transform:
      translate(-50%, -50%)
      scale(var(--scale))
      rotate(0deg);
  }
  100% {
    transform:
      translate(-50%, -50%)
      scale(1)
      rotate(var(--rotation));
  }
}
</code></pre>
<p>The images set their direction to counter the layout rotation and use the same keyframes:</p>
<pre><code>img {
  --rotation: -270deg;
  --scale: 1;
}
</code></pre>
<aside>
You could refactor this to reduce some of the code but we're building to understand how the idea comes to life.
</aside>
<p>Now you can apply the animation. Let's set the iteration count to infinite to see it on loop.</p>
<pre><code>ul, img {
  animation: scale-up 10s infinite ease-in-out alternate;
}
</code></pre>
<blockquote><p>Check out the <a href="https://codepen.io/jh3y/poOvyor">demo pen</a> by Jhey (<a href="https://codepen.io/jh3y">@jh3y</a>) over on <a href="https://codepen.io/jh3y/poOvyor">CodePen</a>.</p></blockquote>
<p>Ready for the last piece of the puzzle? Let's drive it with the body's scroll position.</p>
<pre><code>ul, img {
  animation-timeline: scroll(root);
  animation: 1s scale-up both ease-in;
}
</code></pre>
<p>Yep. That's all you need for a scroll timeline. Remove the iteration count from our animation and set the <code>animation-fill-mode</code> to <code>both</code>. The <code>animation-timeline</code> property is set to <code>scroll(root)</code>. This defines that the animation will get driven by the scroll of the root scroller. In this case, that's the <code>body</code>. To tie it all together, we fix the position of our layout and set the body height to the amount we'd like to scroll.</p>
<pre><code>body { height: 300vh; }
</code></pre>
<p>And we get the end result!</p>
<blockquote><p>Check out the <a href="https://codepen.io/jh3y/VwBgPxP">demo pen</a> by Jhey (<a href="https://codepen.io/jh3y">@jh3y</a>) over on <a href="https://codepen.io/jh3y/VwBgPxP">CodePen</a>.</p></blockquote>
<p>Driving CSS animation with scroll and no JavaScript is an exciting prospect. I'm excited for it to make its way into browsers. Let's hope future versions of the spec include the ability to trigger or ease the animations.</p>
<h2>Bonus (GSAP Solution)</h2>
<p>The scroll-driven animations API is in its early stages. Someone did reach out asking if you could ease the scroll. If it were me, I'd be reaching for <a href="https://greensock.com/">GreenSock</a>. The <a href="https://greensock.com/scrolltrigger/">ScrollTrigger plugin</a> handles this use case well with the <code>scrub</code> property.</p>
<p>You have to adjust your implementation a little. But, you can power the whole thing with this block of JavaScript:</p>
<pre><code>import gsap from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger"

gsap.registerPlugin(ScrollTrigger)

gsap.defaults({
  duration: 2,
  ease: "power1.inOut"
});

const rotate = 270

gsap
  .timeline({
    scrollTrigger: {
      scrub: 1, // smooth scrubbing catch up duration
    }
  })
  .to("ul", {
    scale: 1,
    rotate,
  })
  .to(
    "img",
    {
      rotate: -rotate
    },
    0
  );
</code></pre>
<blockquote><p>Check out the <a href="https://codepen.io/jh3y/yLxyOJp">demo pen</a> by Jhey (<a href="https://codepen.io/jh3y">@jh3y</a>) over on <a href="https://codepen.io/jh3y/yLxyOJp">CodePen</a>.</p></blockquote>
<hr />
<p>That's it! The <a href="https://drafts.csswg.org/scroll-animations-1/">CSS scroll-driven animation API</a> is an exciting one. I've been <a href="https://twitter.com/jh3yy/status/1621564942175322112">playing</a> with it a <a href="https://twitter.com/jh3yy/status/1615815314087837696">bunch</a> seeing what kind of <a href="https://twitter.com/jh3yy/status/1590450608620044288">things</a> you can do with it. I'm excited to see it in your hands! Until that API matures though, solutions like <a href="https://greensock.com/scrolltrigger/">GreenSock's ScrollTrigger</a> are fantastic.</p>
<p><strong>Stay awesome!</strong></p>
<p></p>
<h2>Further reading</h2>
<ul>
<li><a href="https://web.dev/building-chrometober/">Building Chrometober</a>: web.dev</li>
<li><a href="https://drafts.csswg.org/scroll-animations-1/">Scroll Animations Spec</a>: CSSWG</li>
<li><a href="https://caniuse.com/mdn-css_properties_animation-timeline">Animation Timeline Browser Support</a>: caniuse.com</li>
<li><a href="https://twitter.com/jh3yy/status/1621564942175322112">Demo tweet</a>: Twitter</li>
<li><a href="https://codepen.io/jh3y/pen/VwBgPxP">Demo link</a>: CodePen</li>
<li><a href="https://codepen.io/collection/qOobRy">Demo Collection</a>: CodePen</li>
<li><a href="https://greensock.com/scrolltrigger/">GSAP ScrollTrigger</a>: GreenSock</li>
</ul>]]></description>
        <pubDate>Sat, 04 Feb 2023 00:00:00 GMT</pubDate>
        <guid isPermaLink="true">https://jhey.dev/cheep/rotating-gallery-with-css-scroll-driven-animations</guid>
        <source url="https://jhey.dev/rss/writing.xml">Jhey Tompkins writing RSS feed</source>
        
          <category>CSS</category>
        
          <category>HTML</category>
        
          <category>JavaScript</category>
        
      </item>
    
      <item>
        <title>What the Git? My Git workflow</title>
        <link>https://jhey.dev/cheep/what-the-git</link>
        <author>rss@jhey.dev (Jhey Tompkins)</author>
        <description><![CDATA[<p>Believe it or not. There was a time before Git. A time when people used other version control systems. In fact, some people would even FTP things straight to the server. Wild. I started my front-end career in 2012 (That seems like forever ago). I remember having to get my head around Git as the team I was on transitioned from another system. It could have been Subversion. I remember using Tortoise SVN at some point.</p>
<p>Anyway. This isn't a history lesson. There was a recent kerfuffle on social media about whether to "rebase" or "merge". And it got me thinking, "For real? Do you know what this was like before?". Commit message history was the least of people's worries ha. I've worked in a lot of different setups and seen it done in all sorts of ways. There's no one workflow to rule them all. That's the price of Git being feature rich.</p>
<p>In case you wondered, I'm team rebase for what it's worth.</p>
<h2>GUI vs. CLI</h2>
<p>To be honest, I haven't used a GUI app for Git in years. Nothing says that another machine is going to have your GUI app available. This exact scenario pushed me the CLI way when I had to start SSH'ing into remote machines for a role. The deep end will skill you up quicker than anything haha. That said, you can’t take your Git aliases with you.</p>
<h2>Aliases</h2>
<p>Creating <a href="https://git-scm.com/book/en/v2/Git-Basics-Git-Aliases">Git aliases</a> can save you a lot of time. Pushing something up? <code>gpu</code> is quicker to type than <code>git push</code>. Over time, it adds up.</p>
<p>How do you write an alias? That depends on how you're set up. You could write them into your <code>.gitconfig</code>. I like to set them up with the command line shell. I use ZSH and these are my current aliases. I do use <code>yolo</code> a bunch as part of the forking workflow.</p>
<pre><code>#
# Git aliases
#
alias gs="git status"
alias gba="git branch -av"
alias gch="git checkout"
alias gca="git commit -a -m"
alias gaa="git add --all"
alias gau="git remote add upstream"
alias gfu="git fetch upstream"
alias gpl="git pull"
alias gpu="git push"
alias yolo="git push --force"
alias yolos="git push --force &amp;&amp; say That was sneaky!"
alias gps="git push &amp;&amp; say You are awesome!"
alias gcl="git clone"
alias glg="git log"
alias gst="git shortlog -sn"
alias gsl="git stash list"
alias gsc="git stash clear"

function gsb() {
  git checkout -b $1 upstream/main
}
function gdb() {
  git branch -d $1
  git push origin :$1
}
function gas() {
  git stash apply stash@\{$1\}
}
function grb() {
  git rebase -i HEAD~$1
}
</code></pre>
<p>ZSH supports functions and they're great for creating aliases that handle parameters. I have a rebase alias that allows me to do things like start an interactive rebase of the last 3 commits. Instead of <code>git rebase -i HEAD~3</code>, it's <code>grb 3</code>. Easy.</p>
<h2>Workflow</h2>
<p>Rebase or merge? Whatever you prefer. The goal is to get code into a code base. I can't remember where seeing a merge commit in a Git log has been an issue. That said, I prefer not seeing them in there. It's easier to read depending on the amount of traffic.</p>
<p>Where possible, I try to follow the "<a href="https://www.atlassian.com/git/tutorials/comparing-workflows/forking-workflow">Forking workflow</a>". To me, that feels the most risk-averse. Contributors can only break their own yard.</p>
<p>Powered by my aliases, I'll likely do something like this:</p>
<pre><code># Clone my fork
gcl https://github.com/dev/awesome-project.git
cd awesome-project
# Add an upstream remote
gau https://github.com/official/awesome-project.git
# Fetch the upstream
gfu
# Start a new branch for what I'm doing
gsb FEAT-123/new-component
</code></pre>
<p>And then I'll crack on with a feature or something. I'll likely make a bunch of changes along the way. And I'll write myself messages in the commits:</p>
<pre><code>gca "update"
gca "try different looping method"
gca "pre lunch commit"
gca "check in before the refactor storm"
</code></pre>
<p>The idea is that these atomic messages help me out. If I needed to roll back to some point in time, I could. I'll tidy them up before I push. No one needs to know about the commit I made before lunch.</p>
<p>When everything looks good and I'm ready to push, I'll do an <a href="https://docs.gitlab.com/ee/topics/git/git_rebase.html">interactive rebase</a>. I'll squash all the meta-commits making it easier for others to read the commit history. If it feels like there are useful checkpoints, I'll leave them in. But, this kinda leans towards the ideal practice of keeping things atomic. If you start creating a bunch of checkpoints, they could likely all be pull requests. And it's easier for someone to review smaller changes.</p>
<pre><code># interactive rebase last 4 commits
grb 4
# push those changes
yolo
</code></pre>
<p>You can use the "Squash and merge" button on GitHub. I recommend it. Thing is. This habit started for me way before that feature was available. It's not a bad habit to have. I'll squash my commits, make sure I'm up to date with the official repo, and push.</p>
<hr />
<p>That's it. At the end of the day, find a workflow that's comfortable for you and be mindful of others. Keep things atomic. I mean, as long as the code gets into the repo, that's the main thing. That's the goal. Heck, write an alias that acts like FTP if you want (<em>Maybe don't do this</em>).</p>
<pre><code>function ftp() {
  git commit -a -m "FTP"
  git push --force
}
</code></pre>
<p><strong>Stay Awesome!</strong></p>
<p></p>
<h2>Further Reading</h2>
<ul>
<li><a href="https://git-scm.com/book/en/v2/Git-Basics-Git-Aliases">Git aliases</a>: Git</li>
<li><a href="https://www.atlassian.com/git/tutorials/comparing-workflows/forking-workflow">Forking workflow</a>: Atlassian</li>
<li><a href="https://docs.gitlab.com/ee/topics/git/git_rebase.html">Rebase and push</a>: GitLab</li>
<li><a href="https://zsh.sourceforge.io/Doc/Release/Functions.html">ZSH Functions</a>: ZSH Sourceforge</li>
<li><a href="https://ohmyz.sh/">Oh My ZSH</a>: Oh My ZSH</li>
</ul>]]></description>
        <pubDate>Fri, 03 Feb 2023 00:00:00 GMT</pubDate>
        <guid isPermaLink="true">https://jhey.dev/cheep/what-the-git</guid>
        <source url="https://jhey.dev/rss/writing.xml">Jhey Tompkins writing RSS feed</source>
        
          <category>Git</category>
        
      </item>
    
      <item>
        <title>Circular text with CSS?</title>
        <link>https://jhey.dev/cheep/circular-text-with-css</link>
        <author>rss@jhey.dev (Jhey Tompkins)</author>
        <description><![CDATA[<p>Have you ever wanted to lay out some text in a circle but it felt like a lot of prodding in the dark? How might you do it today? Could you do it with CSS alone in an accurate way? Let's take a look at a new way 👀</p>

<h2>How you might solve this today</h2>
<p>You've definitely got options. Before we go down the CSS route, you could use images. The least maintainable route could be creating an image each time you need to change the text. Make sure to use the <code>alt</code> attribute to describe the text that's shown.</p>
<img src="/media/image/2023/01/cheeps/circular-text-with-css/circular-text.png" alt="Circular text generated in Figma" width="250" height="250" />
<aside>
  The SVG generated in Figma, creates a path for each letter individually based on their position.
</aside>
<p>Or you could use an inline SVG. SVG has a <code>textPath</code> element. For the most part, it's pretty good. You give it some text and a path to lay that text on.</p>
<pre><code>&lt;svg
  viewBox="0 0 100 100"
  xmlns="http://www.w3.org/2000/svg"
&gt;
  &lt;path
    id="circlePath"
    d="
      M 10, 50
      a 40,40 0 1,1 80,0
      40,40 0 1,1 -80,0
    "
  /&gt;
  &lt;text&gt;
    &lt;textPath href="#circlePath"&gt;
      Your text here!
    &lt;/textPath&gt;
  &lt;/text&gt;
&lt;/svg&gt;
</code></pre>
<p>This route does pose a couple of hurdles. First, you need a <code>path</code>. You can't pass reference to a <code>circle</code>. That means converting a <code>circle</code> to a <code>path</code>.</p>
<pre><code>&lt;path
  d="
    M (CENTER_X - RADIUS),CENTER_Y
    a RADIUS,RADIUS 0 1,1 (2 * RADIUS),0
    RADIUS,RADIUS 0 1,1 (-2 * RADIUS),0
  "
/&gt;
</code></pre>
<p>Next, you need to choose whether you use the <code>textLength</code> attribute of <code>textPath</code>. This can spread the text around the path. The value of this will be the circumference.</p>
<pre><code>&lt;textPath
  href="#circularPath"
  textLength={Math.floor(Math.PI * 2 * RADIUS)}
&gt;
  Your text here!
&lt;/textPath&gt;
</code></pre>
<p>Put everything together and you'll get something like this.</p>
<blockquote><p>Check out the <a href="https://codepen.io/jh3y/ZEMYebW">demo pen</a> by Jhey (<a href="https://codepen.io/jh3y">@jh3y</a>) over on <a href="https://codepen.io/jh3y/ZEMYebW">CodePen</a>.</p></blockquote>
<p>In this demo, you can change the text and see how the use of <code>textLength</code> plays a part. You can also change the radius and font size. A neat part of using SVG is that we have something scalable. Another cool feature is that the text will follow the path direction. That makes it easy to flip whether the text is inside or outside of the path. You can do that by changing the <a href="https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths#arcs">sweep flag of an arc</a> between <code>1</code> and <code>0</code>.</p>
<p>So SVG can do the job, right? Well, kinda. But, if you try punching in some longer text, that radius will need adjusting. And, at this point, you're prodding in the dark.</p>
<hr />
<p>For the most part, working in code, we're somewhat wired to assume some degree of accuracy. That is, minus some rounding and other JavaScript quirks. So for me, punching numbers in until it "looks right", sometimes doesn't sit quite well with me.</p>
<p>Could you be more accurate with CSS? A rudimentary approach could go like this:</p>
<ol>
<li>Split text into span elements for each character.</li>
<li>Set an inline custom property for the character index.</li>
<li>Set an inline custom property on the parent for total characters.</li>
<li>Using CSS calc, transform each span by rotating and then translating it using its index.</li>
<li>If this will be visible to screenreaders, hide all the characters with <code>aria-hidden</code>. Then create a visually hidden span with the full text inside it.</li>
</ol>
<p>Here's how the HTML might look:</p>
<pre><code>&lt;span
  class="text-ring"
  style="--total: 15;"
&gt;
  &lt;span aria-hidden="true"&gt;
    &lt;span style="--index: 0"&gt;Y&lt;/span&gt;
    &lt;span style="--index: 1"&gt;o&lt;/span&gt;
    &lt;span style="--index: 2"&gt;u&lt;/span&gt;
    &lt;!-- Obfuscated markup --&gt;
  &lt;/span&gt;
  &lt;span class="sr-only"&gt;
    Your text here!
  &lt;/span&gt;
&lt;/span&gt;
</code></pre>
<p>And the CSS could go a little like this:</p>
<pre><code>.text-ring {
  position: relative;
}
.text-ring [style*=--index] {
  font-size: calc(var(--font-size, 2) * 1rem);
  position: absolute;
  top: 50%;
  left: 50%;
  transform:
    translate(-50%, -50%)
    rotate(calc(360deg / var(--total) * var(--index)))
    translateY(calc(var(--radius, 5) * -1ch));
}
</code></pre>
<p>How do you calculate that radius though? We're still prodding in the dark. Try adjusting things until they "look right" in this demo.</p>
<blockquote><p>Check out the <a href="https://codepen.io/jh3y/jOvEBME">demo pen</a> by Jhey (<a href="https://codepen.io/jh3y">@jh3y</a>) over on <a href="https://codepen.io/jh3y/jOvEBME">CodePen</a>.</p></blockquote>
<h2>Enter trigonometric functions</h2>
<p>Try not to fear the word "trigonometric". I know, I know. When I hear it, I start thinking of "Differential equations", "Mechanics", and so on. But, some Math and leaning into font behavior is going to get us a solution.</p>
<img src="/media/image/2023/01/cheeps/circular-text-with-css/math-lady-meme.jpeg" alt="Math lady meme" width="645" height="430" />
<p>You may have noticed the demos above use a monospace font. The benefit of doing so is that you know every character will be the same width. Think about the circle in a different way. It's actually lots of triangles around a point. A monospace font means every "side" of our circle is the same width. If you have the width of a side and the inner angle, you can calculate the hypoteneuse. That hypoteneuse is our radius!</p>
<pre><code>const TOTAL_CHARACTERS = 15
const INNER_ANGLE = 360 / 15
const LENGTH_OF_SIDE = 1 // 1ch
const RADIUS = LENGTH_OF_SIDE /
  Math.sin(INNER_ANGLE / (180 / Math.PI))
</code></pre>
<p>A neat trick here is to define the side width using the "ch" unit. That's equal to the width of a "0" in our font. And because a monospace font is being used, that'll be the width of every character. That means we'll get a radius in "ch" units. But, changing the <code>font-size</code> will behave in a way that scales the text ring. Neat!</p>
<p>That snippet of JavaScript above gets us the radius and now we can set that in our CSS. The bonus is that if you're doing static markup generation, you can pass all the details in as inline styles. Here it is <a href="https://codepen.io/jh3y/pen/OJwagZa">in a React component</a>. You might server-side render this or use it in something like Astro (What this site uses).</p>
<pre><code>const TextRing = (text) =&gt; {
  const CHARS = text.split('')
  const INNER_ANGLE = 360 / CHARS.length
  return (
    &lt;span
      className="text-ring"
      style={{
        '--total': CHARS.length,
        '--radius': 1 / Math.sin(INNER_ANGLE / (180 / Math.PI))
      }}
    &gt;
      {CHARS.map((char, index) =&gt; (
        &lt;span style={{'--index': index }}&gt;
          {char}
        &lt;/span&gt;
      ))}
    &lt;/span&gt;
  )
}
</code></pre>
<p>For the most part, this will do the trick. But, what if you don't like the feel of dictating your layout styles in JavaScript? Well, CSS might be able to help with that very soon.</p>
<aside>
Random fact. Not meeting the grade in advanced Mathematics in school put me on the programming path. But, that's a story for another day.
</aside>
<h2>Introducing CSS trigonometry</h2>
<p>Trigonometric functions are coming to CSS. This will give you access to functions such as <code>sin</code>, <code>cos</code>, and <code>tan</code> within CSS. They're already available in Firefox and Safari. They're poised to ship in Chromium 111. Be sure to check out the <a href="https://w3c.github.io/csswg-drafts/css-values/#trig-funcs">"CSS Values and Units Module Level 4"</a> spec. The introduction of these functions in CSS opens up some exciting opportunities. For example, you could use them <a href="https://twitter.com/jh3yy/status/1611450493129330689">in layouts</a> or the timing of <a href="https://twitter.com/jh3yy/status/1611475080818851840">loading animations</a>.</p>
<p></p>
<p>What does this mean for our circular text? CSS can now do the radius calculation. You no longer need to couple the layout styling to some JavaScript. The <code>--radius</code> is now calculated using <code>sin</code> in our CSS.</p>
<pre><code>.text-ring {
  --character-width: 1; /* In "ch" units */
  --inner-angle: calc((360 / var(--total)) * 1deg);
  --radius: calc(
    (
      var(--character-width, 1) /
      sin(var(--inner-angle))
    ) * -1ch
  );
}
.text-ring [style*=--index] {
  transform:
    translate(-50%, -50%)
    rotate(calc(var(--inner-angle) * var(--index)))
    translateY(var(--radius, -5ch));
}
</code></pre>
<p>Plug that into our demo and we get the right radius.</p>
<blockquote><p>Check out the <a href="https://codepen.io/jh3y/QWVwppw">demo pen</a> by Jhey (<a href="https://codepen.io/jh3y">@jh3y</a>) over on <a href="https://codepen.io/jh3y/QWVwppw">CodePen</a>.</p></blockquote>
<p>If you're not in a supporting browser, you <em>should</em> see a warning message. You can detect CSS trigonometric function support in CSS with:</p>
<pre><code>@supports (top: calc(sin(1) * 1px)) {
  /* Insert styles */
}
</code></pre>
<p>Or in JavaScript with:</p>
<pre><code>const canTrig = CSS.supports('(top: calc(sin(1) * 1px))')
</code></pre>
<p>For the finishing touches, let's make our text ring spin:</p>
<pre><code>@media (prefers-reduced-motion: no-preference) {
  .text-ring {
  	animation: spin 6s infinite linear;
  }
  @keyframes spin {
    to {
      rotate: -360deg;
    }
  }
}
</code></pre>
<p>And that'll do it. Putting it all together, we can make a demo like this one.</p>
<blockquote><p>Check out the <a href="https://codepen.io/jh3y/LYBdKXE">demo pen</a> by Jhey (<a href="https://codepen.io/jh3y">@jh3y</a>) over on <a href="https://codepen.io/jh3y/LYBdKXE">CodePen</a>.</p></blockquote>
<p>In this demo, CSS trigonometric functions get used if supported. If not, we fall back to setting the <code>--radius</code> with JavaScript. For now, you could copy the HTML and CSS you need until CSS trigonometric functions get full support. The next step is getting <code>sibling-count</code> and <code>sibling-index</code> in CSS. There's <a href="https://github.com/w3c/csswg-drafts/issues/4559">a proposal</a> for it in the CSSWG repo. Then we wouldn't need the inline custom properties anymore.</p>
<hr />
<p>That's it! It's wild to think how the web platform is evolving. All these new features and tools that are knocking down hurdles we've faced for some time.</p>
<p><strong>Until next time, stay awesome!</strong></p>
<p></p>
<h2>Further reading</h2>
<ul>
<li><a href="https://blog.stephaniestimac.com/posts/2023/1/css-trigonometric-functions/">An Intro to Trigonometric CSS Functions</a>: Stephanie Stimac</li>
<li><a href="https://css-tricks.com/the-power-and-fun-of-scope-with-css-custom-properties/">The Power (and fun) of Scope with Custom CSS Properties</a>: CSS Tricks</li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/SVG/Element/textPath">textPath</a>: MDN</li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/textLength">textLength</a>: MDN</li>
<li><a href="https://www.smashingmagazine.com/2019/03/svg-circle-decomposition-paths/">SVG circle decomposition to paths</a>: Smashing Magazine</li>
<li><a href="https://codepen.io/collection/yrKLvE">Demo Collection</a>: CodePen</li>
</ul>]]></description>
        <pubDate>Thu, 26 Jan 2023 00:00:00 GMT</pubDate>
        <guid isPermaLink="true">https://jhey.dev/cheep/circular-text-with-css</guid>
        <source url="https://jhey.dev/rss/writing.xml">Jhey Tompkins writing RSS feed</source>
        
          <category>CSS</category>
        
          <category>HTML</category>
        
          <category>JavaScript</category>
        
      </item>
    
      <item>
        <title>Control your drop caps with CSS initial-letter</title>
        <link>https://developer.chrome.com/blog/control-your-drop-caps-with-css-initial-letter/</link>
        <author>rss@jhey.dev (Jhey Tompkins)</author>
        <description><![CDATA[<p>Check out <a href="https://developer.chrome.com/blog/control-your-drop-caps-with-css-initial-letter/">this post</a> from Jhey over on <a href="https://developer.chrome.com/blog/control-your-drop-caps-with-css-initial-letter/">developer.chrome.com</a>!</p>]]></description>
        <pubDate>Thu, 19 Jan 2023 00:00:00 GMT</pubDate>
        <guid isPermaLink="true">https://developer.chrome.com/blog/control-your-drop-caps-with-css-initial-letter/</guid>
        <source url="https://jhey.dev/rss/writing.xml">Jhey Tompkins writing RSS feed</source>
        
          <category>CSS</category>
        
          <category>HTML</category>
        
      </item>
    
      <item>
        <title>Speedy CSS Tip! Animated Gradient Text</title>
        <link>https://web.dev/speedy-css-tip-animated-gradient-text/</link>
        <author>rss@jhey.dev (Jhey Tompkins)</author>
        <description><![CDATA[<p>Check out <a href="https://web.dev/speedy-css-tip-animated-gradient-text/">this post</a> from Jhey over on <a href="https://web.dev/speedy-css-tip-animated-gradient-text/">web.dev</a>!</p>]]></description>
        <pubDate>Thu, 03 Nov 2022 00:00:00 GMT</pubDate>
        <guid isPermaLink="true">https://web.dev/speedy-css-tip-animated-gradient-text/</guid>
        <source url="https://jhey.dev/rss/writing.xml">Jhey Tompkins writing RSS feed</source>
        
          <category>HTML</category>
        
          <category>Animation</category>
        
          <category>CSS</category>
        
      </item>
    
      <item>
        <title>Building Chrometober</title>
        <link>https://web.dev/building-chrometober/</link>
        <author>rss@jhey.dev (Jhey Tompkins)</author>
        <description><![CDATA[<p>Check out <a href="https://web.dev/building-chrometober/">this post</a> from Jhey over on <a href="https://web.dev/building-chrometober/">web.dev</a>!</p>]]></description>
        <pubDate>Mon, 31 Oct 2022 00:00:00 GMT</pubDate>
        <guid isPermaLink="true">https://web.dev/building-chrometober/</guid>
        <source url="https://jhey.dev/rss/writing.xml">Jhey Tompkins writing RSS feed</source>
        
          <category>Web Platform</category>
        
          <category>JavaScript</category>
        
          <category>CSS</category>
        
          <category>Astro</category>
        
          <category>Creative</category>
        
      </item>
    
      <item>
        <title>Speedy CSS Tip! Animated Loader</title>
        <link>https://web.dev/speedy-css-tip-animated-loader/</link>
        <author>rss@jhey.dev (Jhey Tompkins)</author>
        <description><![CDATA[<p>Check out <a href="https://web.dev/speedy-css-tip-animated-loader/">this post</a> from Jhey over on <a href="https://web.dev/speedy-css-tip-animated-loader/">web.dev</a>!</p>]]></description>
        <pubDate>Thu, 22 Sep 2022 00:00:00 GMT</pubDate>
        <guid isPermaLink="true">https://web.dev/speedy-css-tip-animated-loader/</guid>
        <source url="https://jhey.dev/rss/writing.xml">Jhey Tompkins writing RSS feed</source>
        
          <category>Animation</category>
        
          <category>CSS</category>
        
          <category>HTML</category>
        
      </item>
    
      <item>
        <title>Pop-ups: They're making a resurgence!</title>
        <link>https://developer.chrome.com/blog/pop-ups-theyre-making-a-resurgence/</link>
        <author>rss@jhey.dev (Jhey Tompkins)</author>
        <description><![CDATA[<p>Check out <a href="https://developer.chrome.com/blog/pop-ups-theyre-making-a-resurgence/">this post</a> from Jhey over on <a href="https://developer.chrome.com/blog/pop-ups-theyre-making-a-resurgence/">developer.chrome.com</a>!</p>]]></description>
        <pubDate>Tue, 13 Sep 2022 00:00:00 GMT</pubDate>
        <guid isPermaLink="true">https://developer.chrome.com/blog/pop-ups-theyre-making-a-resurgence/</guid>
        <source url="https://jhey.dev/rss/writing.xml">Jhey Tompkins writing RSS feed</source>
        
          <category>Web Platform</category>
        
          <category>HTML</category>
        
          <category>JavaScript</category>
        
          <category>CSS</category>
        
      </item>
    
      <item>
        <title>Is it :modal?</title>
        <link>https://web.dev/is-it-modal/</link>
        <author>rss@jhey.dev (Jhey Tompkins)</author>
        <description><![CDATA[<p>Check out <a href="https://web.dev/is-it-modal/">this post</a> from Jhey over on <a href="https://web.dev/is-it-modal/">web.dev</a>!</p>]]></description>
        <pubDate>Fri, 02 Sep 2022 00:00:00 GMT</pubDate>
        <guid isPermaLink="true">https://web.dev/is-it-modal/</guid>
        <source url="https://jhey.dev/rss/writing.xml">Jhey Tompkins writing RSS feed</source>
        
          <category>CSS</category>
        
          <category>Web Platform</category>
        
      </item>
    
      <item>
        <title>Meet the top layer: A solution to z-index: 10000</title>
        <link>https://developer.chrome.com/blog/what-is-the-top-layer/</link>
        <author>rss@jhey.dev (Jhey Tompkins)</author>
        <description><![CDATA[<p>Check out <a href="https://developer.chrome.com/blog/what-is-the-top-layer/">this post</a> from Jhey over on <a href="https://developer.chrome.com/blog/what-is-the-top-layer/">developer.chrome.com</a>!</p>]]></description>
        <pubDate>Mon, 22 Aug 2022 00:00:00 GMT</pubDate>
        <guid isPermaLink="true">https://developer.chrome.com/blog/what-is-the-top-layer/</guid>
        <source url="https://jhey.dev/rss/writing.xml">Jhey Tompkins writing RSS feed</source>
        
          <category>Web Platform</category>
        
          <category>CSS</category>
        
          <category>HTML</category>
        
      </item>
    
      <item>
        <title>:has(): the family selector</title>
        <link>https://developer.chrome.com/blog/has-m105/</link>
        <author>rss@jhey.dev (Jhey Tompkins)</author>
        <description><![CDATA[<p>Check out <a href="https://developer.chrome.com/blog/has-m105/">this post</a> from Jhey over on <a href="https://developer.chrome.com/blog/has-m105/">developer.chrome.com</a>!</p>]]></description>
        <pubDate>Wed, 03 Aug 2022 00:00:00 GMT</pubDate>
        <guid isPermaLink="true">https://developer.chrome.com/blog/has-m105/</guid>
        <source url="https://jhey.dev/rss/writing.xml">Jhey Tompkins writing RSS feed</source>
        
          <category>Web Platform</category>
        
          <category>CSS</category>
        
          <category>HTML</category>
        
      </item>
    
      <item>
        <title>An Interactive Starry Backdrop for Content</title>
        <link>https://css-tricks.com/an-interactive-starry-backdrop-for-content/</link>
        <author>rss@jhey.dev (Jhey Tompkins)</author>
        <description><![CDATA[<p>Check out <a href="https://css-tricks.com/an-interactive-starry-backdrop-for-content/">this post</a> from Jhey over on <a href="https://css-tricks.com/an-interactive-starry-backdrop-for-content/">CSS Tricks</a>!</p>]]></description>
        <pubDate>Wed, 18 May 2022 00:00:00 GMT</pubDate>
        <guid isPermaLink="true">https://css-tricks.com/an-interactive-starry-backdrop-for-content/</guid>
        <source url="https://jhey.dev/rss/writing.xml">Jhey Tompkins writing RSS feed</source>
        
          <category>Canvas</category>
        
          <category>JavaScript</category>
        
          <category>Animation</category>
        
          <category>Creative</category>
        
      </item>
    
      <item>
        <title>A CSS slinky in 3D? Challenge accepted</title>
        <link>https://css-tricks.com/a-css-slinky-in-3d/</link>
        <author>rss@jhey.dev (Jhey Tompkins)</author>
        <description><![CDATA[<p>Check out <a href="https://css-tricks.com/a-css-slinky-in-3d/">this post</a> from Jhey over on <a href="https://css-tricks.com/a-css-slinky-in-3d/">CSS Tricks</a>!</p>]]></description>
        <pubDate>Thu, 12 May 2022 00:00:00 GMT</pubDate>
        <guid isPermaLink="true">https://css-tricks.com/a-css-slinky-in-3d/</guid>
        <source url="https://jhey.dev/rss/writing.xml">Jhey Tompkins writing RSS feed</source>
        
          <category>3D</category>
        
          <category>CSS</category>
        
          <category>Animation</category>
        
      </item>
    
      <item>
        <title>Creating the DigitalOcean logo in 3D with CSS</title>
        <link>https://css-tricks.com/creating-the-digitalocean-logo-in-3d-with-css/</link>
        <author>rss@jhey.dev (Jhey Tompkins)</author>
        <description><![CDATA[<p>Check out <a href="https://css-tricks.com/creating-the-digitalocean-logo-in-3d-with-css/">this post</a> from Jhey over on <a href="https://css-tricks.com/creating-the-digitalocean-logo-in-3d-with-css/">CSS Tricks</a>!</p>]]></description>
        <pubDate>Fri, 29 Apr 2022 00:00:00 GMT</pubDate>
        <guid isPermaLink="true">https://css-tricks.com/creating-the-digitalocean-logo-in-3d-with-css/</guid>
        <source url="https://jhey.dev/rss/writing.xml">Jhey Tompkins writing RSS feed</source>
        
          <category>3D</category>
        
          <category>CSS</category>
        
          <category>Animation</category>
        
      </item>
    
      <item>
        <title>What if our sliders actually slid?</title>
        <link>https://www.smashingmagazine.com/2022/04/what-if-sliders-actually-slid-html-element-input-range/</link>
        <author>rss@jhey.dev (Jhey Tompkins)</author>
        <description><![CDATA[<p>Check out <a href="https://www.smashingmagazine.com/2022/04/what-if-sliders-actually-slid-html-element-input-range/">this post</a> from Jhey over on <a href="https://www.smashingmagazine.com/2022/04/what-if-sliders-actually-slid-html-element-input-range/">Smashing Magazine</a>!</p>]]></description>
        <pubDate>Mon, 25 Apr 2022 00:00:00 GMT</pubDate>
        <guid isPermaLink="true">https://www.smashingmagazine.com/2022/04/what-if-sliders-actually-slid-html-element-input-range/</guid>
        <source url="https://jhey.dev/rss/writing.xml">Jhey Tompkins writing RSS feed</source>
        
          <category>GreenSock</category>
        
          <category>JavaScript</category>
        
          <category>Creative</category>
        
      </item>
    
      <item>
        <title>A guide to audio visualization with JavaScript and GSAP (pt.2)</title>
        <link>https://www.smashingmagazine.com/2022/03/audio-visualization-javascript-gsap-part2/</link>
        <author>rss@jhey.dev (Jhey Tompkins)</author>
        <description><![CDATA[<p>Check out <a href="https://www.smashingmagazine.com/2022/03/audio-visualization-javascript-gsap-part2/">this post</a> from Jhey over on <a href="https://www.smashingmagazine.com/2022/03/audio-visualization-javascript-gsap-part2/">Smashing Magazine</a>!</p>]]></description>
        <pubDate>Wed, 09 Mar 2022 00:00:00 GMT</pubDate>
        <guid isPermaLink="true">https://www.smashingmagazine.com/2022/03/audio-visualization-javascript-gsap-part2/</guid>
        <source url="https://jhey.dev/rss/writing.xml">Jhey Tompkins writing RSS feed</source>
        
          <category>JavaScript</category>
        
          <category>GreenSock</category>
        
          <category>React</category>
        
          <category>Audio</category>
        
          <category>Canvas</category>
        
      </item>
    
      <item>
        <title>A guide to audio visualization with JavaScript and GSAP (pt.1)</title>
        <link>https://www.smashingmagazine.com/2022/03/audio-visualization-javascript-gsap-part1/</link>
        <author>rss@jhey.dev (Jhey Tompkins)</author>
        <description><![CDATA[<p>Check out <a href="https://www.smashingmagazine.com/2022/03/audio-visualization-javascript-gsap-part1/">this post</a> from Jhey over on <a href="https://www.smashingmagazine.com/2022/03/audio-visualization-javascript-gsap-part1/">Smashing Magazine</a>!</p>]]></description>
        <pubDate>Wed, 02 Mar 2022 00:00:00 GMT</pubDate>
        <guid isPermaLink="true">https://www.smashingmagazine.com/2022/03/audio-visualization-javascript-gsap-part1/</guid>
        <source url="https://jhey.dev/rss/writing.xml">Jhey Tompkins writing RSS feed</source>
        
          <category>JavaScript</category>
        
          <category>GreenSock</category>
        
          <category>Animation</category>
        
          <category>Audio</category>
        
          <category>Canvas</category>
        
      </item>
    
      <item>
        <title>How to Make a Pure CSS 3D Package Toggle</title>
        <link>https://css-tricks.com/how-to-make-a-pure-css-3d-package-toggle/</link>
        <author>rss@jhey.dev (Jhey Tompkins)</author>
        <description><![CDATA[<p>Check out <a href="https://css-tricks.com/how-to-make-a-pure-css-3d-package-toggle/">this post</a> from Jhey over on <a href="https://css-tricks.com/how-to-make-a-pure-css-3d-package-toggle/">CSS Tricks</a>!</p>]]></description>
        <pubDate>Wed, 12 Jan 2022 00:00:00 GMT</pubDate>
        <guid isPermaLink="true">https://css-tricks.com/how-to-make-a-pure-css-3d-package-toggle/</guid>
        <source url="https://jhey.dev/rss/writing.xml">Jhey Tompkins writing RSS feed</source>
        
          <category>Animation</category>
        
          <category>CSS</category>
        
          <category>3D</category>
        
      </item>
    
      <item>
        <title>3D CSS flippy snaps with React and GSAP</title>
        <link>https://www.smashingmagazine.com/2021/11/3d-css-flippy-snaps-react-greensock/</link>
        <author>rss@jhey.dev (Jhey Tompkins)</author>
        <description><![CDATA[<p>Check out <a href="https://www.smashingmagazine.com/2021/11/3d-css-flippy-snaps-react-greensock/">this post</a> from Jhey over on <a href="https://www.smashingmagazine.com/2021/11/3d-css-flippy-snaps-react-greensock/">Smashing Magazine</a>!</p>]]></description>
        <pubDate>Mon, 29 Nov 2021 00:00:00 GMT</pubDate>
        <guid isPermaLink="true">https://www.smashingmagazine.com/2021/11/3d-css-flippy-snaps-react-greensock/</guid>
        <source url="https://jhey.dev/rss/writing.xml">Jhey Tompkins writing RSS feed</source>
        
          <category>React</category>
        
          <category>CSS</category>
        
          <category>GreenSock</category>
        
          <category>JavaScript</category>
        
          <category>3D</category>
        
      </item>
    
      <item>
        <title>Parallax powered by CSS custom properties</title>
        <link>https://css-tricks.com/parallax-powered-by-css-custom-properties/</link>
        <author>rss@jhey.dev (Jhey Tompkins)</author>
        <description><![CDATA[<p>Check out <a href="https://css-tricks.com/parallax-powered-by-css-custom-properties/">this post</a> from Jhey over on <a href="https://css-tricks.com/parallax-powered-by-css-custom-properties/">CSS Tricks</a>!</p>]]></description>
        <pubDate>Fri, 19 Nov 2021 00:00:00 GMT</pubDate>
        <guid isPermaLink="true">https://css-tricks.com/parallax-powered-by-css-custom-properties/</guid>
        <source url="https://jhey.dev/rss/writing.xml">Jhey Tompkins writing RSS feed</source>
        
          <category>CSS</category>
        
          <category>JavaScript</category>
        
          <category>Creative</category>
        
      </item>
    
      <item>
        <title>print.css but not how you know it – Creating a 3D CSS printer</title>
        <link>https://www.sitepoint.com/3d-css-printer/</link>
        <author>rss@jhey.dev (Jhey Tompkins)</author>
        <description><![CDATA[<p>Check out <a href="https://www.sitepoint.com/3d-css-printer/">this post</a> from Jhey over on <a href="https://www.sitepoint.com/3d-css-printer/">SitePoint</a>!</p>]]></description>
        <pubDate>Wed, 16 Jun 2021 00:00:00 GMT</pubDate>
        <guid isPermaLink="true">https://www.sitepoint.com/3d-css-printer/</guid>
        <source url="https://jhey.dev/rss/writing.xml">Jhey Tompkins writing RSS feed</source>
        
          <category>JavaScript</category>
        
          <category>CSS</category>
        
          <category>Creative</category>
        
      </item>
    
      <item>
        <title>Can we create a resize hack with container queries?</title>
        <link>https://css-tricks.com/can-we-create-a-resize-hack-with-container-queries/</link>
        <author>rss@jhey.dev (Jhey Tompkins)</author>
        <description><![CDATA[<p>Check out <a href="https://css-tricks.com/can-we-create-a-resize-hack-with-container-queries/">this post</a> from Jhey over on <a href="https://css-tricks.com/can-we-create-a-resize-hack-with-container-queries/">CSS Tricks</a>!</p>]]></description>
        <pubDate>Thu, 20 May 2021 00:00:00 GMT</pubDate>
        <guid isPermaLink="true">https://css-tricks.com/can-we-create-a-resize-hack-with-container-queries/</guid>
        <source url="https://jhey.dev/rss/writing.xml">Jhey Tompkins writing RSS feed</source>
        
          <category>CSS</category>
        
          <category>Web Platform</category>
        
          <category>Creative</category>
        
      </item>
    
      <item>
        <title>Get started with React by building a Whac-A-Mole game</title>
        <link>https://www.smashingmagazine.com/2021/05/get-started-whac-a-mole-react-game/</link>
        <author>rss@jhey.dev (Jhey Tompkins)</author>
        <description><![CDATA[<p>Check out <a href="https://www.smashingmagazine.com/2021/05/get-started-whac-a-mole-react-game/">this post</a> from Jhey over on <a href="https://www.smashingmagazine.com/2021/05/get-started-whac-a-mole-react-game/">Smashing Magazine</a>!</p>]]></description>
        <pubDate>Mon, 10 May 2021 00:00:00 GMT</pubDate>
        <guid isPermaLink="true">https://www.smashingmagazine.com/2021/05/get-started-whac-a-mole-react-game/</guid>
        <source url="https://jhey.dev/rss/writing.xml">Jhey Tompkins writing RSS feed</source>
        
          <category>React</category>
        
          <category>JavaScript</category>
        
          <category>Creative</category>
        
      </item>
    
      <item>
        <title>Going "Meta GSAP": The quest for perfect infinite scrolling</title>
        <link>https://css-tricks.com/going-meta-gsap-the-quest-for-perfect-infinite-scrolling/</link>
        <author>rss@jhey.dev (Jhey Tompkins)</author>
        <description><![CDATA[<p>Check out <a href="https://css-tricks.com/going-meta-gsap-the-quest-for-perfect-infinite-scrolling/">this post</a> from Jhey over on <a href="https://css-tricks.com/going-meta-gsap-the-quest-for-perfect-infinite-scrolling/">CSS Tricks</a>!</p>]]></description>
        <pubDate>Wed, 14 Apr 2021 00:00:00 GMT</pubDate>
        <guid isPermaLink="true">https://css-tricks.com/going-meta-gsap-the-quest-for-perfect-infinite-scrolling/</guid>
        <source url="https://jhey.dev/rss/writing.xml">Jhey Tompkins writing RSS feed</source>
        
          <category>GreenSock</category>
        
          <category>JavaScript</category>
        
          <category>CSS</category>
        
          <category>Animation</category>
        
          <category>Creative</category>
        
      </item>
    
      <item>
        <title>Go Headless with Netlify CMS</title>
        <link>https://dev.to/jh3y/go-headless-with-netlify-cms-5gcm/stats</link>
        <author>rss@jhey.dev (Jhey Tompkins)</author>
        <description><![CDATA[<p>Check out <a href="https://dev.to/jh3y/go-headless-with-netlify-cms-5gcm/stats">this post</a> from Jhey over on <a href="https://dev.to/jh3y/go-headless-with-netlify-cms-5gcm/stats">DEV</a>!</p>]]></description>
        <pubDate>Wed, 31 Mar 2021 00:00:00 GMT</pubDate>
        <guid isPermaLink="true">https://dev.to/jh3y/go-headless-with-netlify-cms-5gcm/stats</guid>
        <source url="https://jhey.dev/rss/writing.xml">Jhey Tompkins writing RSS feed</source>
        
          <category>JavaScript</category>
        
          <category>Netlify</category>
        
      </item>
    
      <item>
        <title>Squeaky portraits: Having fun with the CSS path() function</title>
        <link>https://www.sitepoint.com/css-path-function-squeaky-portraits/</link>
        <author>rss@jhey.dev (Jhey Tompkins)</author>
        <description><![CDATA[<p>Check out <a href="https://www.sitepoint.com/css-path-function-squeaky-portraits/">this post</a> from Jhey over on <a href="https://www.sitepoint.com/css-path-function-squeaky-portraits/">SitePoint</a>!</p>]]></description>
        <pubDate>Thu, 25 Mar 2021 00:00:00 GMT</pubDate>
        <guid isPermaLink="true">https://www.sitepoint.com/css-path-function-squeaky-portraits/</guid>
        <source url="https://jhey.dev/rss/writing.xml">Jhey Tompkins writing RSS feed</source>
        
          <category>CSS</category>
        
          <category>Web Platform</category>
        
          <category>Animation</category>
        
          <category>Creative</category>
        
      </item>
    
      <item>
        <title>Paint your Github profile with serverless</title>
        <link>https://dev.to/jh3y/paint-your-github-profile-with-serverless-15i7</link>
        <author>rss@jhey.dev (Jhey Tompkins)</author>
        <description><![CDATA[<p>Check out <a href="https://dev.to/jh3y/paint-your-github-profile-with-serverless-15i7">this post</a> from Jhey over on <a href="https://dev.to/jh3y/paint-your-github-profile-with-serverless-15i7">DEV</a>!</p>]]></description>
        <pubDate>Mon, 08 Mar 2021 00:00:00 GMT</pubDate>
        <guid isPermaLink="true">https://dev.to/jh3y/paint-your-github-profile-with-serverless-15i7</guid>
        <source url="https://jhey.dev/rss/writing.xml">Jhey Tompkins writing RSS feed</source>
        
          <category>JavaScript</category>
        
          <category>Node</category>
        
          <category>Serverless</category>
        
          <category>Netlify</category>
        
      </item>
    
      <item>
        <title>Exploring @property and it's animating powers</title>
        <link>https://css-tricks.com/exploring-property-and-its-animating-powers/</link>
        <author>rss@jhey.dev (Jhey Tompkins)</author>
        <description><![CDATA[<p>Check out <a href="https://css-tricks.com/exploring-property-and-its-animating-powers/">this post</a> from Jhey over on <a href="https://css-tricks.com/exploring-property-and-its-animating-powers/">CSS Tricks</a>!</p>]]></description>
        <pubDate>Thu, 04 Mar 2021 00:00:00 GMT</pubDate>
        <guid isPermaLink="true">https://css-tricks.com/exploring-property-and-its-animating-powers/</guid>
        <source url="https://jhey.dev/rss/writing.xml">Jhey Tompkins writing RSS feed</source>
        
          <category>CSS</category>
        
          <category>Animation</category>
        
          <category>Web Platform</category>
        
      </item>
    
      <item>
        <title>Add a little whimsy to your forms</title>
        <link>https://dev.to/jh3y/add-a-little-whimsy-to-your-forms-2c1f</link>
        <author>rss@jhey.dev (Jhey Tompkins)</author>
        <description><![CDATA[<p>Check out <a href="https://dev.to/jh3y/add-a-little-whimsy-to-your-forms-2c1f">this post</a> from Jhey over on <a href="https://dev.to/jh3y/add-a-little-whimsy-to-your-forms-2c1f">DEV</a>!</p>]]></description>
        <pubDate>Mon, 22 Feb 2021 00:00:00 GMT</pubDate>
        <guid isPermaLink="true">https://dev.to/jh3y/add-a-little-whimsy-to-your-forms-2c1f</guid>
        <source url="https://jhey.dev/rss/writing.xml">Jhey Tompkins writing RSS feed</source>
        
          <category>JavaScript</category>
        
          <category>Canvas</category>
        
          <category>Animation</category>
        
      </item>
    
      <item>
        <title>How to: Cursor tracking parallax</title>
        <link>https://dev.to/jh3y/how-to-cursor-tracking-parallax-52cf</link>
        <author>rss@jhey.dev (Jhey Tompkins)</author>
        <description><![CDATA[<p>Check out <a href="https://dev.to/jh3y/how-to-cursor-tracking-parallax-52cf">this post</a> from Jhey over on <a href="https://dev.to/jh3y/how-to-cursor-tracking-parallax-52cf">DEV</a>!</p>]]></description>
        <pubDate>Thu, 18 Feb 2021 00:00:00 GMT</pubDate>
        <guid isPermaLink="true">https://dev.to/jh3y/how-to-cursor-tracking-parallax-52cf</guid>
        <source url="https://jhey.dev/rss/writing.xml">Jhey Tompkins writing RSS feed</source>
        
          <category>JavaScript</category>
        
          <category>CSS</category>
        
          <category>Creative</category>
        
      </item>
    
      <item>
        <title>Creating directionally lit 3D buttons with CSS</title>
        <link>https://www.sitepoint.com/creating-directionally-lit-3d-buttons-with-css/</link>
        <author>rss@jhey.dev (Jhey Tompkins)</author>
        <description><![CDATA[<p>Check out <a href="https://www.sitepoint.com/creating-directionally-lit-3d-buttons-with-css/">this post</a> from Jhey over on <a href="https://www.sitepoint.com/creating-directionally-lit-3d-buttons-with-css/">SitePoint</a>!</p>]]></description>
        <pubDate>Tue, 16 Feb 2021 00:00:00 GMT</pubDate>
        <guid isPermaLink="true">https://www.sitepoint.com/creating-directionally-lit-3d-buttons-with-css/</guid>
        <source url="https://jhey.dev/rss/writing.xml">Jhey Tompkins writing RSS feed</source>
        
          <category>JavaScript</category>
        
          <category>CSS</category>
        
          <category>Creative</category>
        
          <category>3D</category>
        
      </item>
    
      <item>
        <title>Recreate the Cyberpunk 2077 button glitch effect in CSS</title>
        <link>https://www.sitepoint.com/recreate-the-cyberpunk-2077-button-glitch-effect-in-css/</link>
        <author>rss@jhey.dev (Jhey Tompkins)</author>
        <description><![CDATA[<p>Check out <a href="https://www.sitepoint.com/recreate-the-cyberpunk-2077-button-glitch-effect-in-css/">this post</a> from Jhey over on <a href="https://www.sitepoint.com/recreate-the-cyberpunk-2077-button-glitch-effect-in-css/">SitePoint</a>!</p>]]></description>
        <pubDate>Wed, 16 Dec 2020 00:00:00 GMT</pubDate>
        <guid isPermaLink="true">https://www.sitepoint.com/recreate-the-cyberpunk-2077-button-glitch-effect-in-css/</guid>
        <source url="https://jhey.dev/rss/writing.xml">Jhey Tompkins writing RSS feed</source>
        
          <category>CSS</category>
        
          <category>Animation</category>
        
          <category>Creative</category>
        
      </item>
    
      <item>
        <title>Playfulness in code: Supercharge your learning by having fun</title>
        <link>https://www.smashingmagazine.com/2020/11/playfulness-code-supercharge-fun-learning/</link>
        <author>rss@jhey.dev (Jhey Tompkins)</author>
        <description><![CDATA[<p>Check out <a href="https://www.smashingmagazine.com/2020/11/playfulness-code-supercharge-fun-learning/">this post</a> from Jhey over on <a href="https://www.smashingmagazine.com/2020/11/playfulness-code-supercharge-fun-learning/">Smashing Magazine</a>!</p>]]></description>
        <pubDate>Wed, 25 Nov 2020 00:00:00 GMT</pubDate>
        <guid isPermaLink="true">https://www.smashingmagazine.com/2020/11/playfulness-code-supercharge-fun-learning/</guid>
        <source url="https://jhey.dev/rss/writing.xml">Jhey Tompkins writing RSS feed</source>
        
          <category>Creative</category>
        
          <category>Thoughts</category>
        
          <category>Whimsy</category>
        
      </item>
    
      <item>
        <title>CSS in 3D: Learning to think in cubes instead of boxes</title>
        <link>https://css-tricks.com/css-in-3d-learning-to-think-in-cubes-instead-of-boxes/</link>
        <author>rss@jhey.dev (Jhey Tompkins)</author>
        <description><![CDATA[<p>Check out <a href="https://css-tricks.com/css-in-3d-learning-to-think-in-cubes-instead-of-boxes/">this post</a> from Jhey over on <a href="https://css-tricks.com/css-in-3d-learning-to-think-in-cubes-instead-of-boxes/">CSS Tricks</a>!</p>]]></description>
        <pubDate>Fri, 23 Oct 2020 00:00:00 GMT</pubDate>
        <guid isPermaLink="true">https://css-tricks.com/css-in-3d-learning-to-think-in-cubes-instead-of-boxes/</guid>
        <source url="https://jhey.dev/rss/writing.xml">Jhey Tompkins writing RSS feed</source>
        
          <category>CSS</category>
        
          <category>3D</category>
        
          <category>Creative</category>
        
          <category>JavaScript</category>
        
      </item>
    
      <item>
        <title>It's good to talk: Thoughts and feelings on creative wellness</title>
        <link>https://www.smashingmagazine.com/2020/07/thoughts-feelings-creative-wellness/</link>
        <author>rss@jhey.dev (Jhey Tompkins)</author>
        <description><![CDATA[<p>Check out <a href="https://www.smashingmagazine.com/2020/07/thoughts-feelings-creative-wellness/">this post</a> from Jhey over on <a href="https://www.smashingmagazine.com/2020/07/thoughts-feelings-creative-wellness/">Smashing Magazine</a>!</p>]]></description>
        <pubDate>Fri, 17 Jul 2020 00:00:00 GMT</pubDate>
        <guid isPermaLink="true">https://www.smashingmagazine.com/2020/07/thoughts-feelings-creative-wellness/</guid>
        <source url="https://jhey.dev/rss/writing.xml">Jhey Tompkins writing RSS feed</source>
        
          <category>Health</category>
        
          <category>Thoughts</category>
        
      </item>
    
      <item>
        <title>Write for yourself so that one day you might write for those you look up to</title>
        <link>https://dev.to/jh3y/write-for-yourself-so-that-one-day-you-might-write-for-those-you-look-up-to-38ld</link>
        <author>rss@jhey.dev (Jhey Tompkins)</author>
        <description><![CDATA[<p>Check out <a href="https://dev.to/jh3y/write-for-yourself-so-that-one-day-you-might-write-for-those-you-look-up-to-38ld">this post</a> from Jhey over on <a href="https://dev.to/jh3y/write-for-yourself-so-that-one-day-you-might-write-for-those-you-look-up-to-38ld">DEV</a>!</p>]]></description>
        <pubDate>Sun, 28 Jun 2020 00:00:00 GMT</pubDate>
        <guid isPermaLink="true">https://dev.to/jh3y/write-for-yourself-so-that-one-day-you-might-write-for-those-you-look-up-to-38ld</guid>
        <source url="https://jhey.dev/rss/writing.xml">Jhey Tompkins writing RSS feed</source>
        
          <category>Thoughts</category>
        
          <category>Creative</category>
        
      </item>
    
      <item>
        <title>Starting a streaming journey</title>
        <link>https://dev.to/jh3y/starting-a-streaming-journey-2jj5</link>
        <author>rss@jhey.dev (Jhey Tompkins)</author>
        <description><![CDATA[<p>Check out <a href="https://dev.to/jh3y/starting-a-streaming-journey-2jj5">this post</a> from Jhey over on <a href="https://dev.to/jh3y/starting-a-streaming-journey-2jj5">DEV</a>!</p>]]></description>
        <pubDate>Sun, 21 Jun 2020 00:00:00 GMT</pubDate>
        <guid isPermaLink="true">https://dev.to/jh3y/starting-a-streaming-journey-2jj5</guid>
        <source url="https://jhey.dev/rss/writing.xml">Jhey Tompkins writing RSS feed</source>
        
          <category>Streaming</category>
        
          <category>Creative</category>
        
          <category>Thoughts</category>
        
      </item>
    
      <item>
        <title>Advice for complex CSS illustrations</title>
        <link>https://css-tricks.com/advice-for-complex-css-illustrations/</link>
        <author>rss@jhey.dev (Jhey Tompkins)</author>
        <description><![CDATA[<p>Check out <a href="https://css-tricks.com/advice-for-complex-css-illustrations/">this post</a> from Jhey over on <a href="https://css-tricks.com/advice-for-complex-css-illustrations/">CSS Tricks</a>!</p>]]></description>
        <pubDate>Sat, 20 Jun 2020 00:00:00 GMT</pubDate>
        <guid isPermaLink="true">https://css-tricks.com/advice-for-complex-css-illustrations/</guid>
        <source url="https://jhey.dev/rss/writing.xml">Jhey Tompkins writing RSS feed</source>
        
          <category>CSS</category>
        
          <category>HTML</category>
        
          <category>Animation</category>
        
      </item>
    
      <item>
        <title>Create a responsive CSS motion path? Sure we can!</title>
        <link>https://css-tricks.com/create-a-responsive-css-motion-path-sure-we-can/</link>
        <author>rss@jhey.dev (Jhey Tompkins)</author>
        <description><![CDATA[<p>Check out <a href="https://css-tricks.com/create-a-responsive-css-motion-path-sure-we-can/">this post</a> from Jhey over on <a href="https://css-tricks.com/create-a-responsive-css-motion-path-sure-we-can/">CSS Tricks</a>!</p>]]></description>
        <pubDate>Wed, 15 Apr 2020 00:00:00 GMT</pubDate>
        <guid isPermaLink="true">https://css-tricks.com/create-a-responsive-css-motion-path-sure-we-can/</guid>
        <source url="https://jhey.dev/rss/writing.xml">Jhey Tompkins writing RSS feed</source>
        
          <category>CSS</category>
        
          <category>JavaScript</category>
        
          <category>Animation</category>
        
      </item>
    
      <item>
        <title>Animated Matryoshka dolls in CSS</title>
        <link>https://css-tricks.com/animated-matryoshka-dolls-in-css/</link>
        <author>rss@jhey.dev (Jhey Tompkins)</author>
        <description><![CDATA[<p>Check out <a href="https://css-tricks.com/animated-matryoshka-dolls-in-css/">this post</a> from Jhey over on <a href="https://css-tricks.com/animated-matryoshka-dolls-in-css/">CSS Tricks</a>!</p>]]></description>
        <pubDate>Thu, 27 Feb 2020 00:00:00 GMT</pubDate>
        <guid isPermaLink="true">https://css-tricks.com/animated-matryoshka-dolls-in-css/</guid>
        <source url="https://jhey.dev/rss/writing.xml">Jhey Tompkins writing RSS feed</source>
        
          <category>Animation</category>
        
          <category>CSS</category>
        
          <category>Creative</category>
        
      </item>
    
      <item>
        <title>The power (and fun) of scope with CSS custom properties</title>
        <link>https://css-tricks.com/the-power-and-fun-of-scope-with-css-custom-properties/</link>
        <author>rss@jhey.dev (Jhey Tompkins)</author>
        <description><![CDATA[<p>Check out <a href="https://css-tricks.com/the-power-and-fun-of-scope-with-css-custom-properties/">this post</a> from Jhey over on <a href="https://css-tricks.com/the-power-and-fun-of-scope-with-css-custom-properties/">CSS Tricks</a>!</p>]]></description>
        <pubDate>Wed, 27 Nov 2019 00:00:00 GMT</pubDate>
        <guid isPermaLink="true">https://css-tricks.com/the-power-and-fun-of-scope-with-css-custom-properties/</guid>
        <source url="https://jhey.dev/rss/writing.xml">Jhey Tompkins writing RSS feed</source>
        
          <category>CSS</category>
        
          <category>HTML</category>
        
          <category>Animation</category>
        
      </item>
    
      <item>
        <title>Ghost buttons with directional awareness in CSS</title>
        <link>https://css-tricks.com/ghost-buttons-with-directional-awareness-in-css/</link>
        <author>rss@jhey.dev (Jhey Tompkins)</author>
        <description><![CDATA[<p>Check out <a href="https://css-tricks.com/ghost-buttons-with-directional-awareness-in-css/">this post</a> from Jhey over on <a href="https://css-tricks.com/ghost-buttons-with-directional-awareness-in-css/">CSS Tricks</a>!</p>]]></description>
        <pubDate>Fri, 13 Sep 2019 00:00:00 GMT</pubDate>
        <guid isPermaLink="true">https://css-tricks.com/ghost-buttons-with-directional-awareness-in-css/</guid>
        <source url="https://jhey.dev/rss/writing.xml">Jhey Tompkins writing RSS feed</source>
        
          <category>HTML</category>
        
          <category>CSS</category>
        
          <category>Creative</category>
        
      </item>
    
      <item>
        <title>React hooks in 5 minutes</title>
        <link>https://codeburst.io/react-hooks-in-5-minutes-1180f1aa0449</link>
        <author>rss@jhey.dev (Jhey Tompkins)</author>
        <description><![CDATA[<p>Check out <a href="https://codeburst.io/react-hooks-in-5-minutes-1180f1aa0449">this post</a> from Jhey over on <a href="https://codeburst.io/react-hooks-in-5-minutes-1180f1aa0449">Medium</a>!</p>]]></description>
        <pubDate>Mon, 14 Jan 2019 00:00:00 GMT</pubDate>
        <guid isPermaLink="true">https://codeburst.io/react-hooks-in-5-minutes-1180f1aa0449</guid>
        <source url="https://jhey.dev/rss/writing.xml">Jhey Tompkins writing RSS feed</source>
        
          <category>React</category>
        
          <category>JavaScript</category>
        
      </item>
    
      <item>
        <title>React Portals in 3 minutes</title>
        <link>https://codeburst.io/reacts-portals-in-3-minutes-9b2efb74e9a9</link>
        <author>rss@jhey.dev (Jhey Tompkins)</author>
        <description><![CDATA[<p>Check out <a href="https://codeburst.io/reacts-portals-in-3-minutes-9b2efb74e9a9">this post</a> from Jhey over on <a href="https://codeburst.io/reacts-portals-in-3-minutes-9b2efb74e9a9">Medium</a>!</p>]]></description>
        <pubDate>Wed, 05 Dec 2018 00:00:00 GMT</pubDate>
        <guid isPermaLink="true">https://codeburst.io/reacts-portals-in-3-minutes-9b2efb74e9a9</guid>
        <source url="https://jhey.dev/rss/writing.xml">Jhey Tompkins writing RSS feed</source>
        
          <category>React</category>
        
          <category>JavaScript</category>
        
          <category>Creative</category>
        
      </item>
    
      <item>
        <title>JavaScript async and await in 5 minutes</title>
        <link>https://medium.com/p/4081284ffed7</link>
        <author>rss@jhey.dev (Jhey Tompkins)</author>
        <description><![CDATA[<p>Check out <a href="https://medium.com/p/4081284ffed7">this post</a> from Jhey over on <a href="https://medium.com/p/4081284ffed7">Medium</a>!</p>]]></description>
        <pubDate>Thu, 25 Jan 2018 00:00:00 GMT</pubDate>
        <guid isPermaLink="true">https://medium.com/p/4081284ffed7</guid>
        <source url="https://jhey.dev/rss/writing.xml">Jhey Tompkins writing RSS feed</source>
        
          <category>JavaScript</category>
        
      </item>
    
      <item>
        <title>Pure CSS masonry layouts</title>
        <link>https://medium.com/me/stats/post/a8ede07ba31a</link>
        <author>rss@jhey.dev (Jhey Tompkins)</author>
        <description><![CDATA[<p>Check out <a href="https://medium.com/me/stats/post/a8ede07ba31a">this post</a> from Jhey over on <a href="https://medium.com/me/stats/post/a8ede07ba31a">Medium</a>!</p>]]></description>
        <pubDate>Thu, 21 Jan 2016 00:00:00 GMT</pubDate>
        <guid isPermaLink="true">https://medium.com/me/stats/post/a8ede07ba31a</guid>
        <source url="https://jhey.dev/rss/writing.xml">Jhey Tompkins writing RSS feed</source>
        
          <category>CSS</category>
        
          <category>HTML</category>
        
      </item>
    
      <item>
        <title>Throttling and Debouncing in JavaScript</title>
        <link>https://medium.com/p/b01cad5c8edf</link>
        <author>rss@jhey.dev (Jhey Tompkins)</author>
        <description><![CDATA[<p>Check out <a href="https://medium.com/p/b01cad5c8edf">this post</a> from Jhey over on <a href="https://medium.com/p/b01cad5c8edf">Medium</a>!</p>]]></description>
        <pubDate>Tue, 03 Feb 2015 00:00:00 GMT</pubDate>
        <guid isPermaLink="true">https://medium.com/p/b01cad5c8edf</guid>
        <source url="https://jhey.dev/rss/writing.xml">Jhey Tompkins writing RSS feed</source>
        
          <category>JavaScript</category>
        
      </item>
    
    </channel>
  </rss>
