<?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: Anthony Fung</title>
    <description>The latest articles on DEV Community by Anthony Fung (@ant_f_dev).</description>
    <link>https://dev.to/ant_f_dev</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1021330%2Fb38e4565-4ef4-493b-8cb8-825b54793db6.jpg</url>
      <title>DEV Community: Anthony Fung</title>
      <link>https://dev.to/ant_f_dev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ant_f_dev"/>
    <language>en</language>
    <item>
      <title>Absolute vs. Relative Co-ordinates for Defining an SVG Path</title>
      <dc:creator>Anthony Fung</dc:creator>
      <pubDate>Wed, 27 Mar 2024 13:00:00 +0000</pubDate>
      <link>https://dev.to/ant_f_dev/absolute-vs-relative-co-ordinates-for-defining-an-svg-path-5bec</link>
      <guid>https://dev.to/ant_f_dev/absolute-vs-relative-co-ordinates-for-defining-an-svg-path-5bec</guid>
      <description>&lt;p&gt;We &lt;a href="https://webdeveloperdiary.substack.com/p/convert-simple-icons-from-sketches-to-svg"&gt;previously&lt;/a&gt; looked at taking an icon drawn on paper and converting it to SVG code. The process first involves identifying co-ordinates for key points within a design. We use these alongside a set of commands to form the data for a path element to render our icon.&lt;/p&gt;

&lt;p&gt;The icon we transcribed used three commands: M, L, and Z. These respectively represent &lt;strong&gt;M&lt;/strong&gt;oving to a location, drawing a straight &lt;strong&gt;L&lt;/strong&gt;ine to a point, and closing an open path. Like much in programming, casing is important. Many path commands also have a lower-case counterpart.&lt;/p&gt;

&lt;p&gt;In this article, we’ll look at how they differ.&lt;/p&gt;

&lt;h2&gt;
  
  
  Moving To or Passing By?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  An Example
&lt;/h3&gt;

&lt;p&gt;The following SVG renders to look like the square shown in Image 1. As we’re focussing on the &lt;code&gt;d&lt;/code&gt; attribute of the path element, I’ve left out both styling attributes, and the html for a Web page to host the SVG.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;svg&lt;/span&gt; &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2000/svg"&lt;/span&gt; &lt;span class="na"&gt;viewBox=&lt;/span&gt;&lt;span class="s"&gt;"0 0 7 7"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;path&lt;/span&gt; &lt;span class="na"&gt;d=&lt;/span&gt;&lt;span class="s"&gt;"m1,1 l5,0 l0,5 l-5,0 z"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/path&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/svg&amp;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%2Fxk410lgz7emdjab2h6uc.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%2Fxk410lgz7emdjab2h6uc.png" alt="A yellow square with a black outline" width="90" height="90"&gt;&lt;/a&gt;&lt;/p&gt;

Image 1: An SVG containing a Path element defined with relative commands




&lt;p&gt;Now, let’s use the same markup but with one modification. Instead of lower-case commands in the value of the d attribute, we’ll use their upper-case equivalents. The result is shown in Image 2.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;svg&lt;/span&gt; &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2000/svg"&lt;/span&gt; &lt;span class="na"&gt;viewBox=&lt;/span&gt;&lt;span class="s"&gt;"0 0 7 7"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;path&lt;/span&gt; &lt;span class="na"&gt;d=&lt;/span&gt;&lt;span class="s"&gt;"M1,1 L5,0 L0,5 L-5,0 Z"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/path&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/svg&amp;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%2Fm5rza4bjr1djbslchmh2.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%2Fm5rza4bjr1djbslchmh2.png" alt="A partial view of an irregular yellow shape with a black outline" width="90" height="90"&gt;&lt;/a&gt;&lt;/p&gt;

Image 2: The results of rendering the SVG in Image 1 using upper case commands in the path element




&lt;h3&gt;
  
  
  What’s Going On?
&lt;/h3&gt;

&lt;p&gt;In general, lower-case commands work with relative co-ordinates. In contrast, upper-case versions interpret them to be absolute. Z (and z) is an exception; these behave in the same way as they don’t rely on co-ordinates.&lt;/p&gt;

&lt;p&gt;In the markup for Image 1, we declared instructions to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;m1,1&lt;/code&gt;: move across and down &lt;strong&gt;by&lt;/strong&gt; 1 unit from the origin without drawing.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;l5,0&lt;/code&gt;: draw a line &lt;strong&gt;for&lt;/strong&gt; 5 units rightwards.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;l0,5&lt;/code&gt;: draw a line &lt;strong&gt;for&lt;/strong&gt; 5 units downwards.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;l-5,0&lt;/code&gt;: draw a line &lt;strong&gt;for&lt;/strong&gt; 5 units leftwards.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;z&lt;/code&gt;: close the loop, resulting in drawing a line upwards.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;As we can see in Image 1, this forms a square.&lt;/p&gt;

&lt;p&gt;In the markup for Image 2, we:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;M1,1&lt;/code&gt;: moved directly &lt;strong&gt;to&lt;/strong&gt; point (1,1).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;L5,0&lt;/code&gt;: draw a line rightwards and upwards &lt;strong&gt;to&lt;/strong&gt; point (5,0).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;L0,5&lt;/code&gt;: draw a line downwards and leftwards &lt;strong&gt;to&lt;/strong&gt; point (0,5).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;L-5,0&lt;/code&gt;: draw a line leftwards and upwards &lt;strong&gt;to&lt;/strong&gt; point (-5,0).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Z&lt;/code&gt;: close the loop, resulting in a line being drawn rightwards and downwards back towards point (1,1).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In Image 2, we only see part of the shape we’ve drawn. The image’s &lt;code&gt;viewBox&lt;/code&gt; attribute has a top-left co-ordinate of (0,0); parts of the image with negative co-ordinates are outside of our specified viewport.&lt;/p&gt;

&lt;h2&gt;
  
  
  Absolute vs Relative Co-ordinates
&lt;/h2&gt;

&lt;p&gt;Ultimately, it’s possible to achieve the same results whether we use absolute, relative, or mixed co-ordinates. The important thing is to be mindful of which is being used when plotting the next point in an image.&lt;/p&gt;

&lt;p&gt;When thinking about an object’s outline, it may be easier to use relative co-ordinates. That way, we only need concern ourselves with how far we move in each direction. As we don’t need to specify exact co-ordinates, we’re left to focus only on the shape being drawn.&lt;/p&gt;

&lt;p&gt;But when transferring diagrams from graph (or dotted) paper, it may be preferable to use absolute co-ordinates. The positions of key points will be marked on the page, removing the need to mentally track their whereabouts. And by specifying exactly where each data point is, any ambiguity about their locations – which might be important when using the &lt;code&gt;viewBox&lt;/code&gt; attribute – is eliminated.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;The syntax for declaring an SVG path is case sensitive. In general, upper-case commands treat co-ordinates as being absolute and lower-case versions relative.&lt;/p&gt;

&lt;p&gt;When mentally following an object’s outline, you may find it easier to think in terms of relative co-ordinates when moving from point to point. But when transferring an image from a design on paper, there’s less ambiguity with absolute co-ordinates.&lt;/p&gt;

&lt;p&gt;You can use relative or absolute co-ordinates when defining data for a path; it’s even possible to use a mix of the two. The important thing is to use the system that’s most convenient for you.&lt;/p&gt;




&lt;p&gt;Thanks for reading!&lt;/p&gt;

&lt;p&gt;This article is from my &lt;a href="https://webdeveloperdiary.substack.com/?sd=pf"&gt;newsletter&lt;/a&gt;. If you found it useful, please consider subscribing. You’ll get more articles like this delivered straight to your inbox (once per week), plus bonus developer tips too!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>frontend</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Change Colours in a Bitmap Image using Browser CSS Filters</title>
      <dc:creator>Anthony Fung</dc:creator>
      <pubDate>Wed, 20 Mar 2024 13:00:00 +0000</pubDate>
      <link>https://dev.to/ant_f_dev/change-colours-in-a-bitmap-image-using-browser-css-filters-262</link>
      <guid>https://dev.to/ant_f_dev/change-colours-in-a-bitmap-image-using-browser-css-filters-262</guid>
      <description>&lt;p&gt;Last week we looked at how we can create greyscale versions of images in real time. Maybe we want to give our images a different flavour. Or maybe we might want to create engaging mouseover effects. In either case, we can use CSS to achieve our goal instead of having to potentially create and manage multiple versions of images.&lt;/p&gt;

&lt;p&gt;Theming is another area we’ve looked at recently where we might need different versions of the same image – we might have multiple themes and want our icons to be a different colour in each. Well, it turns out we can use CSS to achieve this too. There are some caveats however, but to avoid this week’s newsletter from becoming too long, we’ll save those for another.&lt;/p&gt;

&lt;h2&gt;
  
  
  A (Very) High Level Exploration of Colour Theory
&lt;/h2&gt;

&lt;p&gt;We can express colour in many ways. One common format in CSS is a hexadecimal code, e.g. &lt;code&gt;#6495ed&lt;/code&gt;. Here, we use the first two characters (&lt;code&gt;64&lt;/code&gt;) to specify the amount of red in the colour, the next two (&lt;code&gt;95&lt;/code&gt;) for green, and the final two (&lt;code&gt;ed&lt;/code&gt;) blue. In other words, we describe a colour by its intensities of pure red, green, and blue.&lt;/p&gt;

&lt;p&gt;But we can model colour in other ways too. In some models, we reference the hue (base colour tone, e.g. orange, blue, etc.) directly. Image 1 shows the colour wheel from &lt;a href="https://www.gimp.org/"&gt;GIMP&lt;/a&gt; and gives us an idea of how this works. Looking at the outer ring, we can see we can specify any colour we need by referencing its degree of rotation; red is at 0, green at 120, and blue at 240. (Black, white, and the greys between are a special case and can be achieved via other parameters).&lt;/p&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%2Fgcd3ouhgmwhxrw35tqrq.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%2Fgcd3ouhgmwhxrw35tqrq.png" alt="he wheel from the colour picker in GIMP" width="177" height="204"&gt;&lt;/a&gt;&lt;/p&gt;

Image 1: The wheel from the colour picker in GIMP




&lt;h2&gt;
  
  
  Hue Shifting
&lt;/h2&gt;

&lt;p&gt;If we want an image in our app to have a different colour, one option is to use the CSS &lt;code&gt;hue-rotate&lt;/code&gt; filter. By specifying a degree of rotation, we can work with these colour models, offsetting every colour in the image by the indicated amount.&lt;/p&gt;

&lt;p&gt;As an example, Image 2 shows a blue arrow. Let’s say we wanted a red version of it. Looking at Image 1, we can see blue is at around the 7 o’clock position on the outer ring. We want it to be red, which is at the 3 o’clock position – one third of the way (120 degrees) anticlockwise around the ring. Based on this, we can apply a 120 degree hue rotation to it:&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="nt"&gt;filter&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;hue-rotate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;120&lt;/span&gt;&lt;span class="nt"&gt;deg&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result of this is shown in Image 3.&lt;/p&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%2Fv9z441bmcksdwl5j5ybg.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%2Fv9z441bmcksdwl5j5ybg.png" alt="A blue arrow pointing leftwards" width="456" height="327"&gt;&lt;/a&gt;&lt;/p&gt;

Image 2: An image of a blue arrow




&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%2Fbhiypvsbnchcrua1wcd5.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%2Fbhiypvsbnchcrua1wcd5.png" alt="A red arrow pointing leftwards" width="456" height="327"&gt;&lt;/a&gt;&lt;/p&gt;

Image 3: The blue arrow shown in Image 1 with a hue rotation of 120 degrees applied




&lt;p&gt;Bear in mind the degree of rotation offset refers to anticlockwise movements within the circle of hues in Image 1. Let’s say we wanted our original blue arrow to be green. Green is an additional one third of the way around the circle from red; a further 120 degrees makes the total offset 240 degrees. The following CSS would produce the results shown in Image 4.&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="nt"&gt;filter&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;hue-rotate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;240&lt;/span&gt;&lt;span class="nt"&gt;deg&lt;/span&gt;&lt;span class="o"&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%2Fc9abq47vod0sfmub5io6.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%2Fc9abq47vod0sfmub5io6.png" alt="A green arrow pointing leftwards" width="456" height="327"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;br&gt;
Image 4: The blue arrow shown in Image 1 with a hue rotation of 240 degrees applied&lt;br&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;You can use CSS to change colours within images in real time. This means you can have many versions of icon bitmaps without needing to manage multiple files.&lt;/p&gt;

&lt;p&gt;Some colour models distribute the base colour tones across a circle spanning 360 degrees. With the &lt;code&gt;hue-rotate&lt;/code&gt; CSS filter, you can work with these models to offset colours in an image by the amount specified. With careful usage, you can leverage this for areas such as theming – you’ll have different-coloured versions of icons, but without the hassle of maintaining separate files.&lt;/p&gt;




&lt;p&gt;Thanks for reading!&lt;/p&gt;

&lt;p&gt;This article is from my &lt;a href="https://webdeveloperdiary.substack.com/?sd=pf"&gt;newsletter&lt;/a&gt;. If you found it useful, please consider subscribing. You’ll get more articles like this delivered straight to your inbox (once per week), plus bonus developer tips too!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>frontend</category>
      <category>tutorial</category>
      <category>css</category>
    </item>
    <item>
      <title>Using Browser Filters for Mouseover Effects in Web apps</title>
      <dc:creator>Anthony Fung</dc:creator>
      <pubDate>Wed, 13 Mar 2024 13:00:00 +0000</pubDate>
      <link>https://dev.to/ant_f_dev/using-browser-filters-for-mouseover-effects-in-web-apps-2c8d</link>
      <guid>https://dev.to/ant_f_dev/using-browser-filters-for-mouseover-effects-in-web-apps-2c8d</guid>
      <description>&lt;p&gt;Last week, we looked at how we can use different images to change the appearances of icons in our Web apps. This approach gives us more flexibility. It also allows us to be very specific about in how various states look. However, it introduces a downside. By having more images, we increase the overall workload in creating and maintaining them in our projects.&lt;/p&gt;

&lt;p&gt;Changing colours within an SVG is relatively simple. As we can reference elements in an image (both individually and collectively), we can specify and modify their colours using CSS – something we can’t do with bitmap images. However, we can leverage powerful CSS filters to do something similar.&lt;/p&gt;

&lt;p&gt;In this article, we’ll look how we can create a button with an icon showing a grey arrow; this arrow will turn blue when the mouse cursor moves over it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding Colour
&lt;/h2&gt;

&lt;p&gt;Let’s take our previous use case as an example: we have a button in our app that shows an arrow pointing leftwards. Ordinarily, we want it to be grey. But when the mouse moves over it, we want it to become blue.&lt;/p&gt;

&lt;p&gt;When solving this problem with multiple images, we used two images – one grey, one blue. With CSS filters, we can cut this down to just one. By taking advantage of the &lt;code&gt;grayscale&lt;/code&gt; filter, we can desaturate (i.e. remove colour intensity from) any image. This means we can convert our blue arrow (Image 1) into a grey one (Image 2) dynamically at run time with the following CSS:&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="nt"&gt;filter&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;grayscale&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;100&lt;/span&gt;&lt;span class="o"&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%2Fmiyr8h2nadrrwhileq29.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%2Fmiyr8h2nadrrwhileq29.png" alt="A blue arrow pointing leftwards" width="470" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

Image 1: A blue arrow without a grayscale filter applied




&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%2Fgylmlu0fd6k733cfciax.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%2Fgylmlu0fd6k733cfciax.png" alt="A grey arrow pointing leftwards" width="470" height="334"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;br&gt;
Image 2: The blue arrow shown in Image 1 with a 100% grayscale filter applied&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;We’ve passed in a value of &lt;code&gt;100%&lt;/code&gt;. If we wanted to make the effect more subtle, we can tweak this value accordingly. In any case, we can achieve the hover effect with the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!doctype html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en-US"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Image Demo&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"styles.css"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;img&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;grayscale&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="err"&gt;img&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="sx"&gt;url(../Images/arrow-dark.png)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;grayscale&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="p"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the preceding code, we’re always using a dark blue image of an arrow. In the normal state, we apply a &lt;code&gt;grayscale&lt;/code&gt; filter to remove its colour. But in the hover state, we effectively disable it by applying a value of &lt;code&gt;0%&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;When creating hover effects, an alternative to using multiple images is to leverage the browser's CSS filters. These let you manipulate images in real time, allowing you to keep the number of files required to a minimum.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;grayscale&lt;/code&gt; filter lets you desaturate (or remove colour intensity from) an image. When you use this, you can have a greyscale icon or image burst into full colour when certain events happen; an example might be when the mouse pointer moves over it. Its simple syntax lets you specify how strongly to apply it, leaving you in full control of how your images look.&lt;/p&gt;




&lt;p&gt;Thanks for reading!&lt;/p&gt;

&lt;p&gt;This article is from my &lt;a href="https://webdeveloperdiary.substack.com/?sd=pf"&gt;newsletter&lt;/a&gt;. If you found it useful, please consider subscribing. You’ll get more articles like this delivered straight to your inbox (once per week), plus bonus developer tips too!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>frontend</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Dynamically Change PNG Icon Colours for Mouseover Effects</title>
      <dc:creator>Anthony Fung</dc:creator>
      <pubDate>Wed, 06 Mar 2024 13:00:00 +0000</pubDate>
      <link>https://dev.to/ant_f_dev/dynamically-change-png-icon-colours-for-mouseover-effects-213h</link>
      <guid>https://dev.to/ant_f_dev/dynamically-change-png-icon-colours-for-mouseover-effects-213h</guid>
      <description>&lt;p&gt;We previously looked at how we can dynamically change the colours within an SVG image in a Web app. This can be useful for several reasons, ranging from app theming to special effects to improving overall usability.&lt;/p&gt;

&lt;p&gt;But what if you’re not using SVGs? If you’re using bitmap graphics – whether JPG, PNG, or something else – it’s not possible to update the colours of image elements in the same way. However, there are a few things we can do. In this week’s article, we’ll look at one possible option.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using One Image per State
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Hover States
&lt;/h3&gt;

&lt;p&gt;Let’s say we have an app, and we want one of its buttons to have an icon of an arrow pointing leftwards. We want it to be grey, until the mouse pointer moves over it. When that happens, we want it to be blue – to show the button is clickable.&lt;/p&gt;

&lt;p&gt;We can achieve this by creating two versions of the arrow and saving them as separate images – one where the arrow is grey (Image 1), and one where it’s blue (Image 2).&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%2Fau462bl572li6tikq8qk.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%2Fau462bl572li6tikq8qk.png" alt="A grey arrow pointing left"&gt;&lt;/a&gt;&lt;/p&gt;

Image 1: A grey arrow pointing left




&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%2Fdlfexlk4jsqsisq3jqxd.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%2Fdlfexlk4jsqsisq3jqxd.png" alt="A blue arrow pointing left"&gt;&lt;/a&gt;&lt;/p&gt;

Image 2: A blue version of the arrow shown in Image 1




&lt;p&gt;In our app, we can use CSS to show a different image depending on whether the mouse pointer is over the button or not. The following example creates a simple Web page with a single button. The button shows the grey arrow unless the mouse is hovered over it, at which point it shows the blue arrow.&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&lt;br&gt;
 html&lt;br&gt;
&amp;lt;!doctype html&amp;gt;&lt;br&gt;
&amp;lt;html lang="en-US"&amp;gt;

&lt;p&gt;&amp;lt;head&amp;gt;&lt;br&gt;
  &amp;lt;title&amp;gt;Image Demo&amp;lt;/title&amp;gt;&lt;br&gt;
  &amp;lt;link rel="stylesheet" href="styles.css"&amp;gt;&lt;br&gt;
&amp;lt;/head&amp;gt;&lt;/p&gt;

&lt;p&gt;&amp;lt;body&amp;gt;&lt;br&gt;
  &amp;lt;button&amp;gt;&lt;br&gt;
    &amp;lt;img&amp;gt;&lt;br&gt;
  &amp;lt;/button&amp;gt;&lt;br&gt;
&amp;lt;/body&amp;gt;&lt;/p&gt;

&lt;p&gt;&amp;lt;/html&amp;gt;&lt;/p&gt;

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

&lt;/div&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&lt;br&gt;
 css&lt;br&gt;
button {&lt;br&gt;
  img {&lt;br&gt;
    content:url(../Images/arrow-grey.png);
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;amp;amp;:hover {
  content:url(../Images/arrow-blue.png);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;}&lt;br&gt;
}&lt;/p&gt;

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

&lt;/div&gt;
&lt;h3&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Theming&lt;br&gt;
&lt;/h3&gt;

&lt;p&gt;In addition to hover states, we can also use this technique (of having an image per state) for theming. Let’s say we have a light theme and a dark theme. The icons need to be visible when using either, so we want the light theme to use a set of dark-coloured icons against light backgrounds. Similarly, the dark theme should use a set of light icons against dark backgrounds.&lt;/p&gt;

&lt;p&gt;If we have a separate stylesheet – or simply use different sections within the same one – for each theme, we can modify the paths to our icon files accordingly.&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&lt;br&gt;
 css&lt;br&gt;
.dark {&lt;br&gt;
  button {&lt;br&gt;
    img {&lt;br&gt;
      background-color: #222;&lt;br&gt;
      content:url(../Images/arrow-light.png);&lt;br&gt;
    }&lt;br&gt;
  }&lt;br&gt;
}

&lt;p&gt;.light {&lt;br&gt;
  button {&lt;br&gt;
    img {&lt;br&gt;
      background-color: #eee;&lt;br&gt;
      content:url(../Images/arrow-dark.png);&lt;br&gt;
    }&lt;br&gt;
  }&lt;br&gt;
}&lt;/p&gt;

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

&lt;/div&gt;
&lt;h3&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Pros and Cons&lt;br&gt;
&lt;/h3&gt;

&lt;p&gt;Having a different image for each icon variation comes with its disadvantages. Because each version needs its own image, it means our projects end up with more files. This can complicate both management and deployment:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The app’s download size potentially increases. The change may be small, but the difference could be noticeable.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A change in colour scheme means recreating and replacing an entire set of icons.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The project becomes more difficult to navigate in source form.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;There are more files to keep track of.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, capturing exactly how each icon should appear in each state means we have a bit more flexibility:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;We can then tweak their appearance until pixel perfect.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We can apply advanced image-editing techniques and special effects.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Effects are applied directly to and captured within the image: they’ll look the same in any browser.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;When building an app, you can’t selectively change colours in a bitmap in real time like you can with an SVG. One workaround is using different images.&lt;/p&gt;

&lt;p&gt;With this approach, you can still use CSS to define themes and mouse-over states. But the downside is that you end up with more files to manage. This can make a project more difficult to navigate and create more work if you ever need to update any of its colours.&lt;/p&gt;

&lt;p&gt;However, you gain some flexibility by doing so. You can edit and tweak each image until you’re happy with it, and you can be sure it’ll look the same in any browser.&lt;/p&gt;




&lt;p&gt;Thanks for reading!&lt;/p&gt;

&lt;p&gt;This article is from my &lt;a href="https://webdeveloperdiary.substack.com/?sd=pf" rel="noopener noreferrer"&gt;newsletter&lt;/a&gt;. If you found it useful, please consider subscribing. You’ll get more articles like this delivered straight to your inbox (once per week), plus bonus developer tips too!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>frontend</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Convert Simple Icon Designs from Paper Sketches to SVG Code</title>
      <dc:creator>Anthony Fung</dc:creator>
      <pubDate>Wed, 28 Feb 2024 13:00:00 +0000</pubDate>
      <link>https://dev.to/ant_f_dev/convert-simple-icon-designs-from-paper-sketches-to-svg-code-2fdo</link>
      <guid>https://dev.to/ant_f_dev/convert-simple-icon-designs-from-paper-sketches-to-svg-code-2fdo</guid>
      <description>&lt;p&gt;When building an app, we sometimes find ourselves needing an icon but don’t have one at hand. Perhaps it’s for a ‘back’ or ‘home’ button. Or maybe we need a star for a ‘favourite’ button. One option is to find one we need in any of the numerous available online resources, e.g. &lt;a href="https://fontawesome.com/"&gt;Font Awesome&lt;/a&gt; or &lt;a href="https://thenounproject.com/"&gt;Noun Project&lt;/a&gt;. Another is to handcraft your own.&lt;/p&gt;

&lt;p&gt;In this article, we’ll look at how you can impart your design skills not only in crafting your code, but also in your app’s icons too. Taking the example of a simple icon, we’ll go from sketching it on paper, all the way to creating an SVG of it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sketching the Icon
&lt;/h2&gt;

&lt;p&gt;First off, we need some grid-lined or dotted paper to work on. If you don’t have any, there are many websites you can download graph paper from to print.&lt;/p&gt;

&lt;p&gt;In this example, we’ll create an arrow pointing leftwards. You can see our design in Image 1. The gridlines are faint but note that all corners of the arrow occur at where they cross. This is important because it will make the translation to SVG much easier.&lt;/p&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%2Fv647tsed29s5d45w4gsd.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%2Fv647tsed29s5d45w4gsd.png" alt="An outline of an arrow pointing leftwards overlaid on a grid" width="503" height="354"&gt;&lt;/a&gt;&lt;/p&gt;

Image 1: The initial icon design




&lt;h2&gt;
  
  
  Transferring to SVG
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Adding Boilerplate Code
&lt;/h3&gt;

&lt;p&gt;Now we have our design, we can transcribe it as an SVG. The first step is to find the co-ordinates of each corner of the shape in our image. The origin point, i.e. (0,0) in an SVG is at its top-left corner. In image 2, we’ve added some numbers along the axes of our icon design to help.&lt;/p&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%2Fxjbgvxrytq0kzpzdvs05.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%2Fxjbgvxrytq0kzpzdvs05.png" alt="An outline of an arrow pointing leftwards overlaid on a grid with co-ordinates marked" width="532" height="383"&gt;&lt;/a&gt;&lt;/p&gt;

Image 2: Our icon design with co-ordinates marked




&lt;p&gt;The following code is for a simple Web page; the part we’ll focus on is the &lt;code&gt;svg&lt;/code&gt; tag and its contents.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!doctype html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en-US"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;SVG Demo&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;svg&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"100"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"100"&lt;/span&gt; &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2000/svg"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;path&lt;/span&gt; &lt;span class="na"&gt;d=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt; &lt;span class="na"&gt;stroke=&lt;/span&gt;&lt;span class="s"&gt;"#000"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/path&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/svg&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Breaking it down, our SVG:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Has a width of &lt;code&gt;100&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Has a height of &lt;code&gt;100&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Declares itself and its contents to be in the SVG namespace &lt;code&gt;http://www.w3.org/2000/svg&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It contains a &lt;code&gt;path&lt;/code&gt; tag, which has two attributes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;stroke&lt;/code&gt; defines the outline colour; this is currently &lt;code&gt;#000&lt;/code&gt; (black).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;d&lt;/code&gt; defines the outline to be drawn. We’ll add data for our arrow icon here.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Transcribing the icon
&lt;/h3&gt;

&lt;p&gt;Let’s think about how we drew the icon on paper. The process will be difficult to follow when described with words, but the steps are also visualised in Image 3.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;We first moved our hand (with the pen off the page) to a point on the page.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We then put the pen tip to the page and drew a diagonal line, moving upwards and rightwards.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Without lifting the pen, we then drew a vertical line downwards.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Then a horizontal line rightwards.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Then a vertical line downwards.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Then a horizontal line leftwards.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Then a vertical line downwards.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;And finally, we finished the shape by closing our outline.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&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%2Flk9mjz1b2dppjg8ma6gl.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%2Flk9mjz1b2dppjg8ma6gl.png" alt="An outline of an arrow pointing leftwards overlaid on a grid with key points marked" width="532" height="384"&gt;&lt;/a&gt;&lt;/p&gt;

Image 3: The stages involved in drawing the icon




&lt;p&gt;We can transcribe these steps using SVG path syntax and our grid co-ordinates.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;M&lt;/strong&gt;ove without drawing to (0,5).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;From there, draw a &lt;strong&gt;L&lt;/strong&gt;ine to (7,0).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Draw a &lt;strong&gt;L&lt;/strong&gt;ine to (7,3).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Draw a &lt;strong&gt;L&lt;/strong&gt;ine to (15,3).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Draw a &lt;strong&gt;L&lt;/strong&gt;ine to (15,7).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Draw a &lt;strong&gt;L&lt;/strong&gt;ine to (7,7).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Draw a &lt;strong&gt;L&lt;/strong&gt;ine to (7,10).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The command for closing an open shape in SVG is &lt;strong&gt;Z&lt;/strong&gt;. To help with remembering this, think of the last command in drawing our shape corresponding with the last letter of the alphabet.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Putting this together, we have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;M0,5 L7,0 L7,3 L15,3 L15,7 L7,7 L7,10 Z
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s enter this as our path data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;path&lt;/span&gt; &lt;span class="na"&gt;d=&lt;/span&gt;&lt;span class="s"&gt;"M0,5 L7,0 L7,3 L15,3 L15,7 L7,7 L7,10 Z"&lt;/span&gt; &lt;span class="na"&gt;stroke=&lt;/span&gt;&lt;span class="s"&gt;"#000"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/path&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Adjusting the Icon Colour and Scale
&lt;/h3&gt;

&lt;p&gt;When rendered in a browser, two things become apparent:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The arrow’s body is coloured black.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It’s rather small.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Luckily, these are easy to remedy. To change our arrow’s body colour, we only need specify its &lt;code&gt;fill&lt;/code&gt;. We’ll use &lt;code&gt;#ff0&lt;/code&gt; (yellow) in our example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;path&lt;/span&gt; &lt;span class="na"&gt;d=&lt;/span&gt;&lt;span class="s"&gt;"M0,5 L7,0 L7,3 L15,3 L15,7 L7,7 L7,10 Z"&lt;/span&gt; &lt;span class="na"&gt;stroke=&lt;/span&gt;&lt;span class="s"&gt;"#000"&lt;/span&gt; &lt;span class="na"&gt;fill=&lt;/span&gt;&lt;span class="s"&gt;"#ff0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/path&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To zoom into our icon, we can use the &lt;code&gt;viewBox&lt;/code&gt; attribute. This takes four arguments, all based on its content:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The leftmost co-ordinate.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The topmost co-ordinate.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The width of the content.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The height of the content.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These need to be based on the co-ordinates within the image, rather than the actual size it’s displayed at. Looking at our data points, we can see:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The leftmost point in our data is &lt;code&gt;0&lt;/code&gt;. To ensure it is shown, we want the left co-ordinate of the &lt;code&gt;viewBox&lt;/code&gt; to be &lt;code&gt;-1&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The topmost point is &lt;code&gt;0&lt;/code&gt;. For it to be seen, we’ll use &lt;code&gt;-1&lt;/code&gt; as the top co-ordinate for our &lt;code&gt;viewBox&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The rightmost point is &lt;code&gt;15&lt;/code&gt;. To include it, we’d want the rightmost co-ordinate to be &lt;code&gt;16&lt;/code&gt;. But because the &lt;code&gt;viewBox&lt;/code&gt; starts at &lt;code&gt;-1&lt;/code&gt; and we’re specifying total width, this becomes &lt;code&gt;17&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Our SVG has both a width and height of &lt;code&gt;100&lt;/code&gt;. To preserve the 1:1 aspect ratio, that of our &lt;code&gt;viewBox&lt;/code&gt; should also match: a width of &lt;code&gt;17&lt;/code&gt; means the height should also be &lt;code&gt;17&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Adding this to the markup will give us the following, which will produce results as shown in Image 4.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;svg&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"100"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"100"&lt;/span&gt; &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2000/svg"&lt;/span&gt;
     &lt;span class="na"&gt;viewBox=&lt;/span&gt;&lt;span class="s"&gt;"-1 -1 17 17"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;path&lt;/span&gt; &lt;span class="na"&gt;d=&lt;/span&gt;&lt;span class="s"&gt;"M0,5 L7,0 L7,3 L15,3 L15,7 L7,7 L7,10 Z"&lt;/span&gt; &lt;span class="na"&gt;stroke=&lt;/span&gt;&lt;span class="s"&gt;"#000"&lt;/span&gt; &lt;span class="na"&gt;fill=&lt;/span&gt;&lt;span class="s"&gt;"#ff0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/path&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/svg&amp;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%2Fyfq83p0vp2lagy82fuax.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%2Fyfq83p0vp2lagy82fuax.png" alt="An arrow pointing leftwards, with a black outline and coloured yellow" width="100" height="75"&gt;&lt;/a&gt;&lt;/p&gt;

Image 4: Our SVG icon rendered in a browser




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Raw SVG data can look complex. But the core data format is relatively simple, and transcribing an icon from a paper sketch can be a straightforward task.&lt;/p&gt;

&lt;p&gt;By designing an icon on graph paper, you have a way of referencing co-ordinates of key points within it. With those, you can mimic the way it was drawn by using a series of commands in SVG markup. In addition, you can specify colours for the icon’s outline and fill.&lt;/p&gt;

&lt;p&gt;Finally, you use the viewBox attribute to adjust both the icon’s position and scale to add the finishing touches.&lt;/p&gt;




&lt;p&gt;Thanks for reading!&lt;/p&gt;

&lt;p&gt;This article is from my &lt;a href="https://webdeveloperdiary.substack.com/?sd=pf"&gt;newsletter&lt;/a&gt;. If you found it useful, please consider subscribing. You’ll get more articles like this delivered straight to your inbox (once per week), plus bonus developer tips too!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>frontend</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Dynamically Change SVG Icon Colours for Mouseover Effects</title>
      <dc:creator>Anthony Fung</dc:creator>
      <pubDate>Wed, 21 Feb 2024 13:00:00 +0000</pubDate>
      <link>https://dev.to/ant_f_dev/dynamically-change-svg-icon-colours-for-mouseover-effects-29h</link>
      <guid>https://dev.to/ant_f_dev/dynamically-change-svg-icon-colours-for-mouseover-effects-29h</guid>
      <description>&lt;p&gt;When we use images in an app, we sometimes want to be able to change their colour dynamically to react to either some app settings or certain user actions.&lt;/p&gt;

&lt;p&gt;For example, let’s imagine we have some toolbar icons. We might have an app with switchable light and dark themes. To maintain good contrast in both modes, we want the icons to be one colour when using the light theme, and another with the dark.&lt;/p&gt;

&lt;p&gt;Alternatively, we might want to improve the UX by providing immediate feedback on screen elements that can be clicked on. To do this, we want buttons to change their icon colour when the mouse pointer moves over them.&lt;/p&gt;

&lt;p&gt;In this article, we’ll look at ways in which we can accomplish this when using SVG images.&lt;/p&gt;

&lt;h2&gt;
  
  
  SVG Images
&lt;/h2&gt;

&lt;p&gt;Let’s look at our first use case where we want icons to be coloured differently for light and dark themes. As we’ve &lt;a href="https://webdeveloperdiary.substack.com/p/svg-an-introduction-vs-bitmap-formats"&gt;previously&lt;/a&gt; seen, an SVG image is declared using markup. Like HTML, we can modify its properties using CSS if we can reference it. When rendered in a browser, we should see something like Image 1 with the following code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;svg&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"icon"&lt;/span&gt; &lt;span class="na"&gt;viewBox=&lt;/span&gt;&lt;span class="s"&gt;"0 0 15 25"&lt;/span&gt; &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2000/svg"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;path&lt;/span&gt; &lt;span class="na"&gt;d=&lt;/span&gt;&lt;span class="s"&gt;"M1,10 L11,10 L11,20 Z"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/path&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;path&lt;/span&gt; &lt;span class="na"&gt;d=&lt;/span&gt;&lt;span class="s"&gt;"M0,11 L0,21 L10,21 Z"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/path&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/svg&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.icon&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100px&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;100px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;cornflowerblue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;stroke&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;darkblue&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%2Fhi1g351bvgjv4cvsej2b.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%2Fhi1g351bvgjv4cvsej2b.png" alt="Two blue right-angle triangles arranged to form a square" width="58" height="58"&gt;&lt;/a&gt;&lt;/p&gt;

Image 1: A simple SVG image with styling properties declared for the root element




&lt;p&gt;You’ll notice that the SVG tag that defines the image has an &lt;code&gt;icon&lt;/code&gt; class. In the corresponding CSS, we’ve set the &lt;code&gt;fill&lt;/code&gt; (i.e. background) to be &lt;code&gt;cornflowerblue&lt;/code&gt;; and the &lt;code&gt;stroke&lt;/code&gt; (i.e. line colour) to be &lt;code&gt;darkblue&lt;/code&gt;. This applies to all child elements of the &lt;code&gt;svg&lt;/code&gt;, meaning both triangles are coloured/styled as such.&lt;/p&gt;

&lt;p&gt;If we wanted to be more precise, we could style each triangle individually, as we’ve done in Image 2.&lt;/p&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%2Fc1jiro9icq2gieqhkboh.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%2Fc1jiro9icq2gieqhkboh.png" alt="Two right-angle triangles, one blue and one green, arranged to form a square" width="58" height="58"&gt;&lt;/a&gt;&lt;/p&gt;

Image 2: An SVG image with styling properties declared for each triangle




&lt;p&gt;To do this, we’ve given each triangle a different class (&lt;code&gt;triangle1&lt;/code&gt; and &lt;code&gt;triangle2&lt;/code&gt;). In the CSS, we can then be more specific; we’ve coloured the first triangle green, and the second blue.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;svg&lt;/span&gt; &lt;span class="na"&gt;viewBox=&lt;/span&gt;&lt;span class="s"&gt;"0 0 15 25"&lt;/span&gt; &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2000/svg"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;path&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"triangle1"&lt;/span&gt; &lt;span class="na"&gt;d=&lt;/span&gt;&lt;span class="s"&gt;"M1,10 L11,10 L11,20 Z"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/path&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;path&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"triangle2"&lt;/span&gt; &lt;span class="na"&gt;d=&lt;/span&gt;&lt;span class="s"&gt;"M0,11 L0,21 L10,21 Z"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/path&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/svg&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;svg&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100px&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;100px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.triangle1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;lightgreen&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;stroke&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;darkgreen&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.triangle2&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;cornflowerblue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;stroke&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;darkblue&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;h2&gt;
  
  
  Hover States
&lt;/h2&gt;

&lt;p&gt;For our second use case, we’d like our icons to change colour when the mouse pointer moves over them to indicate that they can be clicked on. Luckily, we can use the CSS &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/:hover"&gt;:hover&lt;/a&gt; pseudo-class to help us – all we need do is declare the styles we want for each state.&lt;/p&gt;

&lt;p&gt;In the following code, our icon is blue in its natural state. When the mouse pointer moves over it, its colours change to green. Image 3 shows the result of running this code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;svg&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"icon"&lt;/span&gt; &lt;span class="na"&gt;viewBox=&lt;/span&gt;&lt;span class="s"&gt;"0 0 15 25"&lt;/span&gt; &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2000/svg"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;path&lt;/span&gt; &lt;span class="na"&gt;d=&lt;/span&gt;&lt;span class="s"&gt;"M1,10 L11,10 L11,20 Z"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/path&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;path&lt;/span&gt; &lt;span class="na"&gt;d=&lt;/span&gt;&lt;span class="s"&gt;"M0,11 L0,21 L10,21 Z"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/path&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/svg&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.icon&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100px&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;100px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;cornflowerblue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;stroke&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;darkblue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="err"&gt;&amp;amp;:hover&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
    &lt;span class="py"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;lightgreen&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;stroke&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;darkgreen&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;/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%2F5o5swj9abf5deod5rpcj.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%2F5o5swj9abf5deod5rpcj.png" alt="Two squares each formed from two triangles. One is blue and one green" width="158" height="82"&gt;&lt;/a&gt;&lt;/p&gt;

Image 3: The icon in its (a) normal state, and (b) when hovered over by the mouse pointer




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;When building a Web app, you might want to change the colours of its icons in real time – maybe for theming or UX purposes. This is easy with SVG icons.&lt;/p&gt;

&lt;p&gt;An SVG image is declared as markup. Like HTML, the properties of it (or its elements) can be specified using CSS. If your app uses separate stylesheets for different themes, the colours of icons in each theme can be specified directly in the stylesheet.&lt;/p&gt;

&lt;p&gt;Similarly, it’s possible to declare hover states. You can use this technique to change an icon’s colour when the mouse pointer moves over it (or its corresponding button). This can enhance an app’s UX by providing immediate feedback to a user to show the buttons that can be clicked on.&lt;/p&gt;




&lt;p&gt;Thanks for reading!&lt;/p&gt;

&lt;p&gt;This article is from my &lt;a href="https://webdeveloperdiary.substack.com/?sd=pf"&gt;newsletter&lt;/a&gt;. If you found it useful, please consider subscribing. You’ll get more articles like this delivered straight to your inbox (once per week), plus bonus developer tips too!&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>tutorial</category>
      <category>webdev</category>
    </item>
    <item>
      <title>An Overview of Scaling SVG vs. Bitmap (JPG, PNG) Images</title>
      <dc:creator>Anthony Fung</dc:creator>
      <pubDate>Wed, 14 Feb 2024 13:00:00 +0000</pubDate>
      <link>https://dev.to/ant_f_dev/an-overview-of-scaling-svg-vs-bitmap-jpg-png-images-1hjj</link>
      <guid>https://dev.to/ant_f_dev/an-overview-of-scaling-svg-vs-bitmap-jpg-png-images-1hjj</guid>
      <description>&lt;p&gt;Having looked at the basics of &lt;a href="https://webdeveloperdiary.substack.com/p/svg-an-introduction-vs-bitmap-formats" rel="noopener noreferrer"&gt;SVG&lt;/a&gt; and bitmap formats (like &lt;a href="https://webdeveloperdiary.substack.com/p/jpg-vs-png-pros-and-cons-when-building-apps" rel="noopener noreferrer"&gt;JPG and PNG&lt;/a&gt;), we now have a rough idea of their pros and cons. In this article, we’ll look at another important factor that sets these formats apart: scalability.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Things Pixel Perfect – Scaling Bitmaps
&lt;/h2&gt;

&lt;p&gt;A bitmap format represents an image as a series of pixel colour values. Each pixel is a separate entity, and we have independent control over its value. This works to our advantage in images where colours and textures blend smoothly. But when we want to scale an image (to make it either larger or smaller), the nature of being a grid of colour points has its disadvantages.&lt;/p&gt;

&lt;p&gt;To explain why, consider Image 1. When we look at it, we see a diagonal line going through the centre of a rectangle. But as a bitmap image, it’s nothing more than a series of colour values.&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%2F0lxwd8bmt7ds1kl01ycd.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%2F0lxwd8bmt7ds1kl01ycd.png" alt="A diagonal line with rounded line endings inside a rectangle"&gt;&lt;/a&gt;&lt;/p&gt;

Image 1: A diagonal line with rounded line endings inside a rectangle




&lt;p&gt;Let’s say we wanted to double its size. As a grid of colour values, we have no concept of there being a line. Instead, we work at the pixel level and duplicate each one horizontally and vertically. And if we wanted to zoom an image to four times its original size, we’d replicate each pixel four times. And so on: we’re effectively increasing the size of each pixel in the image without adding to or enhancing any of its details.&lt;/p&gt;

&lt;p&gt;After a certain point, this affects image quality. Image 2 shows the top right tip of the line at different zoom factors. Everything is smooth and sharp at 1x. The image starts to look blurry at 2x but isn’t too bad. At 4x the diagonal line starts to look like a series of steps, and this pixelation is even more apparent at 8x. (The pixel gridlines in the image are an overlay from &lt;a href="https://affinity.serif.com/en-gb/photo/" rel="noopener noreferrer"&gt;Affinity Photo&lt;/a&gt; – the image editor I used while zooming into the image.)&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%2F2gjmb87snpt2hdovudhr.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%2F2gjmb87snpt2hdovudhr.png" alt="The top right tip of the line from Image 1 shown at 1x, 2x, 4x, and 8x zoom levels as a bitmap"&gt;&lt;/a&gt;&lt;/p&gt;

Image 2: The top right tip of the line from Image 1 shown at 1x, 2x, 4x, and 8x zoom levels as a bitmap




&lt;p&gt;Pixelation is more noticeable with certain types of image content than others. But in general, it isn’t possible to scale a bitmap up too far without it become apparent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Plotting a Route – Scaling SVGs
&lt;/h2&gt;

&lt;p&gt;SVG images define their content as shapes on a co-ordinates grid. Instead of a series of unrelated colour values, Image 1 would be represented as a series of lines and curves. Scaling an SVG involves multiplying the co-ordinates of its content by the zoom factor. As shapes are mathematically defined, we’re able to recreate them at any scale without any loss in quality.&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%2Fo2ypocxn4gzxis9czynx.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%2Fo2ypocxn4gzxis9czynx.png" alt="The top right tip of the line from Image 1 zoomed in as an SVG"&gt;&lt;/a&gt;&lt;/p&gt;

Image 3: The top right tip of the line from Image 1 zoomed in as an SVG




&lt;p&gt;Image 3 shows the same tip of the line from Image 1, zoomed in as an SVG. Despite a greater scale factor than the 8x level shown in Image 2, the line ending is still smooth and rounded.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;A bitmap format like JPG or PNG represents an image as separate colour values, whereas SVG defines its content as shapes. This affects how scalable an image is.&lt;/p&gt;

&lt;p&gt;When working at the pixel level, scaling an image up effectively means increasing the size of each pixel without being able to add more detail. At smaller zoom increases, this can cause an image to become blurry; at higher levels, pixelation becomes apparent and rounded edges become ‘stepped’.&lt;/p&gt;

&lt;p&gt;Scaling an SVG involves applying a zoom factor to its content. As shapes are defined mathematically, this process causes no loss in quality; rounded edges won’t suffer from pixelation, even at high magnification levels.&lt;/p&gt;




&lt;p&gt;Thanks for reading!&lt;/p&gt;

&lt;p&gt;This article is from my &lt;a href="https://webdeveloperdiary.substack.com/?sd=pf" rel="noopener noreferrer"&gt;newsletter&lt;/a&gt;. If you found it useful, please consider subscribing. You’ll get more articles like this delivered straight to your inbox (once per week), plus bonus developer tips too!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>frontend</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>SVG: An Introduction and Overview vs. Bitmap Formats</title>
      <dc:creator>Anthony Fung</dc:creator>
      <pubDate>Wed, 07 Feb 2024 13:00:00 +0000</pubDate>
      <link>https://dev.to/ant_f_dev/svg-an-introduction-and-overview-vs-bitmap-formats-4d6g</link>
      <guid>https://dev.to/ant_f_dev/svg-an-introduction-and-overview-vs-bitmap-formats-4d6g</guid>
      <description>&lt;p&gt;In last week’s &lt;a href="https://webdeveloperdiary.substack.com/p/jpg-vs-png-pros-and-cons-when-building-apps"&gt;article&lt;/a&gt;, we looked at and compared two common bitmap image formats – JPG and PNG. These formats represent an image as a fixed-sized grid.&lt;/p&gt;

&lt;p&gt;In this article, we’ll look at an alternative way of representing images where more emphasis is placed on the elements within it. In addition to introducing the data format, we’ll look at what it means in terms of storage requirements.&lt;/p&gt;

&lt;h2&gt;
  
  
  Making a Calculated Choice
&lt;/h2&gt;

&lt;p&gt;A bitmap describes an image at the pixel level. It specifies both the number of points within an image, and the colour of each one. However, the points aren’t related to one another apart from being in the same image. Image 1 shows a green circle on a blue background. Some pixels are blue, some are green. But there’s nothing to say that the green pixels form a circle.&lt;/p&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%2Floe8vwnm4rm36te29uca.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%2Floe8vwnm4rm36te29uca.png" alt="A green circle on a blue background" width="362" height="362"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;br&gt;
Image 1: A green circle on a blue background&lt;br&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  SVG Image Format
&lt;/h3&gt;

&lt;p&gt;Instead of treating an image as a series of colour values in a grid, the SVG format takes an entirely different approach by describing the shapes within it using a dedicated markup language. This makes it unsuitable for certain purposes (like photos) where elements blend smoothly into each other.&lt;/p&gt;

&lt;p&gt;Image 1 was created in &lt;a href="https://affinity.serif.com/en-gb/designer/"&gt;Affinity Designer&lt;/a&gt;. Once exported as an SVG, it – like any other SVG – can be opened in a text editor. The following is a snippet from the output.&lt;/p&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%2Fw1o5pb10nzcitle7pil7.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%2Fw1o5pb10nzcitle7pil7.png" alt="An SVG code snippet" width="800" height="378"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It may look complex, but it’s not too hard to see what’s going on if we take it bit by bit.&lt;/p&gt;

&lt;p&gt;First off, we have a &lt;code&gt;rect&lt;/code&gt;. This represents the blue square we’re using as a background. Looking at its attributes, we see it has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;X and Y co-ordinates (&lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; respectively).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Width and height sizes (&lt;code&gt;width&lt;/code&gt; and &lt;code&gt;height&lt;/code&gt; respectively).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A colour; more specifically, &lt;code&gt;rgb(38,72,184)&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Likewise, the circle also has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;X and Y co-ordinates (&lt;code&gt;cx&lt;/code&gt; and &lt;code&gt;cy&lt;/code&gt; respectively).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A size (&lt;code&gt;r&lt;/code&gt; represents its radius – the length between its midpoint and edge).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A colour: &lt;code&gt;rgb(77,209,94)&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Neither co-ordinate of the &lt;code&gt;rect&lt;/code&gt; is &lt;code&gt;0&lt;/code&gt;, and we might expect the image to be offset as a result. However, this isn’t the case because the image’s elements are all wrapped in a group (&lt;code&gt;g&lt;/code&gt;) with a matrix transform to reposition it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Storage Requirements
&lt;/h3&gt;

&lt;p&gt;SVG markup is semantically rich: each tag describes an element in its entirety. For example, the &lt;code&gt;circle&lt;/code&gt; tag defines a circle with its location and size specified by the tag’s attributes. This lets us express a lot of information with a relatively small amount of data, especially when compared to how a bitmap would represent the same image. For reference, Image 1 as an SVG takes 778 bytes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;The SVG format represents an image differently to how bitmap formats such as JPG and PNG would. An SVG describes its elements using a dedicated markup language, instead of presenting it as a series of colour values in a grid.&lt;/p&gt;

&lt;p&gt;This makes the format unsuitable for images where its elements blend seamlessly with one another. However, it means SVGs generally have a much smaller footprint than a bitmap equivalent.&lt;/p&gt;




&lt;p&gt;Thanks for reading!&lt;/p&gt;

&lt;p&gt;This article is from my &lt;a href="https://webdeveloperdiary.substack.com/?sd=pf"&gt;newsletter&lt;/a&gt;. If you found it useful, please consider subscribing. You’ll get more articles like this delivered straight to your inbox (once per week), plus bonus developer tips too!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>frontend</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>JPG vs PNG: Pros and Cons of Each Format When Building Apps</title>
      <dc:creator>Anthony Fung</dc:creator>
      <pubDate>Wed, 31 Jan 2024 13:00:00 +0000</pubDate>
      <link>https://dev.to/ant_f_dev/jpg-vs-png-pros-and-cons-of-each-format-when-building-apps-4a2a</link>
      <guid>https://dev.to/ant_f_dev/jpg-vs-png-pros-and-cons-of-each-format-when-building-apps-4a2a</guid>
      <description>&lt;p&gt;Images can play an important part when building an app. Whether it’s for desktop; mobile; or Web, there’s a chance you’ll need icons or backgrounds at some point.&lt;/p&gt;

&lt;p&gt;Three popular formats (in alphabetical order) are JPG, PNG, and SVG. In this article, we’ll look at and compare the pros and cons of the first two. As SVG is conceptually different, we’ll explore it in a later article.&lt;/p&gt;

&lt;h2&gt;
  
  
  Taking Things Bit by Bit
&lt;/h2&gt;

&lt;p&gt;An image in either JPG or PNG format is a bitmap. The specific process of encoding/decoding each format differs, but they work in the same way once decoded: an image is represented as a fixed-sized grid where each pixel (i.e. grid ‘slot’) is set to a specified colour. Table 1 summarises a few differences between the two formats and may help when deciding which to use.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;JPG&lt;/th&gt;
&lt;th&gt;PNG&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Compression&lt;/td&gt;
&lt;td&gt;Lossy&lt;/td&gt;
&lt;td&gt;Lossless&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;File size&lt;/td&gt;
&lt;td&gt;Smaller than PNG&lt;/td&gt;
&lt;td&gt;Larger than JPG&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Identical to pre-encoded version&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Supports transparency&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

Table 1: Comparison of .JPG and .PNG formats




&lt;h2&gt;
  
  
  Storage Requirements
&lt;/h2&gt;

&lt;h3&gt;
  
  
  JPG
&lt;/h3&gt;

&lt;p&gt;In general, storage requirements for a JPG file will be less than those for a PNG. However, this might not always be the case: it will depend on an image’s complexity, dimensions, and the specific encoder settings used.&lt;/p&gt;

&lt;p&gt;When creating a JPG, the encoder will analyse an image to find parts that can be discarded while having minimal impact on how it’s perceived. This data is then removed to help achieve smaller file sizes. The transformation is lossy: an encoded image won’t be identical to the original version. And depending on the compression level, this process could introduce noticeable artefacts.&lt;/p&gt;

&lt;p&gt;It’s also worth noting that repeatedly saving a JPG in a typical image editor will gradually degrade image quality as data is lost each time it’s (re)encoded. For this reason, it’s a good idea to only save an image as a JPG as a final step after any required edits have been made.&lt;/p&gt;

&lt;p&gt;While encoded images will contain less data than the original, it might not be noticeable with gentler encoder settings. And if data sizes are important (e.g. to minimise download times) JPG is certainly worth considering.&lt;/p&gt;

&lt;h3&gt;
  
  
  PNG
&lt;/h3&gt;

&lt;p&gt;While PNG images can also be compressed, the compression is lossless. An analogy would be using 7-Zip to create a compressed archive of a file. We can extract its contents at any time, and the result will be identical to the original. No data is lost in encoding.&lt;/p&gt;

&lt;p&gt;This makes PNG a good choice where we want the highest possible image quality, e.g. for charts and diagrams where clarity and/or legibility is important.&lt;/p&gt;

&lt;p&gt;The downside is that because all data is kept, a PNG encoded file can be larger than its JPG counterpart. To give an idea of the differences in file size, I took a screen capture of the image shown in Image 1 and saved it (separately) in both formats as a 521x782 image. The resultant file sizes are shown in Table 2.&lt;/p&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%2Fsihxfj65wilqavpcqw73.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%2Fsihxfj65wilqavpcqw73.png" alt="a winding road surrounded by trees in the mountains" width="521" height="782"&gt;&lt;/a&gt;&lt;/p&gt;

Image 1: Photo by alex geerts on Unsplash




&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;JPG&lt;/th&gt;
&lt;th&gt;PNG&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;File size (bytes)&lt;/td&gt;
&lt;td&gt;458,643&lt;/td&gt;
&lt;td&gt;628,062&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

Table 2: File sizes of the image shown in Image 1 when saved as a 521x782 image in JPG and PNG format




&lt;h2&gt;
  
  
  Image Transparency
&lt;/h2&gt;

&lt;p&gt;Depending on how we plan to use our images, we might need transparency (or alpha channel) support.&lt;/p&gt;

&lt;p&gt;This usually isn’t the case for photos; we typically don’t need to see ‘through’ them, though an exception might be if we wanted to lower an image’s opacity to act as a watermark or subtle overlay.&lt;/p&gt;

&lt;p&gt;But the argument is more persuasive for icons. Many modern UIs feature buttons and menus that become highlighted when a mouse (or other pointing device) hovers over them. In this context, an icon would stand out for the wrong reasons if the entire rectangular area within its image boundaries stayed the same colour while the rest of the control’s appearance changed to its highlighted state. In this scenario, we’d ideally like an image’s background to be transparent, instead of a solid colour. As we can see in Table 1, this is possible with PNG but not with JPG.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;JPG and PNG are two formats you might use for images when building an app. Depending on intended use, one might be more suitable than the other.&lt;/p&gt;

&lt;p&gt;JPG files are typically smaller and so allow for shorter loading times. Depending on the use case, this could make your app feel more responsive. However, this is achieved by removing data from the image. This potentially results in less clarity, or artefacts being added to an image at more extreme settings.&lt;/p&gt;

&lt;p&gt;PNG files preserve all image data and are a good choice when you need to prioritise image quality. While they can be larger than their JPG counterparts, the difference in file size may not be significant and will depend on an image’s complexity, its dimensions, and the settings used.&lt;/p&gt;

&lt;p&gt;When images are used as photos, you might prefer JPG for a smaller data footprint; this can lead to an app feeling more responsive due to shorter loading times. For charts; diagrams; and icons, PNG gives you the highest possible image quality. Furthermore, it supports transparency; this can give your app a more natural feeling when used on buttons and other UI controls.&lt;/p&gt;




&lt;p&gt;Thanks for reading!&lt;/p&gt;

&lt;p&gt;This article is from my &lt;a href="https://webdeveloperdiary.substack.com/?sd=pf"&gt;newsletter&lt;/a&gt;. If you found it useful, please consider subscribing. You’ll get more articles like this delivered straight to your inbox (once per week), plus bonus developer tips too!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>frontend</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Using Virtual Desktops to Stay Organised and Productive</title>
      <dc:creator>Anthony Fung</dc:creator>
      <pubDate>Wed, 24 Jan 2024 13:00:00 +0000</pubDate>
      <link>https://dev.to/ant_f_dev/using-virtual-desktops-to-stay-organised-and-productive-jdg</link>
      <guid>https://dev.to/ant_f_dev/using-virtual-desktops-to-stay-organised-and-productive-jdg</guid>
      <description>&lt;p&gt;It’s usual to have many apps open at once while writing software. As a back-end developer, you might have Visual Studio; &lt;a href="https://learn.microsoft.com/en-us/azure-data-studio/download-azure-data-studio" rel="noopener noreferrer"&gt;Azure Data Studio&lt;/a&gt;; and a browser open for documentation. When working front-end, you might have Visual Studio Code, &lt;a href="https://www.telerik.com/fiddler/fiddler-classic" rel="noopener noreferrer"&gt;Fiddler&lt;/a&gt;, and a browser to see the results of your work. And things can get even more complicated if you’re working both sides.&lt;/p&gt;

&lt;p&gt;It’s possible to switch between all open apps using the Taskbar. But leveraging virtual desktops to create a different workspace for each of your workflows could give your productivity a boost.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Workspace for Each of Your Workflows
&lt;/h2&gt;

&lt;p&gt;You’ll likely have encountered virtual desktops before if you’ve used Linux or macOS. However, it’s only been a native feature in Windows since Windows 10.&lt;/p&gt;

&lt;p&gt;Each virtual desktop gives you a separate workspace in which you can arrange your apps in any way you want – if you’re working full stack, you could dedicate one virtual desktop exclusively for back-end tools; and another for building a front-end Web client.&lt;/p&gt;

&lt;p&gt;While there’s nothing to stop you from having all your apps open on a single desktop, the ability to group related tools together gives you options to help stay focussed and organised.&lt;/p&gt;

&lt;h2&gt;
  
  
  Managing your Workspaces
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Creating and Navigating Virtual Desktops
&lt;/h3&gt;

&lt;p&gt;In Windows 11, you can create a new virtual desktop in one of two ways:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Using the keyboard shortcut &lt;code&gt;Ctrl&lt;/code&gt;+&lt;code&gt;Win&lt;/code&gt;+&lt;code&gt;D&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Via the Task View: press &lt;code&gt;Win&lt;/code&gt;+&lt;code&gt;Tab&lt;/code&gt; and select &lt;em&gt;New desktop&lt;/em&gt; – this option is highlighted in Image 1.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&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%2Facq3w1p62g62yssukcx8.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%2Facq3w1p62g62yssukcx8.png" alt="The Task View in Windows 11 with ‘New desktop’ highlighted"&gt;&lt;/a&gt;&lt;/p&gt;

Image 1: The Task View in Windows 11 with ‘New desktop’ highlighted




&lt;p&gt;When using option (1), you’ll automatically switch to using a newly created virtual desktop. With option (2), the new desktop will appear in the list at the bottom of the screen where and can select it.&lt;/p&gt;

&lt;p&gt;Regardless of how they’re created, you can move between your virtual desktops in one of two ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The keyboard shortcuts &lt;code&gt;Ctrl&lt;/code&gt;+&lt;code&gt;Win&lt;/code&gt;+&lt;code&gt;Left Arrow&lt;/code&gt; and &lt;code&gt;Ctrl&lt;/code&gt;+&lt;code&gt;Win&lt;/code&gt;+&lt;code&gt;Right Arrow&lt;/code&gt;. These move to the previous and next desktop respectively.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Clicking on the desktop you’d like to use in the Task View.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Moving Apps Between Virtual Desktops
&lt;/h3&gt;

&lt;p&gt;When working with multiple virtual desktops, opening an app launches an instance of it on the desktop that’s currently active. If you later decide it would be better suited on another, it’s easy to move. The Task View shows the apps open on the current desktop, and all available desktops along the bottom of the screen. From here, it’s possible to drag the app you want moved and drop it on the desktop you’d like it to go to. To illustrate this, image 2 shows moving the Calculator app from Desktop 1 to Desktop 2.&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%2Fbw4u9v3bx8stls6dripy.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%2Fbw4u9v3bx8stls6dripy.png" alt="Moving Calculator onto Desktop 2"&gt;&lt;/a&gt;&lt;/p&gt;

Image 2: Moving Calculator onto Desktop 2




&lt;p&gt;Things get a bit more complicated with apps that are set up to be a single instance. For example, let’s say we have an instance of Microsoft Excel open on Desktop 1. If we move to Desktop 2 and try to launch Excel again, we’ll find we jump straight back to Desktop 1. This is because Excel is already open there; when not opening a different workbook, Excel’s behaviour is to maintain a single instance. In this case, we can work around it by opening another workbook. This will launch a new Excel instance, which we can then move to Desktop 2.&lt;/p&gt;

&lt;h3&gt;
  
  
  Closing Virtual Desktops
&lt;/h3&gt;

&lt;p&gt;If you no longer need a virtual desktop, you can easily close it by either:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Pressing the keyboard shortcut &lt;code&gt;Ctrl&lt;/code&gt;+&lt;code&gt;Win&lt;/code&gt;+&lt;code&gt;F4&lt;/code&gt;. This will close the active desktop.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Clicking on the close button located in the top right corner on the respective desktop in the Task View (Image 3).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&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%2Fh3diymf3ie44957obiee.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%2Fh3diymf3ie44957obiee.png" alt="The Task View with the button to close Desktop 2 highlighted"&gt;&lt;/a&gt;&lt;/p&gt;

Image 3: The Task View with the button to close Desktop 2 highlighted




&lt;p&gt;Closing a desktop doesn’t close the apps on it. Any that are open will be moved (and will appear) on the desktop to the left of it; for example, apps on Desktop 2 will be moved to Desktop 1 when Desktop 2 is closed. You’ll need to manually close any apps you no longer need.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;It’s easy to lose track of things when working with many apps. Virtual desktops is a powerful feature in Windows 11 that can help group related tools together.&lt;/p&gt;

&lt;p&gt;Each virtual desktop acts as a separate workspace where you can arrange your apps as required. The Task View allows you to manage your currently open apps and desktops. Here, you can create new virtual desktops, move apps around, and close any that are no longer needed. If you prefer, there are keyboard shortcuts for navigation too.&lt;/p&gt;

&lt;p&gt;With this, you can create themed workspaces where you only have the tools you need open. And if you need to temporarily change focus, you’ll be able to quickly switch to another toolset with minimal disruption to your workflow.&lt;/p&gt;




&lt;p&gt;Thanks for reading!&lt;/p&gt;

&lt;p&gt;This article is from my &lt;a href="https://webdeveloperdiary.substack.com/?sd=pf" rel="noopener noreferrer"&gt;newsletter&lt;/a&gt;. If you found it useful, please consider subscribing. You’ll get more articles like this delivered straight to your inbox (once per week), plus bonus developer tips too!&lt;/p&gt;

</description>
      <category>programming</category>
      <category>productivity</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Static Helper Class vs. Injected Service: Pros and Cons</title>
      <dc:creator>Anthony Fung</dc:creator>
      <pubDate>Wed, 17 Jan 2024 13:00:00 +0000</pubDate>
      <link>https://dev.to/ant_f_dev/static-helper-class-vs-injected-service-pros-and-cons-29ha</link>
      <guid>https://dev.to/ant_f_dev/static-helper-class-vs-injected-service-pros-and-cons-29ha</guid>
      <description>&lt;p&gt;We’ve all worked on apps and services that weren’t as clearly written as they could have been. While we try our best, the combination of complexity and time constraints can result in code that needs a bit of time to get into before making modifications.&lt;/p&gt;

&lt;p&gt;One way of reducing complexity – even if only to save ourselves a bit of head scratching when returning to our own work a few days later – is to follow the Single Responsibility Principle. If we find we later need to redefine the meaning of 'single', or if code was written without the SRP in mind, it’s still possible to apply it; we identify multiple responsibilities within an entity (this could be a module, class, or method), and refactor them into their own units. When doing this, we have two choices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Move logic into a new class we can instantiate (and inject as a service).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Extract it into a static 'helper' class.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While these approaches may appear similar, there are differences that may make one choice a better (or worse) fit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Going Head-to-Head
&lt;/h2&gt;

&lt;p&gt;Before diving in, let’s first refresh our memories on the concept of a pure function. This style of method doesn’t use or modify state variables. Its outputs are entirely dependent on its inputs, and providing the same set of arguments will always lead to the same result.&lt;/p&gt;

&lt;p&gt;Another way of looking at it is that we should be able to replace a pure function with a value-lookup table and have everything continue to work.&lt;/p&gt;

&lt;h3&gt;
  
  
  Testability of Extracted Functions
&lt;/h3&gt;

&lt;p&gt;In terms of testing the extracted logic in isolation, there typically isn’t much difference between static and instantiable classes. In both cases, we’d need to setup our tests in similar ways. With pure functions, the main difference would be how we invoke the methods to be tested, i.e. whether we need a class instance.&lt;/p&gt;

&lt;p&gt;The exception to this would be where state is involved. In this case, we’d need to remember to reset our classes between tests, and also be mindful about running them in &lt;a href="https://webdeveloperdiary.substack.com/p/parallelise-nunit-tests-to-be-more-productive"&gt;parallel&lt;/a&gt;. This is easier with instantiable classes because we can create a new instance per test – something that isn’t possible with a static class.&lt;/p&gt;

&lt;h3&gt;
  
  
  Coupling and Testability of Calling Classes
&lt;/h3&gt;

&lt;p&gt;The main advantage of a static class lies in its simplicity. Once created, its (public) methods immediately become available for use anywhere within a codebase. There’s no need to consider creating additional interfaces, no need to tweak IoC framework modules, and no need to modify the constructor parameters of any classes. For this reason, a static class can be a good choice for self-contained helper methods that form part of an importable class library, possibly via NuGet.&lt;/p&gt;

&lt;p&gt;However, this simplicity is also a double-edged sword. A static class will help separate code in source form, and it’ll help in following the DRY principle. But it doesn’t reduce coupling between responsibilities.&lt;/p&gt;

&lt;p&gt;Whether this is a problem depends on the context. A good example of where using a static class makes sense is &lt;code&gt;System.Math&lt;/code&gt;. The functions it contains return values that are widely accepted to be correct. There’s no need to set them up with input/output value pairs and returning anything other than what they do typically isn’t useful, not even for testing purposes.&lt;/p&gt;

&lt;p&gt;Another example where this might not be a problem is a library that converts between different colour formats/models. After all, mocking a service to transform red &lt;code&gt;rgb(255, 0, 0)&lt;/code&gt; into the hex code for blue &lt;code&gt;#00f&lt;/code&gt; probably isn’t useful.&lt;/p&gt;

&lt;p&gt;Let’s contrast this with logic for calculating a password hash for example. While this too should produce consistent results, there is value in mocking its outputs in tests. Imagine writing a test that verifies a method:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Takes a password string.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Hashes the password into a long hash value.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Compares it against a known value in the test assertion.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If a real hashing algorithm is used in step (2), it could unnecessarily increase the time it takes for the test to run. More importantly, it reduces its focus. Instead of only checking that the process is followed, we’d also be incorporating knowledge about the output hash. (While testing the password transformation is important, it can – and should – be done in a separate test.) Lastly, if we ever changed the hashing algorithm, we’d need to update this test.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;When refactoring code into separate classes, you can often choose between creating new static or instantiable classes. The best choice often depends on context.&lt;/p&gt;

&lt;p&gt;When you create a static class, you’ll build a solution that’s easy to use and requires minimal changes (if any) to integrate. These are often a good choice for standalone logic where functions have widely accepted expectations or conversion results.&lt;/p&gt;

&lt;p&gt;By creating an instantiable class, you’ll allow for more flexibility by decoupling separate concepts. While needing a bit more effort to incorporate, you’ll find it can be easier to write tests for and run in parallel. As a bonus, you might be able to avoid modifying your tests if you ever need to change your implementations.&lt;/p&gt;




&lt;p&gt;Thanks for reading!&lt;/p&gt;

&lt;p&gt;This article is from my &lt;a href="https://webdeveloperdiary.substack.com/?sd=pf"&gt;newsletter&lt;/a&gt;. If you found it useful, please consider subscribing. You’ll get more articles like this delivered straight to your inbox (once per week), plus bonus developer tips too!&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>How Programming to an Interface Affects Testability</title>
      <dc:creator>Anthony Fung</dc:creator>
      <pubDate>Wed, 20 Dec 2023 16:46:36 +0000</pubDate>
      <link>https://dev.to/ant_f_dev/how-programming-to-an-interface-affects-testability-1c86</link>
      <guid>https://dev.to/ant_f_dev/how-programming-to-an-interface-affects-testability-1c86</guid>
      <description>&lt;p&gt;We’ve previously explored how a slight change in mindset can make our code more flexible. Thinking in terms of &lt;em&gt;what&lt;/em&gt; we’re doing rather than &lt;em&gt;how&lt;/em&gt; can help us to architect our software to be more modular. We benefit from this by producing code that’s potentially less brittle in the face of requirements changes; reusable; and adaptable for various environments. This week, we’ll look at the implications of programming to an interface when it comes to testing.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem with Holding All Responsibilities
&lt;/h2&gt;

&lt;p&gt;It’s worth noting that not all forms of testing are affected. The main advantage of having a modular design lies in the ability to swap a component’s dependencies freely and easily for others. However, some tests focus on the bigger picture. End-to-end and manual tests typically verify the workflows of a finished product. And as such, the way that it’s put together is irrelevant for these types of tests; they are only concerned with how the product behaves as a whole.&lt;/p&gt;

&lt;p&gt;However, writing unit and small integration tests becomes much easier. When attempting this for code that wasn’t written with testing in mind, we sometimes encounter two characteristics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Dependencies are presented as concrete class types.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A class contains multiple tightly coupled responsibilities.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This in turn presents three challenges:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Tests become more complex to set up: we need to create and configure real instances of objects that are merely dependencies of the actual test subject.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We need to design our tests more carefully: we must factor in the additional processing these dependencies will perform, which may not be directly related to (but also cannot be isolated from) the code we want to test.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The code can become impractical to test.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To further explain point (3), let’s consider an example. Imagine we have a method that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Accepts data via a parameter.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Converts it from one type to another.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Writes it to a database.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We’d like to test the conversion logic, and we could theoretically provide a database to write to. But we’d prefer not to have to persist the results of a unit test, especially as doing so is outside the scope of what we’re testing. And it’d slow down something we’d run both repeatedly and regularly.&lt;/p&gt;

&lt;p&gt;Alternatively, consider a method for logging errors, which:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Takes a message as a parameter.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Adds a timestamp.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Writes it to storage.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While the code itself is relatively straightforward, it becomes difficult to test if the timestamp is obtained by calling &lt;code&gt;DateTime.UtcNow&lt;/code&gt; directly. By doing this, we’d need to know the exact time every time the test was run to determine whether the logged message is correct.&lt;/p&gt;

&lt;h2&gt;
  
  
  Modularity to the Rescue
&lt;/h2&gt;

&lt;p&gt;Both examples of how code can become impractical to test suffer from the same problem: it’s trying to do too many things.&lt;/p&gt;

&lt;p&gt;In the first example, logic for writing to a database is coupled with that for mapping data types. It’s important that we have both for the system to work correctly, but we can separate the two concerns. By introducing an interface for a data repository, we can say we want to store data. But we don’t say how, nor do we need to at this level. It also means we can bypass writing to a database in our unit tests. Instead, we can provide an implementation that stores data passed to it in a variable, which can be used later if necessary.&lt;/p&gt;

&lt;p&gt;Again, we can break apart the two distinct responsibilities in our second example. By &lt;a href="https://webdeveloperdiary.substack.com/p/how-to-unit-test-services-with-date-time-logic"&gt;introducing an interface representing a timing service&lt;/a&gt;, we can say we want the current time and date without specifying how we obtain it. In unit tests, we can use an implementation (whether in the form of a &lt;a href="https://webdeveloperdiary.substack.com/p/alternatives-in-unit-tests-instead-of-mocks"&gt;mock, stub, or fake&lt;/a&gt;) that returns a constant time value. This gives us the power to manipulate time – at least as far as the logging service is concerned.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Writing tests is difficult when multiple responsibilities are tightly coupled within the same body of code. Programming to an interface can help separate them.&lt;/p&gt;

&lt;p&gt;Without doing so, tests could be unnecessarily cumbersome to set up due to their subjects needing concrete implementations of their dependencies. Furthermore, they may need more careful design to cater for the additional moving parts. This can lead to code that’s impractical to test.&lt;/p&gt;

&lt;p&gt;However, you can prevent this from happening by identifying boundaries between conceptually separate systems within your code. By introducing interfaces at these points, you loosen the coupling between them. In doing so, your code becomes cleaner and more modular. Its subsystems can be swapped for simpler and more predictable substitutes while testing. Ultimately, you’ll produce code that’s easier to both test and maintain.&lt;/p&gt;




&lt;p&gt;Thanks for reading!&lt;/p&gt;

&lt;p&gt;This article is from my &lt;a href="https://webdeveloperdiary.substack.com/?sd=pf"&gt;newsletter&lt;/a&gt;. If you found it useful, please consider subscribing. You’ll get more articles like this delivered straight to your inbox (once per week), plus bonus developer tips too!&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
    </item>
  </channel>
</rss>
