<?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: Plank</title>
    <description>The latest articles on DEV Community by Plank (@plank).</description>
    <link>https://dev.to/plank</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%2Forganization%2Fprofile_image%2F6788%2F5a4f90e0-a29e-4ad6-af8b-0488ac9453da.png</url>
      <title>DEV Community: Plank</title>
      <link>https://dev.to/plank</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/plank"/>
    <language>en</language>
    <item>
      <title>The REM to PX relation: how to write more accessible media queries</title>
      <dc:creator>Riley McMaster</dc:creator>
      <pubDate>Mon, 26 Aug 2024 15:45:29 +0000</pubDate>
      <link>https://dev.to/plank/the-rem-to-px-relation-how-to-write-more-accessible-media-queries-5f95</link>
      <guid>https://dev.to/plank/the-rem-to-px-relation-how-to-write-more-accessible-media-queries-5f95</guid>
      <description>&lt;p&gt;We are developers. We want to develop the most responsive layouts. We want to accommodate different devices, resolutions and user settings. We want to use consistent units across all stylesheets. We want to do as little math as possible. &lt;/p&gt;

&lt;p&gt;When do we want this? NOW!&lt;br&gt;
What do we need to know? Lots of stuff!&lt;br&gt;
How do we do this? With a custom SASS function!&lt;/p&gt;

&lt;p&gt;By using a SASS function, we can accommodate more users by understanding and accounting for their system and browser-level settings. I will go over how rem values relate to pixel values and what might affect the relation between them. 1rem almost always starts off as 16px but there are ways a user can change that. This SASS function we’ll write later is very helpful because it can apply to a larger project and it can be introduced incrementally into your existing projects.&lt;/p&gt;

&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;What got me looking into this topic was the article &lt;a href="https://bootcamp.uxdesign.cc/theres-no-such-thing-as-a-desktop-screen-b9e300c0b128" rel="noopener noreferrer"&gt;There’s No Such Thing as a Desktop Screen&lt;/a&gt;, Hajime Yamasaki Vukelic,  where his take on responsive design is that “responsiveness is not about a simple set of arbitrary screen widths.... responsiveness is about robustness: how much can you stretch or squeeze the page before it starts falling apart”. Hajime talks about how his father is browsing the web at essentially 400% regular scale. While this may seem like an edge case, it’s important to know the different ways a user may scale their display and how the styles we’re writing are affected by these changes in settings.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scaled display
&lt;/h2&gt;

&lt;p&gt;Let’s start as small as possible with understanding exactly what a pixel is. As far as a developer is concerned, there are two types of pixels: there are device pixels which are the amount of dots of light on a given screen and there are CSS pixels which are a unit of measurement. Device pixels usually do not equal CSS pixels. It’s important to understand the difference between the two so we can figure which settings affect each value.&lt;/p&gt;

&lt;p&gt;There are several ways that a user can change the size of the content on their screen like Hajime’s father. The most common ways that a user could scale their display: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;changing the display resolution (system setting)&lt;/li&gt;
&lt;li&gt;zooming in on the browser tab (on Mac pressing &lt;code&gt;⌘ and +&lt;/code&gt;, windows &lt;code&gt;Ctrl and +&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;increasing the font size in the browser’s settings. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The first and second options, changing the display resolution and zooming in the browser, essentially do the same thing. Both methods will scale the CSS pixels so that each CSS pixel takes up more device pixels. In this case, our layout all scales proportionally. 1rem will still equal 16px but each CSS pixel takes up more device pixels. To test this, you can zoom in on the browser tab until you trigger the “mobile” layout. This setting is quick to test and generally shouldn’t cause much issue. &lt;/p&gt;

&lt;p&gt;Changing the browser font size will cause the most change. By default, the browser’s setting is “medium” which in Chrome means 1rem is 16px. When the user increases the font size, the value of 1rem will increase but no other values will scale. 1rem will equal more CSS pixels and therefore take up more device pixels. On Chrome, with the font size set to “very large”, 1rem will equal 24px. The size of the CSS pixels remain the same, it is the root font size that has changed. Any value that references the root font size will be affected.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fsh96gdbv5gw2q4efzbp2.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fsh96gdbv5gw2q4efzbp2.jpg" alt="two variations of the same layout that consists of an image on the left and on the right a heading and text all bordered in a smooth drop shadow. The first variation is properly proportioned. The second example with the browser's font size set to "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In your code, If you have a mix of pixel and rem values then you might start to have layout issues since the rem values will scale but the pixel values will stay the same. The image above shows how a simple example of how drastically the layout can change when the text is set in rem values while the max-width, column width and paddings are set with pixel values. A responsive layout should scale accordingly with the root font size.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem with media queries
&lt;/h2&gt;

&lt;p&gt;This is generally how we write a media query:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;

&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;min-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1000px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="nc"&gt;.declarations&lt;/span&gt; &lt;span class="nt"&gt;here&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Since we’re trying to be responsive and adaptable to all of the users’ settings, we want to use relative units all everywhere that we can. Let’s use a rem value instead of pixels in the media query:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;

&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;min-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;62.5rem&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="nc"&gt;.declarations&lt;/span&gt; &lt;span class="nt"&gt;here&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 default browser settings, 1000px will equal 62.5rem&lt;br&gt;
1rem = 16px&lt;br&gt;
1000px / 16px/rem = 62.5rem&lt;br&gt;
That looks like math I have to do every time I want to write a relative unit. We said right at the start that we don’t want to have to do math. &lt;/p&gt;

&lt;p&gt;There is a common fix that we’ve all seen where we make 1rem = 10px. This is generally done while setting up the boilerplate of a project. You overwrite the root font size on the root element by targeting the &lt;code&gt;html&lt;/code&gt; selector:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;

&lt;span class="nt"&gt;html&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;62.5%&lt;/span&gt; 
    &lt;span class="p"&gt;//&lt;/span&gt; &lt;span class="n"&gt;this&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt; 
    &lt;span class="p"&gt;//&lt;/span&gt; &lt;span class="n"&gt;but&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="n"&gt;only&lt;/span&gt; &lt;span class="n"&gt;needs&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="n"&gt;done&lt;/span&gt; &lt;span class="nb"&gt;once&lt;/span&gt; &lt;span class="n"&gt;for&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;whole&lt;/span&gt; &lt;span class="n"&gt;project&lt;/span&gt; 
    &lt;span class="p"&gt;//&lt;/span&gt; &lt;span class="n"&gt;so&lt;/span&gt; &lt;span class="n"&gt;I&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="n"&gt;ll&lt;/span&gt; &lt;span class="n"&gt;let&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="n"&gt;slide&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now any time we want to convert a pixel value from the design to a rem value in our code we just have to carry the decimal one place.&lt;br&gt;
1rem = 10px&lt;br&gt;
To get a value of 1000px, we use 100rem. This still involves math but is fairly minor. &lt;/p&gt;

&lt;p&gt;Now, when using a rem value, we can safely assume that 1rem will be 10px. &lt;br&gt;
Right? &lt;br&gt;
Yes? &lt;br&gt;
Example? &lt;br&gt;
No need. We know it is true. We have used rem for widths, heights, paddings, margins, translates or any other declaration without any issue. But…will there be any issue using it in the condition for a media query?&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;

&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;min-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100rem&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="nt"&gt;does&lt;/span&gt; &lt;span class="nt"&gt;is&lt;/span&gt; &lt;span class="nt"&gt;trigger&lt;/span&gt; &lt;span class="nt"&gt;at&lt;/span&gt; &lt;span class="err"&gt;1000&lt;/span&gt;&lt;span class="nt"&gt;px&lt;/span&gt; &lt;span class="nt"&gt;as&lt;/span&gt; &lt;span class="nt"&gt;expected&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
    &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="nc"&gt;.declarations&lt;/span&gt; &lt;span class="nt"&gt;here&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/plankdesign/embed/YzbEojr?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;br&gt;
Open the example in a new window and play with the width of the viewport. When the “desktop” media query triggers then the background will turn blue.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is happening?
&lt;/h2&gt;

&lt;p&gt;The values for a media query are calculated before any other rules are set, so the ruleset we applied to the &lt;code&gt;html&lt;/code&gt; element in the start of our project will not be applied in the condition of the media query. According to this media query, 1rem is still equal to 16px. We expected 100rem to be 1000px but it ended up being 1600px.&lt;/p&gt;

&lt;p&gt;If you change the browser font size to “very large” and refresh the example, you will notice that 1rem = 15px and the 100rem media query won’t trigger until 2400px. If your monitor isn’t wide enough to see that change happen, zoom out on the browser with ⌘/Ctrl and + .&lt;/p&gt;

&lt;p&gt;The condition for the media query is not scaling consistently with the browser’s desired font size. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Font size “Medium”: 

&lt;ul&gt;
&lt;li&gt;1rem = 10px&lt;/li&gt;
&lt;li&gt;Media query: 100rem = 1600px&lt;/li&gt;
&lt;li&gt;rem to px ratio: 0.0625&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Font size “Very Large”:

&lt;ul&gt;
&lt;li&gt;1rem = 15px&lt;/li&gt;
&lt;li&gt;Media query: 100rem = 2400px&lt;/li&gt;
&lt;li&gt;rem to px ratio: 0.0416666667&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;For content and layouts to scale consistently, we need the rem to px ratio to always remain the same.&lt;/p&gt;

&lt;h2&gt;
  
  
  REMPX()
&lt;/h2&gt;

&lt;p&gt;This has taken a long time to get to even suggesting a solution to a problem that we maybe didn’t know we had. &lt;/p&gt;

&lt;p&gt;Let’s create a custom SASS function that will allow us to write our code in pixel values and be rendered as rem values. I came across this function on a legacy project at work but I believe it was heavily inspired by this quick article: &lt;a href="https://medium.com/@bhargav3shah/scss-convert-pixel-values-to-rem-using-functions-f1cef575edfd" rel="noopener noreferrer"&gt;Convert pixel values to rem, Sass style&lt;/a&gt;, by Bhargav Shah. Since this article was written, CSS introduced its own &lt;code&gt;rem()&lt;/code&gt; function which calculates the remainder of a fraction so instead we’ll name our function &lt;code&gt;rempx()&lt;/code&gt;.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;

&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="nt"&gt;html-font-size&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="err"&gt;16&lt;/span&gt;&lt;span class="nt"&gt;px&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;@function&lt;/span&gt; &lt;span class="n"&gt;stripUnit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;value&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="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="err"&gt;+&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;@function&lt;/span&gt; &lt;span class="n"&gt;rempx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;pxValue&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="err"&gt;#&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nt"&gt;stripUnit&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="nt"&gt;pxValue&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nt"&gt;stripUnit&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="nt"&gt;html-font-size&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;rem&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="nt"&gt;implementation&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="nc"&gt;.image&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rempx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;300px&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;&lt;iframe height="600" src="https://codepen.io/plankdesign/embed/zYQPVLr?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;br&gt;
Open the example in a new window and play with the width of the viewport and change the browser font size (refresh the page after you update the font size).&lt;/p&gt;

&lt;p&gt;Notice how after we change the browser font size to “very large” (after a page a refresh), the 1rem square becomes larger and you can see that 1rem is equal to 24px.&lt;/p&gt;

&lt;p&gt;When used in the condition of a media query, a &lt;code&gt;rempx&lt;/code&gt; value will scale accordingly with the browsers font size. With the font size set to “very large”, the desktop layout &lt;code&gt;rempx(1000px)&lt;/code&gt; will trigger at the viewport width of 1500px. The scaling of the content and layout behave the same way as when we zoom in on the browser. &lt;/p&gt;

&lt;p&gt;A huge benefit of writing all your units with the &lt;code&gt;rempx()&lt;/code&gt; function is you can write pixel values from the designs and then it renders it as a rem value in the browser. This function is very easy to introduce to a project or include in the boilerplate of your future projects.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;This function can be written once and used everywhere. &lt;br&gt;
We can take the pixel values from the design and generate a scalable rem value. &lt;br&gt;
Our media query triggers relative to the root font size.&lt;br&gt;
All our layout and content scales consistently.&lt;br&gt;
No math necessary.&lt;br&gt;
Better user experience across a wider range of user settings. &lt;br&gt;
Better user existence overall.&lt;br&gt;
Better developer existence overall.&lt;br&gt;
This function improves our existence. &lt;/p&gt;

&lt;h2&gt;
  
  
  Further reading
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://bootcamp.uxdesign.cc/theres-no-such-thing-as-a-desktop-screen-b9e300c0b128" rel="noopener noreferrer"&gt;There’s No Such Thing as a Desktop Screen&lt;/a&gt; Hajime Yamasaki Vukelic&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.oddbird.net/2024/07/09/zoomies/" rel="noopener noreferrer"&gt;Zoom, zoom, and zoom: the three types of browser (and CSS!) magnification&lt;/a&gt;, Miriam Suzanne&lt;/p&gt;

&lt;p&gt;&lt;a href="https://medium.com/@bhargav3shah/scss-convert-pixel-values-to-rem-using-functions-f1cef575edfd" rel="noopener noreferrer"&gt;Convert pixel values to rem, Sass style&lt;/a&gt;, Bhargav Shah&lt;/p&gt;

</description>
      <category>css</category>
      <category>webdev</category>
      <category>sass</category>
      <category>a11y</category>
    </item>
    <item>
      <title>Why Did You Render - React &amp; WordPress</title>
      <dc:creator>Riley McMaster</dc:creator>
      <pubDate>Thu, 01 Feb 2024 19:46:30 +0000</pubDate>
      <link>https://dev.to/plank/why-did-you-render-react-wordpress-1flg</link>
      <guid>https://dev.to/plank/why-did-you-render-react-wordpress-1flg</guid>
      <description>&lt;p&gt;When using React components in a WordPress project, I want to be able to diagnose what is causing components to re-render unnecessarily. &lt;/p&gt;

&lt;p&gt;On a project recently, I ran into a problem where a React component was re-rendering unexpectedly. It was causing a quick layout shift and I was finding it really difficult to troubleshoot what was the cause. I came across the package &lt;code&gt;why-did-you-render&lt;/code&gt; and the docs didn't have any tips on how to get it set up on a WordPress project. Below are the steps that my backend dev &lt;a class="mentioned-user" href="https://dev.to/davekellam"&gt;@davekellam&lt;/a&gt; and I took to get the package working with WordPress. We compile assets in our WordPress projects with Webpack and Babel. &lt;/p&gt;

&lt;p&gt;We had to add a couple of dependencies and update the &lt;code&gt;.babelrc&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;Dev dependencies to add to project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;babel&lt;/span&gt;&lt;span class="sr"&gt;/preset-reac&lt;/span&gt;&lt;span class="err"&gt;t
&lt;/span&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;welldone&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;software&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;why&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;did&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;you&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;render&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;.babelrc&lt;/code&gt; (add this line underneath &lt;code&gt;@babel/preset-env&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;presets&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@babel/preset-env&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@babel/preset-react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// added this line&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@wordpress/default&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;Since we don't have access to an &lt;code&gt;.env&lt;/code&gt; file, we had to add this next line in order to access the environment via the &lt;code&gt;global mainScript&lt;/code&gt;. This will prevent the script from loading in production if we have forgotten to remove the dependency. &lt;br&gt;
&lt;code&gt;scripts.php&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;environment&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;esc_attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nf"&gt;wp_get_environment_type&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;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuwihqbpf14cxj2fyib6r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuwihqbpf14cxj2fyib6r.png" alt="Snippet of code used to access env variable" width="800" height="228"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the top level .js file, in this case mine is called &lt;code&gt;frontend.js&lt;/code&gt;, (need &lt;code&gt;global mainscript&lt;/code&gt;, the code below will be placed above the individual component imports):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/* global mainScript */&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;whyDidYouRender&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@welldone-software/why-did-you-render&lt;/span&gt;&lt;span class="dl"&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="nx"&gt;mainScript&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;local&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="nf"&gt;whyDidYouRender&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;trackAllPureComponents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&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;in a component file, with &lt;code&gt;ComponentName&lt;/code&gt; replaced with the actual name of the component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;ComponentName&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;whyDidYouRender&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;WDYR wants to only display a message if a component re-renders with the same props. If your component isn't getting re-rendered unnecessarily then you might not get an error message and it might seem like the package is not doing anything. Using this next code snippet instead will display any prop changes that happen. The result is a bit verbose but a simple test to make sure that the package is working.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;ComponentName&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;whyDidYouRender&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;logOnDifferentValues&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I am still encountering an issue of loading the package in the production environment. The package's docs have an example for how to conditionally import the package but I was unable to find a workaround in WordPress. The best course of action I can find is to either remove the dependency before the site is deployed or install the package when debugging and remove it before merging your branch. &lt;/p&gt;

&lt;p&gt;More information about the use-cases for WDYR and an example on how to use it: &lt;br&gt;
&lt;a href="https://blog.logrocket.com/debugging-react-performance-issues-with-why-did-you-render/"&gt;https://blog.logrocket.com/debugging-react-performance-issues-with-why-did-you-render/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>wordpress</category>
      <category>tutorial</category>
      <category>frontend</category>
    </item>
    <item>
      <title>VoiceOver quick start</title>
      <dc:creator>Riley McMaster</dc:creator>
      <pubDate>Fri, 03 Nov 2023 14:04:40 +0000</pubDate>
      <link>https://dev.to/plank/voiceover-quick-start-2ki2</link>
      <guid>https://dev.to/plank/voiceover-quick-start-2ki2</guid>
      <description>&lt;p&gt;VoiceOver is a screen reader that comes installed on all Apple computers. This article will serve as a quick introduction to some of the basic commands to help you get started using a screen reader on any website. VoiceOver will work in any browser but does work best in Safari. &lt;/p&gt;

&lt;p&gt;The VoiceOver command keys will be used for almost every command going forward. I will refer to the command as &lt;code&gt;VO&lt;/code&gt; which can be either of these:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;caps lock&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;option + command&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Start VoiceOver - &lt;code&gt;command + F5&lt;/code&gt;&lt;br&gt;
Select &lt;code&gt;use VoiceOver&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;It might start reading off all the elements on a webpage without taking a break and this can be a little overwhelming. &lt;/p&gt;

&lt;p&gt;Stop VoiceOver from auto reading - press the &lt;code&gt;control&lt;/code&gt; key.&lt;br&gt;
Start reading again - &lt;code&gt;VO + a&lt;/code&gt; &lt;br&gt;
I wouldn't suggest auto reading for a first-time screen reader user. For now, let's take it one element at a time. &lt;/p&gt;

&lt;p&gt;In the case that the whole browser is selected (you will see an outline around the whole app):&lt;br&gt;
Interact with the item (the browser in this instance) - &lt;code&gt;VO + shift + down&lt;/code&gt;&lt;br&gt;
Stop interacting with an item - &lt;code&gt;VO + shift + up&lt;/code&gt;&lt;br&gt;
This can also be thought of like navigating levels of a directory.&lt;/p&gt;

&lt;p&gt;If the tabs or address bar are selected, you will use &lt;br&gt;
&lt;code&gt;VO + up&lt;/code&gt; or &lt;code&gt;VO + down&lt;/code&gt; until the content of the webpage is selected.&lt;/p&gt;

&lt;p&gt;Once the web content is selected,&lt;br&gt;
navigate between elements on the page:&lt;br&gt;
&lt;code&gt;VO + left arrow&lt;/code&gt; &lt;br&gt;
&lt;code&gt;VO + right arrow&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Open Rotor: &lt;code&gt;VO + u&lt;/code&gt;&lt;br&gt;
This tool is really interesting because it organizes the content of the website in a completely different way than what sighted users are used to seeing. Rotor breaks down the content into several different categories: links, headings, form controls and landmarks.  &lt;/p&gt;

&lt;p&gt;You can navigate between the Rotor sections with the arrow keys.&lt;/p&gt;

&lt;p&gt;Since starting to test the sites that I'm developing with a screen reader, I've found:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"read more" or other vague text in buttons are not helpful. Give buttons like this descriptive aria-labels&lt;/li&gt;
&lt;li&gt;images declared in the content property of pseudo-elements will be read, even though there's no alt or title. &lt;/li&gt;
&lt;li&gt;it's important to connect your labels to your inputs using &lt;code&gt;id&lt;/code&gt; and &lt;code&gt;for&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;use html table elements instead of creating a table visually with divs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is worth exploring how to use screen readers and other assistive technologies in order to become a more empathetic developer. VoiceOver is a great tool that is readily available to all Mac users. While VoiceOver comes with its own tutorial, I found it a bit long and slow but it is definitely worth doing when you have the time. &lt;/p&gt;

&lt;p&gt;To see the whole list of commands:&lt;br&gt;
&lt;a href="https://www.apple.com/voiceover/info/guide/_1131.html"&gt;Apple - VoiceOver commands&lt;/a&gt;&lt;/p&gt;

</description>
      <category>a11y</category>
      <category>webdev</category>
      <category>development</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>CSS: complex grid layout</title>
      <dc:creator>Riley McMaster</dc:creator>
      <pubDate>Tue, 12 Sep 2023 13:23:41 +0000</pubDate>
      <link>https://dev.to/plank/css-complex-grid-layout-2jk9</link>
      <guid>https://dev.to/plank/css-complex-grid-layout-2jk9</guid>
      <description>&lt;p&gt;At Plank, we build many of our projects with Wordpress. Making menus in the CMS is pretty user friendly but when it comes to more complex menu structures, it can be difficult for us as the frontend developer to style when all we are given is nested lists upon nested lists. &lt;/p&gt;

&lt;p&gt;To solve this problem, I came up with this grid layout recently and wanted to share how it is done. I’ll also discuss a big struggle I had to overcome for this to work properly, be flexible and easy to tweak. &lt;/p&gt;

&lt;h2&gt;
  
  
  The markup:
&lt;/h2&gt;

&lt;p&gt;In this example, we are working with one unordered list with several children. The first child is a call to action and the rest are links. Wordpress allows us to add classes to the individual links (as well as a description to support the call to action), so I added a class and a description to the call to action &lt;code&gt;list__item--cta&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;I decided to go with grid over flex in this case because the call to action will take the whole vertical height of the menu while the rest of the links were tiled towards the right side of the screen.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.list&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="err"&gt;//&lt;/span&gt; &lt;span class="err"&gt;need&lt;/span&gt; &lt;span class="err"&gt;to&lt;/span&gt; &lt;span class="err"&gt;name&lt;/span&gt; &lt;span class="err"&gt;the&lt;/span&gt; &lt;span class="err"&gt;start&lt;/span&gt; &lt;span class="err"&gt;and&lt;/span&gt; &lt;span class="err"&gt;end&lt;/span&gt; &lt;span class="err"&gt;of&lt;/span&gt; &lt;span class="err"&gt;the&lt;/span&gt; 
   &lt;span class="err"&gt;//&lt;/span&gt; &lt;span class="err"&gt;first&lt;/span&gt; &lt;span class="err"&gt;column&lt;/span&gt; &lt;span class="err"&gt;so&lt;/span&gt; &lt;span class="err"&gt;it&lt;/span&gt; &lt;span class="err"&gt;can&lt;/span&gt; &lt;span class="err"&gt;be&lt;/span&gt; &lt;span class="err"&gt;referenced&lt;/span&gt; &lt;span class="err"&gt;by&lt;/span&gt; &lt;span class="err"&gt;the&lt;/span&gt; &lt;span class="err"&gt;CTA&lt;/span&gt;
   &lt;span class="err"&gt;//&lt;/span&gt; &lt;span class="err"&gt;declare&lt;/span&gt; &lt;span class="err"&gt;4&lt;/span&gt; &lt;span class="err"&gt;columns,&lt;/span&gt; 
   &lt;span class="err"&gt;//&lt;/span&gt; &lt;span class="err"&gt;first&lt;/span&gt; &lt;span class="err"&gt;spot&lt;/span&gt; &lt;span class="err"&gt;for&lt;/span&gt; &lt;span class="err"&gt;CTA&lt;/span&gt; &lt;span class="err"&gt;then&lt;/span&gt; &lt;span class="err"&gt;repeat&lt;/span&gt; &lt;span class="err"&gt;3&lt;/span&gt; &lt;span class="err"&gt;for&lt;/span&gt; &lt;span class="err"&gt;the&lt;/span&gt; &lt;span class="err"&gt;links&lt;/span&gt;
   &lt;span class="py"&gt;grid-template-columns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;cta-start&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;minmax&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;200px&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;cta-end&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="nb"&gt;repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;minmax&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;50px&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="n"&gt;fr&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
   &lt;span class="py"&gt;grid-auto-rows&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;min-content&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.list__item--cta&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;grid-row&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;grid-column&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;cta-start&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="n"&gt;cta-end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&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;Since we did not define the amount of rows on the parent, the &lt;code&gt;--cta&lt;/code&gt; child is telling the parent grid how many rows there will be with the property &lt;code&gt;grid-row: 1 / 4;&lt;/code&gt;. The value is spanning from the first line (start of the first row) to the fourth line (end of the third row). In this example we have 7 links, so we need 3 rows and 3 columns (in practice I used a bit of JavaScript to adjust the number of rows and columns based on the number of links). &lt;/p&gt;

&lt;p&gt;I made the description of the call to action &lt;code&gt;contenteditable&lt;/code&gt; to show where I went wrong. Edit the text and see how the grid falls apart&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/plankdesign/embed/abQGWrR?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;The gap between the rows shouldn't start stretching out like that. So what is there to do?&lt;/p&gt;

&lt;h2&gt;
  
  
  The Fix
&lt;/h2&gt;

&lt;p&gt;Grid will fill its rows before columns by default. We need three rows for the amount of links we have. But what if we create one extra row that starts at a height of 0 and its only job is to expand to take the extra height of the CTA description? In this case, we update the grid-row property on &lt;code&gt;--cta&lt;/code&gt; to create an extra row:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.list__item--cta&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nl"&gt;grid-row&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="m"&gt;5&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;Remember that when setting the &lt;code&gt;grid-row&lt;/code&gt; property, the last line in the grid will always be one more than the number of rows.&lt;/p&gt;

&lt;p&gt;The cta is now adding a fourth row that won't be filled up by the other links, the last row only exists as a buffer. If the CTA doesn't need that space, the row will have a height of zero.&lt;/p&gt;

&lt;p&gt;Now we can add as much text as we want to the cta description and the other links will be completely unaffected!&lt;/p&gt;

&lt;h2&gt;
  
  
  The final result:
&lt;/h2&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/plankdesign/embed/xxQNYKq?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Done!&lt;/p&gt;

</description>
      <category>css</category>
      <category>grid</category>
      <category>tutorial</category>
      <category>wordpress</category>
    </item>
    <item>
      <title>Five For the Future at Plank</title>
      <dc:creator>Dave Kellam</dc:creator>
      <pubDate>Wed, 23 Aug 2023 14:49:45 +0000</pubDate>
      <link>https://dev.to/plank/five-for-the-future-at-plank-50mo</link>
      <guid>https://dev.to/plank/five-for-the-future-at-plank-50mo</guid>
      <description>&lt;p&gt;&lt;a href="https://plank.co" rel="noopener noreferrer"&gt;Plank&lt;/a&gt; is one of over &lt;a href="https://wordpress.org/five-for-the-future/pledges/" rel="noopener noreferrer"&gt;150 organizations&lt;/a&gt; that have pledged to contribute to &lt;a href="https://wordpress.org/five-for-the-future/" rel="noopener noreferrer"&gt;Five For the Future&lt;/a&gt;. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Launched in 2014, Five for the Future encourages organizations to contribute 5% of their resources to WordPress development. This benchmark was proposed by WordPress co-founder Matt Mullenweg to maintain a "golden ratio" of contributors to users. Participation in the community has more than quadrupled since launch.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;At Plank, we believe in open-source software. We use it to power all of our projects. So many others have contributed to making our lives easier and more productive, it's important that we do the same!&lt;/p&gt;

&lt;p&gt;We’ve begun our Five For the Future journey by contributing to the &lt;a href="https://make.wordpress.org/documentation/" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; and &lt;a href="https://make.wordpress.org/polyglots/" rel="noopener noreferrer"&gt;polyglots&lt;/a&gt; teams. The polyglots team is a natural fit for us, as our team members speak various languages, including English, French, Spanish and Arabic. We’ll be looking to expand our involvement in the near future by attending &lt;a href="https://us.wordcamp.org/2023/contributor-day/" rel="noopener noreferrer"&gt;contributor day&lt;/a&gt; at WordCamp US 2023. &lt;/p&gt;

&lt;p&gt;Visit our &lt;a href="https://wordpress.org/five-for-the-future/pledge/plank/" rel="noopener noreferrer"&gt;pledge&lt;/a&gt; to see our contributions to the project so far!&lt;/p&gt;




&lt;p&gt;&lt;a href="https://www.flickr.com/photos/wceu/53076418323/in/album-72177720310091678/" rel="noopener noreferrer"&gt;Photo&lt;/a&gt; from contributor day at WordCamp Europe 2023.&lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>development</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Using CSS size container queries</title>
      <dc:creator>Eyel Mordido</dc:creator>
      <pubDate>Fri, 18 Aug 2023 17:30:06 +0000</pubDate>
      <link>https://dev.to/plank/using-css-size-container-queries-43ef</link>
      <guid>https://dev.to/plank/using-css-size-container-queries-43ef</guid>
      <description>&lt;p&gt;CSS size container queries are now fully supported in all major browsers and offer a great way to create responsive page elements.&lt;/p&gt;

&lt;p&gt;One advantage of using size container queries is it enables us to place components in different spaces of our web page without needing to know the dimensions of that specific space.&lt;/p&gt;

&lt;p&gt;Let’s see how we can use it in creating a responsive card component:&lt;br&gt;
&lt;a href="https://media.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%2F5sha3dbxlz4j0gqr4iuw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F5sha3dbxlz4j0gqr4iuw.png" alt="stacked cards component"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A rule for using container queries is we cannot style or change the container if we want to measure its dimensions. We can only style its children. In the image above, we are wrapping the &lt;code&gt;.cards__grid&lt;/code&gt; element with a parent &lt;code&gt;.cards__container&lt;/code&gt; element so we can style the grid and all its contents.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. The first step is to define the element we want to get the dimensions of by using the &lt;code&gt;container-type&lt;/code&gt; property&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Here we are making the &lt;code&gt;.cards__container&lt;/code&gt; element as our containment context so we can query its width.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.cards__container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="py"&gt;container-type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;inline-size&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 values for the &lt;code&gt;container-type&lt;/code&gt; property can either be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;size&lt;/code&gt; - query the height and width of the container. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When we make an element the containment context, the built-in dimensions of its content is ignored so the container loses its height. Its width will not be affected because width is an extrinsic size of a block element. They always occupy the entire width of the space.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.cards__container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="py"&gt;container-type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;size&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;See how the pink-bordered &lt;code&gt;.cards__container&lt;/code&gt; element is no longer stretching the full height of its content after changing the value of &lt;code&gt;container-type&lt;/code&gt; to &lt;code&gt;size&lt;/code&gt;:&lt;br&gt;
&lt;a href="https://media.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%2Fajdhxqxi0fzq4pef88n8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fajdhxqxi0fzq4pef88n8.png" alt="stacked cards component"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;inline-size&lt;/code&gt; - only query the width. This is the recommended value for full responsiveness.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;normal&lt;/code&gt; - doesn't allow us to query the dimensions but allows us to query the styles.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Naming the container is also considered a best practice. We can think of the name as a class or ID and we can give multiple names to a container.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.cards__container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="py"&gt;container-type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;inline-size&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;container-name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;cards-container&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;&lt;strong&gt;2. After defining and naming the container, we can add our query.&lt;/strong&gt;&lt;br&gt;
We start the query with the &lt;code&gt;@container&lt;/code&gt; at-rule followed by the name. Similar to media queries, we can use the &lt;code&gt;min-width&lt;/code&gt; or &lt;code&gt;max-width&lt;/code&gt; properties for the condition.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@container&lt;/span&gt; &lt;span class="n"&gt;cards-container&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;min-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;701px&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;We can also use the ranged syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="c"&gt;/* if the width is between 700 and 1000 pixels. */&lt;/span&gt;
&lt;span class="k"&gt;@container&lt;/span&gt; &lt;span class="n"&gt;cards-container&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;700px&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;1000px&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;&lt;strong&gt;3. Finally, we can add the style rules for the children of the container&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.cards__container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;container-type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;inline-size&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;container-name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;cards-container&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;@container&lt;/span&gt; &lt;span class="n"&gt;cards-container&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;min-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;701px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nc"&gt;.cards__grid&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="py"&gt;grid-template-columns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;minmax&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="n"&gt;fr&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nc"&gt;.card&lt;/span&gt; &lt;span class="nt"&gt;figure&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;block&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nc"&gt;.card__text&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;margin-top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nc"&gt;.card&lt;/span&gt; &lt;span class="nt"&gt;h3&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1.8rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nc"&gt;.card&lt;/span&gt; &lt;span class="nt"&gt;figcaption&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1.2rem&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;@container&lt;/span&gt; &lt;span class="n"&gt;cards-container&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;min-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1000px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nc"&gt;.cards__grid&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="py"&gt;grid-template-columns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;minmax&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="n"&gt;fr&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;Now, our &lt;code&gt;.cards__grid&lt;/code&gt; element should switch to a two-column grid layout when the container is more than 700px wide, the image stacked on top of the text and the font-size bigger.&lt;br&gt;
&lt;a href="https://media.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%2Fqh24fgxddlfx9ggdjjdz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fqh24fgxddlfx9ggdjjdz.png" alt="two-column cards grid"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At a width of 1000px and above, it should change to a three-column grid layout.&lt;br&gt;
&lt;a href="https://media.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%2F7uwyyafcilaf3haon4sn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F7uwyyafcilaf3haon4sn.png" alt="three-column cards grid"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why use size container queries over media queries?
&lt;/h2&gt;

&lt;p&gt;At the beginning of this article we mentioned that size container queries allow us to place elements anywhere on the page without worrying about the size of the space.&lt;/p&gt;

&lt;p&gt;To demonstrate this more clearly, let's place the card component in a blog page that has a narrower &lt;code&gt;&amp;lt;main&amp;gt;&lt;/code&gt; element. With media queries, the cards' layout will stay as a three-column grid because we are checking for the page's width instead of the container's.&lt;br&gt;
&lt;a href="https://media.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%2F7hk0iup8ci9zqlblky10.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F7hk0iup8ci9zqlblky10.png" alt="blog page with cards"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We will need to override the styles of the cards that are in the blog page to correct this.&lt;/p&gt;

&lt;p&gt;With container queries, the cards component is more reusable and responsive. The cards' grid will respond to the width of its container and will update to the stacked layout. &lt;br&gt;
&lt;a href="https://media.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%2Fjvzair2ukgl04jccnx83.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fjvzair2ukgl04jccnx83.png" alt="blog page with cards"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can learn more about container queries with these resources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_container_queries" rel="noopener noreferrer"&gt;MDN docs - CSS container queries&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.smashingmagazine.com/2021/05/complete-guide-css-container-queries/" rel="noopener noreferrer"&gt;A Primer on CSS Container Queries&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://web.dev/cq-stable/" rel="noopener noreferrer"&gt;Container queries land in stable browsers&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>css</category>
      <category>frontend</category>
      <category>webdev</category>
    </item>
    <item>
      <title>ChatGPT is Invaluable When You Know What You Want!</title>
      <dc:creator>Oluwatosin Jeremiah</dc:creator>
      <pubDate>Thu, 10 Aug 2023 13:09:57 +0000</pubDate>
      <link>https://dev.to/plank/chatgpt-is-invaluable-when-you-know-what-you-want-5cbb</link>
      <guid>https://dev.to/plank/chatgpt-is-invaluable-when-you-know-what-you-want-5cbb</guid>
      <description>&lt;p&gt;ChatGPT is an advanced language model that converses and produces human-like responses, powered by Natural Language Processing (NLP).&lt;/p&gt;

&lt;p&gt;It can understand and reply to text in a range of settings and subject areas because to its NLP capabilities. When it comes to streamlining processes or doing troubleshooting, this can be really beneficial.&lt;/p&gt;

&lt;p&gt;However, a clear knowledge of your objectives is necessary in order to fully utilize ChatGPT and benefit from it.&lt;/p&gt;

&lt;p&gt;In this article, we will look at the advantages of ChatGPT when used with a clear purpose, allowing you to maximize its full potential and achieve your goals.&lt;/p&gt;

&lt;p&gt;I had the chance to speak with a web developer who is just getting started, and during our conversation, we brought up ChatGPT. He claimed that ChatGPT had been beneficial to him. I replied that Chat GPT is truly helpful, and this the reason why it was created, but as he is just starting out, ChatGPT shouldn't be his primary source of assistance because doing so won't actually help him learn and advance.&lt;/p&gt;

&lt;p&gt;I started a chat with ChatGPT to prove a point, that chatGPT has it's own limitations, especially if you’re asking about anything after September 2021 (where GPT-3 training data ends). &lt;/p&gt;

&lt;p&gt;I needed to learn more about Data Transfer Object, using &lt;a href="https://spatie.be/docs/laravel-data/v3/introduction"&gt;Laravel-data package&lt;/a&gt; from Spatie Open Source.&lt;/p&gt;

&lt;p&gt;Below, I will show you how I did this with ChatGPT and the lessons I learned:&lt;/p&gt;

&lt;p&gt;I started by saying what I wanted to know.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vF5JOI0L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mqg488syuy3m7cum3ntt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vF5JOI0L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mqg488syuy3m7cum3ntt.png" alt="Starting the conversation" width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, the documentation states that we should install the package in this manner;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aHHjvWxf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j0kqkh3j3ay0a669sc1j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aHHjvWxf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j0kqkh3j3ay0a669sc1j.png" alt="Spatie Laravel Data" width="800" height="245"&gt;&lt;/a&gt;&lt;br&gt;
After several attempts, I figured out that I needed to be more specific to ChatGPT;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6aByhP8G--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ab3q61vdjcf92krd01oa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6aByhP8G--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ab3q61vdjcf92krd01oa.png" alt="My response" width="800" height="384"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The problem here is that ChatGPT is using a deprecated version of the package, which will mean that you run into some errors when you follow exactly what you have in this response because the namespace is different from what is in the documentation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---PMKF4S_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gsppovmd7r5d1mxcrjei.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---PMKF4S_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gsppovmd7r5d1mxcrjei.png" alt="Deprecated version" width="800" height="596"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I knew what I was looking for;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sLbvLvC6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/di3p8vt6pa22u6ad1vqx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sLbvLvC6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/di3p8vt6pa22u6ad1vqx.png" alt="Angry me :lol" width="800" height="267"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After some back and forth, I got the response I was looking for.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MqaEcnq5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/20d4j4ouuc0w1a1pmmxq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MqaEcnq5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/20d4j4ouuc0w1a1pmmxq.png" alt="Right answer" width="800" height="329"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h4&gt;
  
  
  My final thoughts
&lt;/h4&gt;

&lt;p&gt;When you know what you want and approach it with a clear objective, ChatGPT can be a really useful tool. You can maximize ChatGPT's possibilities by outlining your objectives, giving precise instructions, using an iterative refining process, and analyzing the results critically. &lt;/p&gt;

&lt;p&gt;Most importantly, if you really want to learn as a developer, read documentation, and use forums to be able to pull from a range of opinions, this will inform better decision-making.&lt;/p&gt;

&lt;h5&gt;
  
  
  Here are a few things you can do:
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;Define your objectives: Knowing what you want can help you explain your needs to ChatGPT clearly and get helpful responses in return. &lt;/li&gt;
&lt;li&gt;Provide clear instructions: By providing clear instructions, you can guide ChatGPT to produce more precise, customized, and responsive results that meet your needs.&lt;/li&gt;
&lt;li&gt;Leverage ChatGPT for Code Review: After writing your code, you may have ChatGPT read a section of it and highlight any flaws or potential refactoring.&lt;/li&gt;
&lt;li&gt;Grow the Conversation: The quality of the information produced by ChatGPT can be improved through iterative dialogue.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As you use ChatGPT to &lt;em&gt;&lt;strong&gt;support&lt;/strong&gt;&lt;/em&gt; and improve your decision-making process, be conscious of its limitations, and use ChatGPT as a tool. When your goals are well defined, ChatGPT can be a helpful ally in your quest for knowledge and information.&lt;/p&gt;

&lt;p&gt;By the way 🥳, this is my first article ever, and I hope you found it interesting and useful 🥳.&lt;/p&gt;

</description>
      <category>chatgpt</category>
      <category>learning</category>
    </item>
    <item>
      <title>My Favourite Websites as a WordPress Developer</title>
      <dc:creator>Christina Garofalo</dc:creator>
      <pubDate>Mon, 07 Aug 2023 14:14:01 +0000</pubDate>
      <link>https://dev.to/plank/my-favourite-websites-as-a-wordpress-developer-kg9</link>
      <guid>https://dev.to/plank/my-favourite-websites-as-a-wordpress-developer-kg9</guid>
      <description>&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@tobben63?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Torbjørn Helgesen&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/SKlrApjIBrw?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;There are loads of useful websites out there to help you with your development, this is just a list of the ones that I use on an almost daily basis. As a fan of open-source and free tools, every one of these websites is free to use. Take a gander at this unordered, non-exhaustive list of handy websites.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://playground.wordpress.net"&gt;playground.wordpress.net&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Run WordPress in your browser. Try plugins and test things out, without the risk of messing up your environment. You can easily swap WordPress and PHP versions without the hassle of setting up a site locally. This is a brand new project, so if you do WordPress development, it’s pretty exciting. The documentation can be found &lt;a href="https://developer.wordpress.org/playground/"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://notpurple.com"&gt;notpurple.com&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;This hardly constitutes a website, but when you just need a dummy URL that’s live, I use notpurple.com. All this website does is randomly change the background colour to something other than purple on reload. That’s it.&lt;/p&gt;

&lt;p&gt;This site’s predecessor was shown to me by an IT technician when I was having issues with my home internet connection, and kept asking me to ping it, instead of Google. This website has a funny history, it used to be purple.com before it was sold not that long ago to a mattress company of the same name. All that site did was the same as notpurple.com, except that it only showed random shades of purple. It’s so bizarre that there’s a &lt;a href="https://en.wikipedia.org/wiki/Purple.com"&gt;Wiki article about it&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://placehold.co"&gt;placehold.co&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Every web developer just needs some good old-fashioned placeholder images, without needing to host them somewhere. There are numerous placeholder websites out there (including &lt;a href="https://placekitten.com"&gt;placekitten.com&lt;/a&gt; and &lt;a href="https://placebear.com"&gt;placebear.com&lt;/a&gt;), but I like placehold.co for its simplicity and versatility. You can define size, colour, text and format in one image URL. I will often use these as fallback images when coding. When all else fails - grab an image from placehold.co.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://ui-avatars.com"&gt;ui-avatars.com&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;This service is similar to placehold.co, except that it serves up avatars that use initials and a random colour. You can define the name, the colour, the size and the shape of the avatar (square or round) if you need something specific for your project.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://unsplash.com"&gt;unsplash.com&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Actually free, royalty-free images. This site was recently acquired by Getty Images, and now offers a paid tier (unsplash+), but there’s still plenty of free goodness to go around. You can also have access to these free images directly in the WordPress Media Library via the &lt;a href="https://wordpress.org/plugins/instant-images/"&gt;Instant Images&lt;/a&gt; plugin. It’s nice just having a source for high-quality images where you don’t need to worry about copyright concerns. While you don’t need to credit the photographers, personally I like to give credit where credit is due, I encourage you to do the same.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://jsoneditoronline.org"&gt;jsoneditoronline.org&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;This one is self-explanatory, it allows you to edit JSON in your browser. I mostly use this to sanity-check large blocks of JSON when working on custom importers and general data manipulation, as it points out syntax errors and differences. Useful for when you don’t want to fire up your IDE.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://onlinephp.io"&gt;onlinephp.io&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;I like to experiment with PHP, but I don’t always want to create a whole local dev site just to do it. This site lets you code directly in the browser and choose from the 400+ versions of PHP at your fingertips. Being able to effortlessly switch PHP versions is a handy way to refactor old code snippets and bring them up to date for PHP 8+, right in your browser.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://dnschecker.org"&gt;dnschecker.org&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Eventually, you are going to need to put your site live, so you buy a domain and host it somewhere. This means you’ll have to point your DNS records at a server. This website lets you check to see if your domain has propagated worldwide, allowing you to debug DNS issues faster. DNS propagation is known to take up to 48 hours, however, I find that most things get propagated in a few hours at most and at times as soon as 5 mins. This tool lets you see the results in almost real-time. (There is a checkbox that lets you auto-refresh to see changes every 20 seconds if you feel the need to watch it like a hawk.)&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://who.is"&gt;who.is&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;When I need to know where a domain is registered, I run it through Who.is. I mostly use this to help clients track down who is holding their domain “hostage”. A lot of the time, they don’t know, either because their predecessor didn’t inform them or some kind of bad breakup with a former developer or agency. This site helps shed light on the situation and could help you or your clients get in touch with the person or organization. (Or maybe you’re just nosey). &lt;/p&gt;

&lt;p&gt;These are just a handful of useful sites I’ve “collected” over the years that I keep going back to, and that generally hang out in my bookmark bar for quick access. What are the go-to websites that help you in your everyday development? I’m always on the hunt for useful tools, comment with your faves below!&lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>development</category>
      <category>tooling</category>
    </item>
    <item>
      <title>My Favourite WordPress Plugins as a Developer</title>
      <dc:creator>Christina Garofalo</dc:creator>
      <pubDate>Mon, 31 Jul 2023 13:54:54 +0000</pubDate>
      <link>https://dev.to/plank/my-favourite-wordpress-plugins-as-a-developer-14dc</link>
      <guid>https://dev.to/plank/my-favourite-wordpress-plugins-as-a-developer-14dc</guid>
      <description>&lt;p&gt;There are 59,592 plugins listed on &lt;a href="https://wordptress.org/plugins" rel="noopener noreferrer"&gt;WordPress.org&lt;/a&gt; at the moment of writing this blog post. That is a lot to sift through! This is the unordered, non-exhaustive list of my favourite plugins that I use as a developer just about every day, and maybe you’ll find them useful too — at the very least this will save you some time searching through a lot of defunct, irrelevant and poorly maintained plugins. I’m a huge fan of open-source software, so all plugins on this list are free to use or have a free version.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. &lt;a href="https://wordpress.org/plugins/fakerpress/" rel="noopener noreferrer"&gt;FakerPress&lt;/a&gt; by Gustavo Bordoni
&lt;/h3&gt;

&lt;p&gt;FakerPress is great for when you just need to populate a staging or local environment with fake posts and content for testing purposes. You can even fake users (which can be used with the User Switching plugin). It will also download and set featured images for you. The best part is when you are all done or need to reset the data, you can bulk delete anything that was generated by FakerPress.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. &lt;a href="https://wordpress.org/plugins/instant-images/" rel="noopener noreferrer"&gt;Instant Images&lt;/a&gt; by Darren Cooney
&lt;/h3&gt;

&lt;p&gt;Instead of using the same boring placeholder images over and over again during development, give Instant Images a go. You can import free &amp;amp; royalty-free images directly from Unsplash into the media library. It even fills out the title, caption and alt text for you (English only). I use this primarily for development, but there's no reason why it couldn't be used in production either. Having relevant images at your fingertips helps the client (and yourself) visualize what the site could look like on a staging site or save you the hassle of having to search for relevant images in another tab in your browser.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. &lt;a href="https://wordpress.org/plugins/wp-mail-smtp/" rel="noopener noreferrer"&gt;WP Mail SMTP&lt;/a&gt; by WP Mail SMTP
&lt;/h3&gt;

&lt;p&gt;Sometimes you need to get email working in your dev environments without the headache of setting up PHP’s mailer. WP Mail makes setting up email a straightforward process with its wizard. I like to use &lt;a href="https://mailtrap.io" rel="noopener noreferrer"&gt;Mailtrap.io&lt;/a&gt; for email testing. A single testing inbox is free and works with WP Mail with the SMTP settings. Using this plugin will ensure that emails sent from your site, such as password resets, will be delivered.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. &lt;a href="https://wordpress.org/plugins/filebird/" rel="noopener noreferrer"&gt;FileBird&lt;/a&gt; by Ninja Team
&lt;/h3&gt;

&lt;p&gt;This plugin creates folders/tags within the native media library. It has a beautiful UI and is extremely useful for keeping your media library organized, especially when you have a lot of files. It doesn’t alter the uploads directory either, so if you do decide to remove it, it won’t leave a mess. While this is handy during testing, it's also nice to have in production as well.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. &lt;a href="https://wordpress.org/plugins/user-switching/" rel="noopener noreferrer"&gt;User Switching&lt;/a&gt; by John Blackbourn &amp;amp; contributors
&lt;/h3&gt;

&lt;p&gt;If you are working on any kind of membership site or a site that has multiple users and roles, I strongly suggest using this plugin to test what the various users on your site can access and see. You can easily "switch" to appear logged in as different users on your site. I would not recommend this plugin be installed in a production environment, but it's certainly handy during testing.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. &lt;a href="https://wordpress.org/plugins/wp-help/" rel="noopener noreferrer"&gt;WP Help&lt;/a&gt; by Mark Jaquith
&lt;/h3&gt;

&lt;p&gt;Add some documentation right into the admin dashboard. Useful for keeping documentation for yourself, or helpful notes for the admins of the site. The only downside is that the documentation is stored in the database, making it difficult to migrate the documentation only from one site to another or commit it to a repository. (This is a bit of annoyance for me as I tend to use the same documentation over and over again with slight tweaks.) There is a feature to link documentation, and all changes made from the source will be mirrored on any linked sites which is handy for multisites. Barring that, it's a lifesaver for fielding potential questions from clients.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. &lt;a href="https://wordpress.org/plugins/password-protected/" rel="noopener noreferrer"&gt;Password Protected&lt;/a&gt; by WPExperts
&lt;/h3&gt;

&lt;p&gt;Does your host not allow basic auth or make it difficult to set up? Try Password Protected. This sets up basic auth for your WordPress site in minutes. You may even add IPs to an allow list so that you are not constantly pestered by the password prompt. This plugin was recommended to me by &lt;a href="https://pressable.com" rel="noopener noreferrer"&gt;Pressable&lt;/a&gt;, and it's now part of my developer arsenal.&lt;/p&gt;

&lt;h3&gt;
  
  
  8. &lt;a href="https://wordpress.org/plugins/query-monitor/" rel="noopener noreferrer"&gt;Query Monitor&lt;/a&gt; by John Blackbourn
&lt;/h3&gt;

&lt;p&gt;If you need to pull back the curtain and see what WordPress is doing in the background or want to improve the performance of your queries, try Query Monitor. It will give you an overwhelming amount of query data that can be used to fine-tune or debug your queries. This plugin hooks deeply into WordPress, so make sure you disable it in production.&lt;/p&gt;

&lt;h3&gt;
  
  
  9. &lt;a href="https://wordpress.org/plugins/debug-bar/" rel="noopener noreferrer"&gt;Debug Bar&lt;/a&gt; by wordpress.org
&lt;/h3&gt;

&lt;p&gt;This plugin adds debugging information right to your admin bar so you can quickly see logs for queries, caches, and other useful debugging info. Query Monitor can be overwhelming at times, however, this plugin is a bit more manageable. I would also recommend that this plugin not be used in production environments.&lt;/p&gt;

&lt;h3&gt;
  
  
  10. &lt;a href="https://www.advancedcustomfields.com/blog/installing-and-upgrading-to-the-latest-version-of-acf/" rel="noopener noreferrer"&gt;Advanced Custom Fields&lt;/a&gt; by WP Engine
&lt;/h3&gt;

&lt;p&gt;ACF is an essential plugin if you want to add custom fields to the CMS quickly and with ease. There is a free version of this plugin, but I would recommend getting a license, as it unlocks considerably more features, including the ability to build blocks without any React knowledge. It has a host of useful functions and filters that can be leveraged to make overall WordPress development less of a headache. I’m particularly fond of the &lt;code&gt;get_field()&lt;/code&gt; and &lt;code&gt;acf_slugify()&lt;/code&gt; helper functions. It’s a powerhouse of a plugin.&lt;/p&gt;

&lt;h3&gt;
  
  
  11. &lt;a href="https://wordpress.org/plugins/limit-login-attempts-reloaded/" rel="noopener noreferrer"&gt;Limit Login Attempts Reloaded&lt;/a&gt; By Limit Login Attempts Reloaded
&lt;/h3&gt;

&lt;p&gt;You’ve put a lot of work into your new site, you put it live and bask in its glory. Wouldn’t it be a shame if something happened to it? It doesn’t take long at all before some bot or hacker tries to brute force their way into your backend. This is a simple plugin that will block multiple attempts to log into your admin area. By default, any more than 3 attempts, and that IP will be blocked for 20 mins from trying to log into your site. That’s usually enough to stop a hacker in their tracks, as most are looking for easy targets, especially fresh installs. There is a pro version that allows you to do things like block IPs from entire countries, but the base version does a pretty good job with basic features.&lt;/p&gt;

&lt;h3&gt;
  
  
  12. &lt;a href="https://en-ca.wordpress.org/plugins/smntcs-disable-rest-api-user-endpoints" rel="noopener noreferrer"&gt;SMNTCS Disable REST API User Endpoints&lt;/a&gt; by Niels Lange
&lt;/h3&gt;

&lt;p&gt;Now with security in mind, did you know how easy for someone to find a list of every single user on your site? Very easy, just hit this endpoint on your WordPress site &lt;code&gt;/wp-json/wp/v2/users&lt;/code&gt;, and you’ll get the whole list, and that’s how hackers can probably deduce which user is an admin, and which accounts to target. This lightweight plugin disables that endpoint, so as long as you don’t need it for anything else, you can rest easy knowing that you’ve given potential nere-do-wells one more obstacle to deal with. There are ways to disable this with code, but this plugin is handy for the no-code approach.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Update Oct 11, 2024&lt;/strong&gt;: ACF download link has been updated, as it is no longer in the wordpress.org plugin directory due to the ongoing dispute.&lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>beginners</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Using the reduced motion media query in a project</title>
      <dc:creator>Riley McMaster</dc:creator>
      <pubDate>Mon, 24 Jul 2023 13:14:31 +0000</pubDate>
      <link>https://dev.to/plank/using-the-reduced-motion-media-query-in-a-project-34gb</link>
      <guid>https://dev.to/plank/using-the-reduced-motion-media-query-in-a-project-34gb</guid>
      <description>&lt;p&gt;The CSS media query &lt;code&gt;prefers-reduced-motion&lt;/code&gt; is a rule that checks the user's accessibility setting for "reduced motion" in their system preferences. It is not browser, website or session dependent but a setting on the user's computer itself. This media query allows us as developers to update any styles based on the user's preference for animation. &lt;/p&gt;

&lt;p&gt;The intent of this media query is to create a comfortable experience for all users. Animations can cause discomfort and even pain for neurodivergent users which can include people with vestibular disorders and users who are prone to inattention due to ADHD, bipolar disorder, depression or anxiety disorders. Other users may wish to turn on "reduced motion" to minimize distractions or reduce cognitive load. &lt;/p&gt;

&lt;p&gt;The problem is that not all sites accommodate the user's wishes and stop animations if they have selected "reduced motion".&lt;/p&gt;

&lt;p&gt;When a user chooses "reduced motion" it does not necessarily mean that they wish to have no motion at all. Some animations are extremely helpful for the user experience in providing visual feedback: a loading spinner that doesn't spin can make the user think the site is frozen, a button changing scale as you click it can emphasize that it has been clicked. Reducing motion is most beneficial when dealing with big parallax effects, scroll hijacking and animations that cover lots of screen space as these are most likely to cause issues for motion-sensitive users. &lt;/p&gt;

&lt;p&gt;A developer's initial instinct to using the &lt;code&gt;prefers-reduced-motion&lt;/code&gt; media query might be to stop animations on an individual selector basis:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;  &lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="n"&gt;screen&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prefers-reduced-motion&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;animation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&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 will likely cause issues because the animations can get stuck at their initial value (ie. opacity: 0 and the position is off screen).&lt;/p&gt;

&lt;p&gt;We want a more global solution that will make it easier to develop for users who want less motion. We also need for the animations to play so that the elements end up at their desired end point, while not noticing the in-between states of the animation. We can use the animation and transition &lt;code&gt;duration&lt;/code&gt; property to force the animations to run at a speed so fast that it is imperceivable. &lt;/p&gt;

&lt;p&gt;In the root level of our CSS, we call the reduced-motion media query and target a specific class that will 'turn off' the animations for those elements.&lt;/p&gt;

&lt;p&gt;A more global and adaptable solution:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="n"&gt;only&lt;/span&gt; &lt;span class="n"&gt;screen&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prefers-reduced-motion&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nc"&gt;.reduce-motion&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="nc"&gt;.reduce-motion&lt;/span&gt;&lt;span class="nd"&gt;::before&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="nc"&gt;.reduce-motion&lt;/span&gt;&lt;span class="nd"&gt;::after&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;animation-delay&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0s&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;animation-duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.001ms&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;animation-iteration-count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
    &lt;span class="nl"&gt;transition-duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;.0001ms&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;transition-delay&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0s&lt;/span&gt; &lt;span class="cp"&gt;!important&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;As we are developing, we can add the class &lt;code&gt;reduce-motion&lt;/code&gt; to any elements that we think are not necessary to the user experience or could cause discomfort to the motion-sensitive users. &lt;/p&gt;

&lt;p&gt;While we try to use the &lt;code&gt;!important&lt;/code&gt; property as little as possible, it is a valuable use of it here since the point is to be a global override of any animation and transition properties further down the style-sheet. &lt;/p&gt;

&lt;p&gt;This isn't necessarily a perfect solution but it is important to have these conversations about how different people experience the web. In order to build more inclusive sites, we need to listen to issues people have and address them with any tools that we have available to us. &lt;/p&gt;

&lt;p&gt;Sources that helped inform this article:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://css-tricks.com/revisiting-prefers-reduced-motion/"&gt;https://css-tricks.com/revisiting-prefers-reduced-motion/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://alistapart.com/article/designing-safer-web-animation-for-motion-sensitivity/"&gt;https://alistapart.com/article/designing-safer-web-animation-for-motion-sensitivity/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://alistapart.com/article/designing-for-cognitive-differences/"&gt;https://alistapart.com/article/designing-for-cognitive-differences/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>css</category>
      <category>a11y</category>
      <category>webdev</category>
    </item>
    <item>
      <title>WCEU23: Block Workshops Recap</title>
      <dc:creator>Christina Garofalo</dc:creator>
      <pubDate>Wed, 28 Jun 2023 14:05:25 +0000</pubDate>
      <link>https://dev.to/plank/wceu23-block-workshops-recap-254i</link>
      <guid>https://dev.to/plank/wceu23-block-workshops-recap-254i</guid>
      <description>&lt;p&gt;I attended 2 workshops this year at WCEU23 in Athens, both were about blocks. &lt;a href="https://plank.co"&gt;At Plank, we create custom WordPress themes for clients that almost always involve custom blocks.&lt;/a&gt; It's a subject that's been unavoidable since the introduction of them in WordPress 5.0 - and we like them. It allows us to create modular designs that give our clients the power to layout their content that stays consistent with their branding without constantly involving developers after the site launch. So naturally I was interested in seeing what the rest of the WordPress community was up to when it came to the subject of blocks.&lt;/p&gt;

&lt;p&gt;The first workshop I attended was by Luis Herranz ( &lt;a class="mentioned-user" href="https://dev.to/luisherranz"&gt;@luisherranz&lt;/a&gt; ), "&lt;a href="https://europe.wordcamp.org/2023/session/building-interactive-blocks-a-step-by-step-workshop/"&gt;Building interactive blocks: a step-by-step workshop&lt;/a&gt;". According to Luis, the interactive API will hopefully be making its debut in WordPress 6.4 🤞. The goal of the Interactive API is to facilitate implementing interactive features into blocks natively, such as “heart this post” or “add to cart” without page reload. You can read his proposal for the interactive API &lt;a href="https://make.wordpress.org/core/2023/03/30/proposal-the-interactivity-api-a-better-developer-experience-in-building-interactive-blocks/"&gt;here&lt;/a&gt;. You can download the repo from the workshop here and jump through the steps of his example &lt;a href="https://github.com/luisherranz/wceu2023"&gt;here&lt;/a&gt;. Personally, I can't wait to see this feature in core.&lt;/p&gt;

&lt;p&gt;The second workshop I attended was by Robert Richardson, "&lt;a href="https://europe.wordcamp.org/2023/session/code-techniques-for-handling-dynamic-data-in-the-newish-world-of-blocks/"&gt;Code techniques for handling dynamic data in the new(ish) world of blocks&lt;/a&gt;". What was interesting about this workshop, for me, wasn't really anything new; but it was really assuring to me that Plank's on the right track concerning the development of blocks. When he asked the room of about 50-60 attendees "who was using custom REST API endpoints to pass data to their blocks", I was the only one who raised their hand! I was honestly shocked that no one else seemed to take this approach to handling data. I recommend leveraging the &lt;a href="https://developer.wordpress.org/rest-api/"&gt;REST API&lt;/a&gt; capabilities of WordPress for use in your blocks. It's very easy to set up, and very powerful. React developers will have a field day.&lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>workshops</category>
      <category>wordcamp</category>
      <category>gutenburg</category>
    </item>
    <item>
      <title>WordPress Playground</title>
      <dc:creator>Dave Kellam</dc:creator>
      <pubDate>Tue, 27 Jun 2023 19:14:08 +0000</pubDate>
      <link>https://dev.to/plank/wordpress-playground-2ig0</link>
      <guid>https://dev.to/plank/wordpress-playground-2ig0</guid>
      <description>&lt;p&gt;One of the most exciting things at &lt;a href="https://europe.wordcamp.org/2023/" rel="noopener noreferrer"&gt;WordCamp Europe 2023&lt;/a&gt; for me was discovering how far along the &lt;a href="https://developer.wordpress.org/playground/" rel="noopener noreferrer"&gt;WordPress Playground&lt;/a&gt; project is. If you haven’t heard of the playground before, it’s a full version of WordPress, running directly in your browser!&lt;/p&gt;

&lt;h2&gt;
  
  
  History
&lt;/h2&gt;

&lt;p&gt;The project began &lt;a href="https://make.wordpress.org/core/2022/09/23/client-side-webassembly-wordpress-with-no-server/" rel="noopener noreferrer"&gt;late last summer&lt;/a&gt;, with version 0.1 being released in April. The readme indicates that it was inspired by the initial PHP WASM implementation,  a Drupal in the browser example, and a &lt;a href="https://wasmlabs.dev/articles/wordpress-in-the-browser/" rel="noopener noreferrer"&gt;WASM Labs WordPress demo&lt;/a&gt;. The WordPress Playground was introduced to the larger WordPress community during the &lt;a href="https://www.hostinger.com/blog/state-of-the-word-2022#WordPress_Playground" rel="noopener noreferrer"&gt;2022 State of the Word&lt;/a&gt; presentation. &lt;/p&gt;

&lt;p&gt;The Playground was actively promoted during WCEU this year — used to quickly spin up sites for the &lt;a href="https://dev.to/cgarofalo/contributor-day-at-wceu23-in-athens-15c1"&gt;documentation team&lt;/a&gt;, and others,  on &lt;a href="https://wordpress.github.io/wordpress-playground/wordcamp-contributor-day/" rel="noopener noreferrer"&gt;contributor day&lt;/a&gt;, featured in a &lt;a href="https://europe.wordcamp.org/2023/wp-connect/" rel="noopener noreferrer"&gt;connect track&lt;/a&gt; session, and a &lt;a href="https://youtu.be/7Nmz3IjtPh0?t=374" rel="noopener noreferrer"&gt;demo during the keynote.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;p&gt;The technology behind the Playground is called WASM, short for &lt;a href="https://webassembly.org/" rel="noopener noreferrer"&gt;Web Assembly&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;WebAssembly (abbreviated Wasm) is a binary instruction format for a stack-based virtual machine. Wasm is designed as a portable compilation target for programming languages, enabling deployment on the web for client and server applications.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There are versions of PHP compiled into WASM binaries that allow you to run PHP code directly in the browser. The Playground then uses those binaries to &lt;a href="https://wordpress.github.io/wordpress-playground/architecture/wordpress" rel="noopener noreferrer"&gt;run the WordPress PHP application&lt;/a&gt;, as well as a plugin that allows MySQL calls to be intercepted and interpreted to SQLite&lt;/p&gt;

&lt;h2&gt;
  
  
  Demos
&lt;/h2&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%2Fgfknl4sn4a2y961nbbmf.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%2Fgfknl4sn4a2y961nbbmf.png" alt="Screenshot of the Playground with Frost Theme" width="800" height="388"&gt;&lt;/a&gt;WordPress Playground with Frost theme installed&lt;/p&gt;

&lt;p&gt;Unfortunately, you can’t embed playground iframes in dev.to, but we can link directly to a few examples of it in action. The &lt;a href="https://playground.wordpress.net" rel="noopener noreferrer"&gt;Playground default&lt;/a&gt; uses the latest version of WordPress with the default theme and PHP 8.0. &lt;/p&gt;

&lt;p&gt;You can use query parameters, like &lt;code&gt;theme&lt;/code&gt; and &lt;code&gt;plugins&lt;/code&gt; to install a particular theme or plugin in the Playground. In &lt;a href="https://playground.wordpress.net/?theme=frost&amp;amp;plugin=coblocks" rel="noopener noreferrer"&gt;this example&lt;/a&gt;, we install the Frost theme and CoBlocks plugin. You can also pass &lt;code&gt;wp&lt;/code&gt; and &lt;code&gt;php&lt;/code&gt; to install different versions of WordPress and PHP.&lt;/p&gt;

&lt;p&gt;If you’re embedding an iframe, the experience is also totally &lt;a href="https://wordpress.github.io/wordpress-playground/javascript-api/index" rel="noopener noreferrer"&gt;scriptable&lt;/a&gt;. One example of the iframes in action is the &lt;a href="https://adamadam.blog/2023/02/16/how-to-modify-html-in-a-php-wordpress-plugin-using-the-new-tag-processor-api/" rel="noopener noreferrer"&gt;tutorial&lt;/a&gt; for using the new tag processor function.&lt;/p&gt;

&lt;h2&gt;
  
  
  The future
&lt;/h2&gt;

&lt;p&gt;The Playground opens up a lot of possibilities since it makes WordPress embeddable in so many areas: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We can easily test different versions of WordPress and PHP&lt;/li&gt;
&lt;li&gt;We can &lt;a href="https://jonathanbossenger.com/2023/06/19/testing-out-the-wp-playground-interactive-code-block/" rel="noopener noreferrer"&gt;embed live examples&lt;/a&gt; in tutorials and lessons&lt;/li&gt;
&lt;li&gt;A &lt;a href="https://marketplace.visualstudio.com/items?itemName=WordPressPlayground.wordpress-playground" rel="noopener noreferrer"&gt;VS Code extension&lt;/a&gt; allows you to open a theme or plugin up in a usable test environment&lt;/li&gt;
&lt;li&gt;It can be embedded directly in &lt;a href="https://twitter.com/adamzielin/status/1669478239771799552" rel="noopener noreferrer"&gt;mobile apps&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;We can include live demos in pull requests&lt;/li&gt;
&lt;li&gt;It can be integrated into a CI/CD pipeline&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;a href="https://github.com/WordPress/wordpress-playground/issues/472" rel="noopener noreferrer"&gt;vision and philosophy&lt;/a&gt; and &lt;a href="https://github.com/WordPress/wordpress-playground/issues/525" rel="noopener noreferrer"&gt;roadmap&lt;/a&gt; are both available on GitHub, so you can see where things are headed. It’s still early on, version 0.2 was just released a few days ago on June 24th. We’re likely to see breaking changes at times until an official 1.0 release happens.&lt;/p&gt;

&lt;p&gt;Now it’s time to go &lt;a href="https://wordpress.github.io/wordpress-playground/" rel="noopener noreferrer"&gt;play&lt;/a&gt;.&lt;/p&gt;

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