<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Jackson Lewis</title>
    <description>The latest articles on DEV Community by Jackson Lewis (@jacksonlewis).</description>
    <link>https://dev.to/jacksonlewis</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F556823%2Ff696856b-5c5e-4e79-88b4-91a1fd52ff37.jpeg</url>
      <title>DEV Community: Jackson Lewis</title>
      <link>https://dev.to/jacksonlewis</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jacksonlewis"/>
    <language>en</language>
    <item>
      <title>TIL: HTML tags edition</title>
      <dc:creator>Jackson Lewis</dc:creator>
      <pubDate>Thu, 22 Apr 2021 16:01:23 +0000</pubDate>
      <link>https://dev.to/jacksonlewis/til-html-tags-edition-3b32</link>
      <guid>https://dev.to/jacksonlewis/til-html-tags-edition-3b32</guid>
      <description>&lt;p&gt;I have a week off work, &lt;em&gt;whey&lt;/em&gt;! And what better way to spend some of it then refreshing my knowledge of HTML tags. Now before you go bashing the keyboard labelling me a madman, hear me out. I feel HTML is deemed as 'the basic one' when people refer to programming languages, like you learn it on your first day then that's it, forever...&lt;/p&gt;

&lt;p&gt;Here's 10 &lt;em&gt;-ish&lt;/em&gt; tags I've found that I wanted to share, enjoy!&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;&amp;lt;dl&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;dt&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;dd&amp;gt;&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;First up is more of a 3-in-1, where &lt;code&gt;&amp;lt;dt&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;dd&amp;gt;&lt;/code&gt; are descendants to &lt;code&gt;&amp;lt;dl&amp;gt;&lt;/code&gt;. The Descriptive List element, contains a collection of terms &lt;code&gt;&amp;lt;dt&amp;gt;&lt;/code&gt;, and descriptions &lt;code&gt;&amp;lt;dd&amp;gt;&lt;/code&gt;. Let's look at an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;dl&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;dt&amp;gt;&lt;/span&gt;Client&lt;span class="nt"&gt;&amp;lt;/dt&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;dd&amp;gt;&lt;/span&gt;Apple&lt;span class="nt"&gt;&amp;lt;/dd&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;dt&amp;gt;&lt;/span&gt;Role&lt;span class="nt"&gt;&amp;lt;/dt&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;dd&amp;gt;&lt;/span&gt;Web development&lt;span class="nt"&gt;&amp;lt;/dd&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;dt&amp;gt;&lt;/span&gt;Year&lt;span class="nt"&gt;&amp;lt;/dt&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;dd&amp;gt;&lt;/span&gt;2019&lt;span class="nt"&gt;&amp;lt;/dd&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dl&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dl" rel="noopener noreferrer"&gt;MDN: Descriptive List element&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;&amp;lt;del&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;ins&amp;gt;&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The Deleted Text element, along with its &lt;code&gt;&amp;lt;ins&amp;gt;&lt;/code&gt; counterpart, highlight when text has been deleted, or added to the document respectively. You can also pass a &lt;code&gt;datetime&lt;/code&gt; attribute on both to signify a date/time when the contents within the tag were deleted or inserted.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;It was a &lt;span class="nt"&gt;&amp;lt;del&amp;gt;&lt;/span&gt;sunny&lt;span class="nt"&gt;&amp;lt;/del&amp;gt;&amp;lt;ins&amp;gt;&lt;/span&gt;rainy&lt;span class="nt"&gt;&amp;lt;/ins&amp;gt;&lt;/span&gt; day.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/del" rel="noopener noreferrer"&gt;MDN: Deleted Text element&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;&amp;lt;address&amp;gt;&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Now I did find this one cool, it signifies that the HTML inside provides contact information.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;address&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Westminster, London SW1A 1AA&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"mailto:info@example.com"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;info@example.com&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"tel:02056123456"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;020 5612 3456&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/address&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/address" rel="noopener noreferrer"&gt;MDN: Contact Address element&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;&amp;lt;time&amp;gt;&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;A way to specify a date or time in a more machine readable way. Could be great for including on your date stamp of a blog post.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Tickets will go on sale &lt;span class="nt"&gt;&amp;lt;time&lt;/span&gt; &lt;span class="na"&gt;datetime=&lt;/span&gt;&lt;span class="s"&gt;"07-06-21"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Monday 7th June&lt;span class="nt"&gt;&amp;lt;/time&amp;gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/time" rel="noopener noreferrer"&gt;MDN: Time element&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;&amp;lt;fieldset&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;legend&amp;gt;&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The Field Set element represents a collection of HTML form elements, which can be logically grouped. This may be handy where you have a quote form with multiple sections, and you can define the sections by &lt;code&gt;&amp;lt;fieldset&amp;gt;&lt;/code&gt;. The &lt;code&gt;&amp;lt;legend&amp;gt;&lt;/code&gt; tag is a label to the overall &lt;code&gt;&amp;lt;fieldset&amp;gt;&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;A neat trick is that you can pass the &lt;code&gt;disabled&lt;/code&gt; attribute to the &lt;code&gt;&amp;lt;fieldset&amp;gt;&lt;/code&gt; tag, which causes all form elements inside to also be disabled.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;form&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;fieldset&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;legend&amp;gt;&lt;/span&gt;Your details&lt;span class="nt"&gt;&amp;lt;/legend&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"tel"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"phone"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/fieldset&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/fieldset" rel="noopener noreferrer"&gt;MDN: Field Set element&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;&amp;lt;optgroup&amp;gt;&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;I did actually discover this one a few months back, however it's too good not to share anyway! If you have a &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt; element with a load of options, which could be split up into groups, then this is for you!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;select&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;optgroup&lt;/span&gt; &lt;span class="na"&gt;label=&lt;/span&gt;&lt;span class="s"&gt;"Audi"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;option&amp;gt;&lt;/span&gt;A3&lt;span class="nt"&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;option&amp;gt;&lt;/span&gt;A5&lt;span class="nt"&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;option&amp;gt;&lt;/span&gt;Q5&lt;span class="nt"&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/optgroup&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;optgroup&lt;/span&gt; &lt;span class="na"&gt;label=&lt;/span&gt;&lt;span class="s"&gt;"BMW"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;option&amp;gt;&lt;/span&gt;1 series&lt;span class="nt"&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;option&amp;gt;&lt;/span&gt;3 series&lt;span class="nt"&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;option&amp;gt;&lt;/span&gt;X4&lt;span class="nt"&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/optgroup&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/select&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/optgroup" rel="noopener noreferrer"&gt;MDN:  element&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;&amp;lt;output&amp;gt;&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;I love this, if you say have a quotation form that takes user input and spits out some sort of calculated result, that's exactly what &lt;code&gt;&amp;lt;output&amp;gt;&lt;/code&gt; is for!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;form&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"number"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"mileage"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"mileage"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Miles remaining: &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;output&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"remaining-miles"&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"mileage"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/output&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/output" rel="noopener noreferrer"&gt;MDN: Output element&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;&amp;lt;datalist&amp;gt;&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;While I can't see myself coming to use this very often, it's still good to know it's there, in the corner, waiting... You could think of it like being a &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt; element, but you can type in your own value if you wish.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;form&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;list=&lt;/span&gt;&lt;span class="s"&gt;"parts"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"part"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;datalist&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"parts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"Water pump"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"Battery"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"Spark plug"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"Front brake disk"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/datalist&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/datalist" rel="noopener noreferrer"&gt;MDN: Data List element&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;&amp;lt;progress&amp;gt;&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Again, limited use-cases yet still keeping it tucked away. Fairly self explanatory, the progress element indicates the progress of any given task. Perhaps you're running a process on a server and want to keep the user updated when it'll be complete?&lt;/p&gt;

&lt;p&gt;If you wanted greater styling control, you could probably do something like how custom radio buttons work, where the main element (&lt;code&gt;&amp;lt;progress&amp;gt;&lt;/code&gt;) is visually hidden and you use a &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; for the visual. Just remember to get your aria attributes correctly defined so it's all accessible!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;progress&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"upload-status"&lt;/span&gt; &lt;span class="na"&gt;max=&lt;/span&gt;&lt;span class="s"&gt;"100"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"30"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;30%&lt;span class="nt"&gt;&amp;lt;/progress&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/progress" rel="noopener noreferrer"&gt;MDN: Progress Indicator element&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Well there we have it! Who'd have thought refreshing my knowledge of mere HTML tags would prove so rewarding... Thanks for reading!&lt;/p&gt;

&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@valerysysoev?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Valery Sysoev&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/rocket?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>html</category>
      <category>todayilearned</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to preload images in WordPress</title>
      <dc:creator>Jackson Lewis</dc:creator>
      <pubDate>Mon, 19 Apr 2021 16:11:54 +0000</pubDate>
      <link>https://dev.to/jacksonlewis/how-to-preload-images-in-wordpress-48di</link>
      <guid>https://dev.to/jacksonlewis/how-to-preload-images-in-wordpress-48di</guid>
      <description>&lt;p&gt;Isn't it fun, the never ending game of web performance! This post will be looking using &lt;code&gt;preload&lt;/code&gt; on images, and more specifically at preloading the featured image of a WordPress post. So let's get stuck in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preload featured image of a post
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cd"&gt;/**
 * Preload attachment image, defaults to post thumbnail
 */&lt;/span&gt;
&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;preload_post_thumbnail&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;global&lt;/span&gt; &lt;span class="nv"&gt;$post&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="cd"&gt;/** Prevent preloading for specific content types or post types */&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nf"&gt;is_singular&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="cd"&gt;/** Adjust image size based on post type or other factor. */&lt;/span&gt;
    &lt;span class="nv"&gt;$image_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'full'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nf"&gt;is_singular&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'product'&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$image_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'woocommerce_single'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nf"&gt;is_singular&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'post'&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$image_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'large'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nv"&gt;$image_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;apply_filters&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'preload_post_thumbnail_image_size'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$image_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$post&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="cd"&gt;/** Get post thumbnail if an attachment ID isn't specified. */&lt;/span&gt;
    &lt;span class="nv"&gt;$thumbnail_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;apply_filters&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'preload_post_thumbnail_id'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;get_post_thumbnail_id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$post&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="no"&gt;ID&lt;/span&gt; &lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nv"&gt;$post&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="cd"&gt;/** Get the image */&lt;/span&gt;
    &lt;span class="nv"&gt;$image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;wp_get_attachment_image_src&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$thumbnail_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$image_size&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;$src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$additional_attr_array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nv"&gt;$additional_attr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$image&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$src&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$height&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$image&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="cd"&gt;/**
         * The following code which generates the srcset is plucked straight
         * out of wp_get_attachment_image() for consistency as it's important
         * that the output matches otherwise the preloading could become ineffective.
         */&lt;/span&gt;
        &lt;span class="nv"&gt;$image_meta&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;wp_get_attachment_metadata&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$thumbnail_id&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nb"&gt;is_array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$image_meta&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nv"&gt;$size_array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nf"&gt;absint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$width&lt;/span&gt; &lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nf"&gt;absint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$height&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nv"&gt;$srcset&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;wp_calculate_image_srcset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$size_array&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$src&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$image_meta&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$thumbnail_id&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nv"&gt;$sizes&lt;/span&gt;      &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;wp_calculate_image_sizes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$size_array&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$src&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$image_meta&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$thumbnail_id&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$srcset&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$sizes&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="k"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$attr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'sizes'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nv"&gt;$additional_attr_array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'imagesrcset'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$srcset&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="k"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$attr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'sizes'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="nv"&gt;$additional_attr_array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'imagesizes'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$sizes&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$additional_attr_array&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$name&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$value&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nv"&gt;$additional_attr&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="s2"&gt;="&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'"'&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$value&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'" '&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="cd"&gt;/** Early exit if no image is found. */&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cd"&gt;/** Output the link HTML tag */&lt;/span&gt;
    &lt;span class="nb"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'&amp;lt;link rel="preload" as="image" href="%s" %s/&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;esc_url&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$src&lt;/span&gt; &lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nv"&gt;$additional_attr&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nf"&gt;add_action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'wp_head'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'preload_post_thumbnail'&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Breakdown
&lt;/h3&gt;

&lt;p&gt;There's a fair bit going on here, so let's break it down and go through the process.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nf"&gt;is_singular&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first &lt;code&gt;if&lt;/code&gt; statement aims to prevent any preloading from taking place if any given condition is met. Perhaps you don't want to preload the featured image of a post that belongs to a certain post type, or just a specific page template.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$image_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'full'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nf"&gt;is_singular&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'product'&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$image_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'woocommerce_single'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nf"&gt;is_singular&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'post'&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$image_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'large'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nv"&gt;$image_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;apply_filters&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'preload_post_thumbnail_image_size'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$image_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$post&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we set the size of the image we want to load. This is actually very important, because if we preload the wrong size image, we waste user data. It's worth noting that auditing tools like Lighthouse will probably scream at you too! So it's vital that the image size requested here matches the size requested on the corresponding template.&lt;/p&gt;

&lt;p&gt;You could be fancy and create some form of an API, where this function to preload and the function that outputs the image tag are in the same place such as within a class. It could allow you to define in one place the image size and enforce consistency.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$thumbnail_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;apply_filters&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'preload_post_thumbnail_id'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;get_post_thumbnail_id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$post&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="no"&gt;ID&lt;/span&gt; &lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nv"&gt;$post&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="cd"&gt;/** Get the image */&lt;/span&gt;
&lt;span class="nv"&gt;$image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;wp_get_attachment_image_src&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$thumbnail_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$image_size&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$additional_attr_array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nv"&gt;$additional_attr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next we set the ID of the attachment, which by default is that of the featured image (also known as the thumbnail). We then call &lt;code&gt;wp_get_attachment_image_src()&lt;/code&gt;, passing our &lt;code&gt;$thumbnail_id&lt;/code&gt; and &lt;code&gt;$image_size&lt;/code&gt;. You'll see we also setup some variables which we'll be using in the next step.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$image&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$src&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$height&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$image&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * The following code which generates the srcset is plucked straight
     * out of wp_get_attachment_image() for consistency as it's important
     * that the output matches otherwise the preloading could become ineffective.
     */&lt;/span&gt;
    &lt;span class="nv"&gt;$image_meta&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;wp_get_attachment_metadata&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$thumbnail_id&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nb"&gt;is_array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$image_meta&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$size_array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nf"&gt;absint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$width&lt;/span&gt; &lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nf"&gt;absint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$height&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$srcset&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;wp_calculate_image_srcset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$size_array&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$src&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$image_meta&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$thumbnail_id&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$sizes&lt;/span&gt;      &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;wp_calculate_image_sizes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$size_array&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$src&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$image_meta&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$thumbnail_id&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$srcset&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$sizes&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="k"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$attr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'sizes'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nv"&gt;$additional_attr_array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'imagesrcset'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$srcset&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="k"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$attr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'sizes'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nv"&gt;$additional_attr_array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'imagesizes'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$sizes&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$additional_attr_array&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$name&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$value&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$additional_attr&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="s2"&gt;="&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'"'&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$value&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'" '&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cd"&gt;/** Early exit if no image is found. */&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This step is a little chunkier that the others, but what's going on is fairly simple. Most of what you see here is directly copied out of the core function &lt;code&gt;wp_get_attachment_image()&lt;/code&gt;, the function used to output the &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tag of an image. So, what it does is it calculates the &lt;code&gt;srcset&lt;/code&gt; and &lt;code&gt;sizes&lt;/code&gt; for the image, based on the &lt;code&gt;$image_size&lt;/code&gt; provided. The reason we're using almost a direct copy of the code is simple, consistency. It's very important we have that when working with preload. From here we build up an array of HTML attributes which will be used in the final step.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nb"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'&amp;lt;link rel="preload" as="image" href="%s" %s/&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;esc_url&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$src&lt;/span&gt; &lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nv"&gt;$additional_attr&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the image we want, and having collated the necessary attribute values based on the image size, we can output the &lt;code&gt;&amp;lt;link&amp;gt;&lt;/code&gt; tag to preload the image.&lt;/p&gt;

&lt;h3&gt;
  
  
  Filters
&lt;/h3&gt;

&lt;p&gt;You'll notice there are two filters, one for the &lt;code&gt;$thumbnail_id&lt;/code&gt;, and another for the &lt;code&gt;$image _size&lt;/code&gt;. The purpose of these is that it is entirely possible for an image that isn't the featured image to be important enough that it should be preloaded. These filters allow you to change the ID of the attachment that is to be preloaded.&lt;/p&gt;

&lt;p&gt;If you were using this directly in a theme for instance, you wouldn't need to use them, you could directly modify the function. I just wanted to show how it would be done if this were a plugin or part of a theme you couldn't actively modify.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use preload responsibly
&lt;/h2&gt;

&lt;p&gt;Now before you go and try to preload for yourself, it's important we quickly understand what the concept of preload is and how exactly it works. Preload lets you tell the browser what resources are critical and should be fetched as soon as possible, without having to wait for them to be discovered in the HTML, CSS or JS. You can learn more in-depth with &lt;a href="https://web.dev/preload-responsive-images/" rel="noopener noreferrer"&gt;this article on web.dev&lt;/a&gt;, as I want to focus more on using preload in WordPress.&lt;/p&gt;

&lt;p&gt;If you try to preload too many resources, the concept of preload almost becomes obsolete because if you define everything as important, it all automatically becomes not important...&lt;/p&gt;

&lt;h3&gt;
  
  
  Usage of preload for WordPress
&lt;/h3&gt;

&lt;p&gt;From our function above, we're only using it to preload the featured image of a post. As the majority of the time, any image above the fold is most likely to be just that. However, that's not to say there won't be instances where there's an image above the fold that isn't a featured image. In this scenario, we could utilize the filters as mentioned earlier to change the attachment ID of the image we want to use. For example, maybe for a template you're not using the built-in featured image, but an ACF image field instead. Well you could simply do something like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nf"&gt;add_filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'preload_post_thumbnail_id'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$thumbnail_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$post&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nf"&gt;get_page_template_slug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$post&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'templates/home.php'&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$thumbnail_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'banner_image'&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$thumbnail_id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above code snippet, if the page has a template with the slug &lt;code&gt;templates/home.php&lt;/code&gt;, we change the &lt;code&gt;$thumbnail_id&lt;/code&gt; to use the value from an ACF field instead.&lt;/p&gt;

&lt;h3&gt;
  
  
  Preload multiple images?
&lt;/h3&gt;

&lt;p&gt;This is a question which may have sprung to mind. In this case, you may want to abstract much of the function so that you can run it multiple times. Perhaps you'd want to create an array of associative arrays, and loop over that and output the &lt;code&gt;&amp;lt;link&amp;gt;&lt;/code&gt; to each image. I won't get into that for this post, although I could add it in if you would find it beneficial!&lt;/p&gt;

&lt;h2&gt;
  
  
  The results
&lt;/h2&gt;

&lt;p&gt;Now for the important question, did it actually make a difference? Well, yes! Below we have a comparison, the before is, well, before preloading the featured image. And after is, obviously, after we added preloading.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqeqn9cakdpi9o1770ax5.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqeqn9cakdpi9o1770ax5.jpg" alt="Screenshot of a before and after showing frames of a web page loading" width="800" height="342"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To make this comparison, I've used the Filmstrip on &lt;a href="https://www.webpagetest.org" rel="noopener noreferrer"&gt;webpagetest.org&lt;/a&gt;. The test was with Mobile on a slow 3G connection. As, when it comes to performance, these are the network connection speeds where it really matters.&lt;/p&gt;

&lt;p&gt;In each frame, the ones with the red border are when the &lt;strong&gt;Largest Contentful Paint&lt;/strong&gt; fully rendered on the page. You can see preloading the image made the image fully render on the page a whomping 4.5 seconds sooner! You may also notice that when preloading was added, the LCP image rendered in all at once, as opposed to progressively loading as seen before. This is because, when it came to rendering the image, it had already been fully downloaded, so was just a matter of rendering.&lt;/p&gt;

&lt;p&gt;However, during my testing I noticed a downside, and that was that it prioritised fetching the image over critical stylesheets. This ultimately increased the time before anything was rendered in the page, commonly known as &lt;strong&gt;First Contentful Paint&lt;/strong&gt;. So it's important to be mindful of any potential side effects when preloading resources, as you could be doing more harm then good!&lt;/p&gt;

&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@jlondonbaker?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;John Baker&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/rocket?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>performance</category>
      <category>preload</category>
      <category>images</category>
    </item>
    <item>
      <title>What is headless WordPress - an in-depth comparison</title>
      <dc:creator>Jackson Lewis</dc:creator>
      <pubDate>Thu, 15 Apr 2021 10:25:56 +0000</pubDate>
      <link>https://dev.to/jacksonlewis/what-is-headless-wordpress-an-in-depth-comparison-1c4m</link>
      <guid>https://dev.to/jacksonlewis/what-is-headless-wordpress-an-in-depth-comparison-1c4m</guid>
      <description>&lt;p&gt;Ah WordPress, the Content Management System that powers over 40% of the web. I think it's fair to say there is a big market for it. Now over the past few years, it seems something else has started to take the web dev scene by storm, JAMstack. This has lead to a new way of building the web of the future, and even WordPress is invited along for the ride!&lt;/p&gt;

&lt;p&gt;But it's not WordPress quite as you know it, oh no, this is headless WordPress.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is headless WordPress?
&lt;/h2&gt;

&lt;p&gt;This is the principle of using WordPress with a decoupled frontend, where content is queried via an API such as REST or GraphQL (&lt;a href="https://www.wpgraphql.com/" rel="noopener noreferrer"&gt;WPGraphQL&lt;/a&gt;), then displayed on the frontend.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fywodzank8afxgz2y0acg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fywodzank8afxgz2y0acg.png" alt="Graphic showing a visual representation of the difference between traditional and headless WordPress" width="800" height="478"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why might you want to use WordPress as a headless CMS?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The tech industry is moving at a phenomenal speed, and more specifically, websites and apps built with JavaScript-powered libraries and frameworks are starting to become the norm. Now then, WordPress was created way back in 2003, built on PHP. The platform has come along way, and it too has adopted some of this modern tech, with its Gutenberg block builder using React. However, you still remain within the confinement of a PHP based frontend.&lt;/p&gt;

&lt;p&gt;Now that we understand what headless WordPress is, we should quickly remind ourselves how a traditional WP frontend works. This will help us draw up a comparison at the end!&lt;/p&gt;

&lt;h2&gt;
  
  
  The traditional way
&lt;/h2&gt;

&lt;p&gt;If you've ever built a WordPress site, there's a good chance it was built traditionally, where all the code you write is in a theme. The theme controls what happens on both the backend and the frontend, it's where you'll have all your page templates, CSS and JavaScript.&lt;/p&gt;

&lt;p&gt;Now we're not going to go in-depth on exactly what the setup of a WP theme is, as that's out of the scope of this post. You can find out more about themes over on the official &lt;a href="https://developer.wordpress.org/themes/getting-started/what-is-a-theme/" rel="noopener noreferrer"&gt;WordPress Theme Handbook&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There are many many ways of working with a theme, you could be using a pre-built theme with lots of templates to choose from, that probably uses a page builder like Elementor. Or you could be building a custom theme that is bespoke to the needs of a project. Whatever the case, the fundamental structure is always the same, and therein lies the problem for many.&lt;/p&gt;

&lt;h2&gt;
  
  
  The headless way
&lt;/h2&gt;

&lt;p&gt;Using WordPress as a headless platform does away with following the 'rules' of WordPress theme development. Long gone are the days of using the likes of a &lt;code&gt;header.php&lt;/code&gt;, &lt;code&gt;footer.php&lt;/code&gt; and &lt;code&gt;style.css&lt;/code&gt;. You are free to structure the site however you please, which allows for a more tailored project, opening possibilities not previously available to a WordPress site.&lt;/p&gt;

&lt;p&gt;Now before you get too excited and hit that &lt;code&gt;ctrl + alt + del&lt;/code&gt; on a theme, WordPress still actually needs a theme in order to function. And your swanky new headless frontend may require some custom backend logic, or modify the WP admin to some degree.&lt;/p&gt;

&lt;p&gt;So you could either use a default theme, &lt;a href="https://en-gb.wordpress.org/themes/twentytwentyone/" rel="noopener noreferrer"&gt;Twenty Twenty One&lt;/a&gt;, or you could create your own barebones theme starting out with only &lt;a href="https://developer.wordpress.org/themes/basics/template-files/#common-wordpress-template-files" rel="noopener noreferrer"&gt;the necessary file&lt;/a&gt;. I find it easier to have a barebones theme setup rather than using a default theme, as for one, you're not going to be making any use of 90% of the features of the theme, and two, you'd have to make a child theme for any custom bits anyway.&lt;/p&gt;

&lt;p&gt;An example of something that you will still need the theme for is to register menu locations and custom post types. These items are backend logic and should be done the same way as if you were building a traditional site. Anything that is backend logic, you probably won't need to change how you work with, unless said logic needs to expose some data to the frontend that won't be handled by an existing mechanism.&lt;/p&gt;

&lt;p&gt;So, now that we have a grasp on the idea of a headless frontend, and we refreshed our brains on the traditional way with themes, let's put the two head-to-head.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparison time
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Pros of headless WordPress
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Full control over the technology&lt;/strong&gt; used on the frontend, from React to Vue to Angular. This factor alone is game changing to many, allowing endless possibilities for how the frontend is created. For example, if you only wanted a simple blog site, you may be best using an SSG like &lt;a href="https://www.11ty.dev" rel="noopener noreferrer"&gt;Eleventy&lt;/a&gt; or &lt;a href="https://www.gatsbyjs.com" rel="noopener noreferrer"&gt;Gatsby&lt;/a&gt;. Whereas if you're working on a large commerce site, &lt;a href="https://nextjs.org" rel="noopener noreferrer"&gt;Next.js&lt;/a&gt; would be a better fit for scalability. This control over tech stack used all ties into the Developer Experience, which I always believe plays a massive influence in the success of any project.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enhanced security&lt;/strong&gt; by going headless allows your frontend to be hosted away from the WordPress installation. This is great for many many reasons, like someone can't just do &lt;a href="http://example.com/wp-admin" rel="noopener noreferrer"&gt;example.com/wp-admin&lt;/a&gt; as the frontend isn't within a WordPress installation. It also protects against the likes of DDoS attacks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hide the CMS source completely&lt;/strong&gt;, something that is theoretically possible, dependant on your setup. Providing you don't make any client-side API calls directly to the CMS, and if you alter the directory structure to images, it is plausible to totally mask the fact you're using WordPress or any CMS for that matter. This could be very welcoming news to those always looking to improve security.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons of headless WordPress
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Reduced extendability&lt;/strong&gt;. WordPress is well known for it's large eco-system of plugins, which allow you to easily extend the functionality of your website in one way or another. However when you go headless, many of these plugins will seise to work as intended. The reason being, these plugins are only built to work with traditional WP, whereby any frontend code is 'hooked' onto frontend template actions. So with headless, the actions are never run as they are never called as there are no PHP page templates. For example let's take Yoast SEO, one of the biggest plugins out there. Now all the meta data Yoast outputs to a page &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; is done so through the &lt;code&gt;wp_head&lt;/code&gt; action. As this is the only means of outputting any meta data Yoast understands, we turn out attention to fix that. Now it is possible via WPGraphQL, using add-on plugins to expose a plugins data to the API, for us to query on the frontend. Luckily, there is an add-on plugin to Yoast SEO which allows just this. &lt;strong&gt;This is only one example, not all plugins have dedicated add-ons to extend to the GraphQL API.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Forces an alternative hosting setup&lt;/strong&gt;. With a traditional site, the frontend and backend exist coupled together in a single place on a server. So when you go headless, you can't have the frontend inside the WP installation. Instead, top recommendations are to use a dedicated hosting platform for these types of websites. Welcome the likes of &lt;a href="https://www.netlify.com" rel="noopener noreferrer"&gt;Netlify&lt;/a&gt; or &lt;a href="https://vercel.com" rel="noopener noreferrer"&gt;Vercel&lt;/a&gt;. These have super simple setups to get a project up and running, taking care of of pretty much everything including free SSL's. You are free to host the WP installation wherever you please. This one isn't as much of a big deal, but still something you should be aware of as both Netlify and Vercel are paid if you want to use commercially.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;From this in-depth look into the pros and cons of headless WordPress, it's important to make sure you're aware of what you're getting yourself, your team and maybe your client into. As, failure to clearly outline what headless means for a project, could leave you in a sticky situation. &lt;/p&gt;

&lt;p&gt;To conclude, is headless the way to go? In my book, yes, most definitely. I believe the pros far out way the cons, in terms of both the possibilities it opens and future-proofing. As mentioned above, it is so important to make it clear to those it will affect, that a site is headless. Failure to communicate this could be devastating. Your manager or the client may know you're building a WordPress site and think that's great, and look forward to extending the site with various plugins etc... Little would they know that a headless site takes away much of this extensibility. On the flip side, if this isn't an issue and everyone is on the same page and understands the benefit of going headless, then you're onto a winner!&lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>headless</category>
      <category>jamstack</category>
      <category>comparison</category>
    </item>
    <item>
      <title>Using toLocaleString to display prices in your application</title>
      <dc:creator>Jackson Lewis</dc:creator>
      <pubDate>Tue, 02 Mar 2021 12:07:52 +0000</pubDate>
      <link>https://dev.to/jacksonlewis/using-tolocalestring-to-display-prices-in-your-application-4eb8</link>
      <guid>https://dev.to/jacksonlewis/using-tolocalestring-to-display-prices-in-your-application-4eb8</guid>
      <description>&lt;p&gt;If you have an application that display prices anywhere, such as an ecommerce store, it's very important that those prices are being correctly formatted. As it could cause a real headache if it were to go wrong, particularly if your application needs to support multiple languages and/or currencies.&lt;/p&gt;

&lt;p&gt;That's where &lt;code&gt;toLocaleString()&lt;/code&gt; comes into play. This method formats number values based on a language code. What's more, you can pass options to specify the style of the number, like a currency!&lt;/p&gt;

&lt;p&gt;Let's take a look at how it works.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using &lt;code&gt;toLocaleString()&lt;/code&gt; for currencies
&lt;/h2&gt;

&lt;p&gt;This method can be used for various means of formatting numbers, including when a number needs to be displayed as a currency. Below is the simplest example of using &lt;code&gt;toLocaleString()&lt;/code&gt; to display a number as a currency.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// The data&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;currency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GBP&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;4.99&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// toLocaleString options&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;currency&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;currency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currency&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLocaleString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en-GB&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// £4.99&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Example
&lt;/h2&gt;

&lt;p&gt;Let's go through a step by step example of how we might use this method of displaying a price in a JavaScript application, we'll be using React for this example, however this will work for any website or application that uses JavaScript.&lt;/p&gt;

&lt;p&gt;Firstly, let's check out the data we're going to be using.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="cm"&gt;/**
 * This could be the data object of a product, which contains a price object
 */&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;...,&lt;/span&gt;
    &lt;span class="na"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;currency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GBP&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;4.99&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Current langauge - this could be set on a backend system and stored globally&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;language&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en-GB&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we have the price data we need, and know what language it should be formatted for, we can create a function that's going to format the data to display a price.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="cm"&gt;/**
 * Format a price amount based on language and currency
 *
 * @param {object} price The price object
 * @param {string} price.currency The currency to use
 * @param {number} price.amount The raw price amount
 * @return {string} The formatted display price
 */&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;formatMoney&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;toLocaleString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;language&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en-GB&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Provide a default value as a precaution&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;currency&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;currency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currency&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GBP&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="c1"&gt;// Provide a default just in case&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Perfect! So we pass a price object to the function as the &lt;code&gt;price&lt;/code&gt; parameter, and directly return the &lt;code&gt;amount&lt;/code&gt; which will get formatted based on the pre-defined &lt;code&gt;language&lt;/code&gt; and the &lt;code&gt;currency&lt;/code&gt; which is defined within our price object.&lt;/p&gt;

&lt;p&gt;You'll also notice from the code snippet above, that we provide fallback values for the language and currency. While this isn't required, it may be a good idea if you believe it's possible either may not be passed a value by their respective variable. It just prevents your app from not displaying a price at all, which would not be good news!&lt;/p&gt;

&lt;p&gt;What's so handy about having such a simple function like this is that we can use it everywhere in an ecommerce application. From the product page, to the cart and viewing customer orders, wherever there is a price to display, we'd use this function to correctly display it, as if enforces consistency across our application.&lt;/p&gt;

&lt;p&gt;So now let's bring all this together to display a price on the frontend of our application, which will look a little like the following.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="cm"&gt;/**
 * Render the price on our component
 */&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Product&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"price"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;formatMoney&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;ReactDOM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Product&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;,&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;root&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's worth mentioning we're only using React for the example here. As &lt;code&gt;toLocaleString()&lt;/code&gt; is native JavaScript, you can apply this to any application where JavaScript is used.&lt;/p&gt;

&lt;h3&gt;
  
  
  Other methods
&lt;/h3&gt;

&lt;p&gt;Let's not forget, this is the world of web development, meaning there are usually many ways of getting to the same result. If &lt;code&gt;toLocaleString()&lt;/code&gt; doesn't float your boat, you may want to take a look at &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat" rel="noopener noreferrer"&gt;Intl.NumberFormat&lt;/a&gt;. Here's how that may look:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Intl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;NumberFormat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en-GB&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;currency&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;currency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GBP&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="mf"&gt;4.99&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// £4.99&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check out the full working example over on &lt;a href="https://codepen.io/jackson-lewis/pen/OJbjoEx" rel="noopener noreferrer"&gt;CodePen&lt;/a&gt;. Thanks!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>locale</category>
      <category>ecommerce</category>
      <category>price</category>
    </item>
    <item>
      <title>Why I built my own WordPress theme</title>
      <dc:creator>Jackson Lewis</dc:creator>
      <pubDate>Tue, 23 Feb 2021 15:40:42 +0000</pubDate>
      <link>https://dev.to/jacksonlewis/why-i-built-my-own-wordpress-theme-56f8</link>
      <guid>https://dev.to/jacksonlewis/why-i-built-my-own-wordpress-theme-56f8</guid>
      <description>&lt;p&gt;With the WordPress eco-system flooded with themes, it's easy to get fixated on the idea that you &lt;em&gt;have&lt;/em&gt; to use one that is already out there. But if you think about it, these themes are generic and are made for the general community, and not your individual style. So I took matters into my own hands and built a theme from the ground up, tailored to my own needs.&lt;/p&gt;

&lt;p&gt;Let's follow the journey of the decisions made that led to the creation of my own WordPress theme!&lt;/p&gt;

&lt;h2&gt;
  
  
  Framework's aren't for me
&lt;/h2&gt;

&lt;p&gt;I don't know who needs to hear this, but it's ok to not use frameworks/libraries if you don't like them. For me, I absolutely hated the idea of all the unused code from parts of the framework that I wouldn't plan on using.&lt;/p&gt;

&lt;p&gt;Now you may be thinking, "Aren't we meant to be talking about WordPress themes?!". And yes, we are, however a framework is at the core of a theme. So it was a good idea to think about this first when going about creating a theme.&lt;/p&gt;

&lt;p&gt;Now that I understood why I didn't want to use a framework for the fundamental HTML/CSS structuring, I began creating my own, but one that would solve the issues I have with existing frameworks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding what I wanted out of a theme
&lt;/h2&gt;

&lt;p&gt;Moving onto the actual WordPress side of things, this would be where the theme would be tailored into something that could get the most out of. I had lots of ideas for things like helper functions that would reduce repetitive tasks such as calling an image on a template, or pre-built segments of the page such as a site header.&lt;/p&gt;

&lt;p&gt;Here's a list of just a few of the things I specifically wanted:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Various utility functions for calling images on templates&lt;/strong&gt; - something that really &lt;em&gt;really&lt;/em&gt; bothered me was seeing the exact same code for rendering an image dotted about across various templates for a site. It was clear to me this needed resolving with the help of some nifty utility functions, which influenced &lt;code&gt;shiftr_image()&lt;/code&gt; and &lt;code&gt;shiftr_featured_image()&lt;/code&gt;, with one for general images and the other specifically for post featured images.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Separated configurations for development and production when compiling assets&lt;/strong&gt; - after some playing around with &lt;code&gt;gulpfile.js&lt;/code&gt;, I found that running minification processes on development slowed down compiling times, which lowers productivity. I also felt like source maps are unnecessary in production, and increase the file size of the respective compiled file. So being able to have full control and split particular tasks between development and production environments was a great achievement.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integration with &lt;a href="https://www.advancedcustomfields.com/" rel="noopener noreferrer"&gt;Advanced Custom Fields&lt;/a&gt;&lt;/strong&gt; - every WordPress site I work on uses this plugin, so it only made sense to make sure it would be as effortless as possible to use it. Some of the utility functions as mentioned above, like &lt;code&gt;shiftr_image()&lt;/code&gt;, use ACF functions to easily work with a ACF Image field automatically.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I found having a list of ideas like the above very helpful in understanding what the actual purpose of this theme would be, which gave me more motivated to get the damn thing built! &lt;/p&gt;

&lt;h2&gt;
  
  
  Hello, Shiftr
&lt;/h2&gt;

&lt;p&gt;First off, I am one of those that absolutely loves naming and branding my personal projects, and my own WordPress theme was no exception. Let me introduce to you &lt;strong&gt;&lt;a href="https://github.com/jackson-lewis/shiftr" rel="noopener noreferrer"&gt;Shape Shiftr&lt;/a&gt;&lt;/strong&gt;, or &lt;strong&gt;Shiftr&lt;/strong&gt; for short. This is a WordPress blank starter theme built completely from the ground up with its own CSS/JS framework.&lt;/p&gt;

&lt;h3&gt;
  
  
  The stack
&lt;/h3&gt;

&lt;p&gt;Shiftr has seen a few big updates since its initial release in early 2019, so to keep it simple, I'll just run over the current, more modern stack in use.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://gulpjs.com/" rel="noopener noreferrer"&gt;Gulp&lt;/a&gt; (v4)-&lt;/strong&gt; The task runner used for everything while building, from hot reloading with browsersync, to compiling assets.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://webpack.js.org/" rel="noopener noreferrer"&gt;Webpack&lt;/a&gt; -&lt;/strong&gt; I took the leap and opted for webpack here, so I could utilize ES6 import/exports which has made working with code in multiple files super easy. Some may say I'm crazy, but my love for JavaScript was really taking off at the time so I wanted to be able to use the most modern syntax.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp7ivbcg7v9yumtplq5ry.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp7ivbcg7v9yumtplq5ry.png" alt="Screenshot from VS Code showing a snippet of the code in the gulpfile currently used by the theme" width="800" height="415"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Top features
&lt;/h3&gt;

&lt;p&gt;What I find most rewarding after creating your own theme is then going onto use it in real projects. To date, Shiftr is used in 12 production sites, all built by myself. So over that time I have been my own critic of sorts, finding anything from bugs to improvements that could be made. I'll walk you through a few of the top features that make a real difference to my day-to-day work while using the theme.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Image functions:&lt;/strong&gt; These are ultimately just wrapper functions to &lt;code&gt;wp_get_attachment_image()&lt;/code&gt;, but has made adding images something that I no longer have to think about. &lt;em&gt;I'm just going to quickly say, if you don't have something like this your theme, you seriouslyyyy need it, right now!&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SEO-ready:&lt;/strong&gt; I personally feel it is only fair that every website is built on a foundation that can be easily optimised for SEO. Shiftr includes everything from being optimised for performance to correct semantic layout of headings across templates.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flexi template:&lt;/strong&gt; This has to be hands down the biggest success to come out of the theme. Utilizing the &lt;a href="https://www.advancedcustomfields.com/resources/flexible-content/" rel="noopener noreferrer"&gt;Flexible content field&lt;/a&gt; in Advanced Custom Fields, I created a template that made it super easy for content creators to add and reorder sections of a page as they needed. This brought convenience and scalability to a site. It has evolved heavily to the point I dedicated a lot of time working on a great little API of sorts making it super easy to add new blocks to the template.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkozkmah47j0uchypw98v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkozkmah47j0uchypw98v.png" alt="Screenshot from VS Code showing a snippet of the PHP code that makes up the Flexi template" width="800" height="515"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Staying ahead of the game
&lt;/h2&gt;

&lt;p&gt;As mentioned in the previous section, I've tried to update the theme with new features, bug fixes and general touch-ups at least once every few months. I found it really important to stay on top of these updates, because as and when I would either find a bug or think of a new feature, I would end up just copying directly from one project to another, without ever actually putting the code into the source of the theme where it would be instantly available for future projects.&lt;/p&gt;

&lt;p&gt;There can also come a time when WordPress catches up with modern tech. For instance, in WordPress 5.5, the core team brought &lt;a href="https://web.dev/browser-level-image-lazy-loading/" rel="noopener noreferrer"&gt;native lazy loading&lt;/a&gt; with some help from the team at Google (I suspect). Now Shiftr already had Google's recommended implementation of lazy loading. So, on the working assumption that Shiftr would only be used with the latest releases of WP, I set about removing my lazy loading, as that can now be handled by WordPress itself.&lt;/p&gt;

&lt;p&gt;So there we have it, my journey of developing my own WordPress theme that meets my every need. Feel free to check out the code for yourself over on &lt;a href="https://github.com/jackson-lewis/shiftr" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, you may use it to find inspiration in creating your own theme. Thanks!&lt;/p&gt;

</description>
      <category>wordpress</category>
    </item>
  </channel>
</rss>
