Skip to main content

Command Palette

Search for a command to run...

Adding Shiba Inu Loading and Error SVGs to My React Site

Updated
7 min read
Adding Shiba Inu Loading and Error SVGs to My React Site
A
Abbey Perini is many things - a metro Atlanta native, person of many hobbies, full-stack web developer, accessibility advocate, international speaker, and technical writer with ✨over 500,000 views.✨ She's full-stack in the truest sense - give her a problem and she'll figure it out. She's happiest problem solving in the front-end, back-end, and all the APIs and microservices in between. Passionate about accessibility, she's worked in Vue, React, and even AngularJS (2013). She's spent her development career rectifying tech debt in existing codebases.

When I updated the blog section of my portfolio site, I realized I had a great opportunity to draw some cute SVGs and take my loading and error messages to the next level.

When I started, the loading text looked like this:

A screenshot of abbeyperini.dev, with a nav bar on a light blue background, the blog button is highlighted by a border, and text on a peach background saying "Blogs loading!"

and the error text looked like this:

A screenshot of abbeyperini.dev, with an example project on a light blue background, with dark text on a blue grey background saying "There was an error! Try again later." Below, larger white text says "About Abbey", the about section starts on a light blue background, with a picture of Abbey in a red sweater. A bio and logos for programming languages and technologies follow

I spent a handful of hours making my loading graphic:

a chibi shiba inu smiling and sticking its tongue out with a yellow construction hat

and my error graphic:

a confused-looking chibi shiba inu with a question over its head

and I'm ready to add them to my site!

For more information on how I made these Shiba Inu graphics, and how to find or make images of your own, check out my post, Sourcing Images and Optimizing Them for the Web.

Putting the SVGs in my React App

My complicated Shiba SVGs are a little big (30 - 35 KB), but I'm choosing an .svg format over a .png format for a few reasons:

  1. I just removed hundreds of KBs of photos from my app by rewriting my blog to pull from the DEV API
  2. the PNG compression only takes them down to 21KB
  3. ease of resizing
  4. animation

I start by making two new components - Error.js and Loading.js. My initial Error component looks like this:

import React from 'react';

function Error() {
  return (
    <div>  
      <p>There was an error! Try again later.</p>
    </div>
  )
}

export default Error

There are a few ways I can import my SVGs into my components. If I were using CDN or another image hosting tool, I could use an <img> with a src link like this:

<img src="https://someSvgLink.com/svgID" alt="very descriptive alt text" />

Or I could use an <img> with the SVG saved and imported like a JPEG or PNG:

import React from 'react';
import ConfusedShiba from '../images/confused-shiba-inu.svg'

function Error() {
  return (
    <div>
      <img src={ConfusedShiba} alt="Confused Shiba Inu"></img> 
      <p>There was an error! Try again later.</p>
    </div>
  )
}

export default Error

Neither of these would let me animate or change my SVGs programmatically. Pasting the code directly into the React component would allow me to do that, but the complexity of my Shiba SVG makes for very long code. Here's an example of a React wrapper for a very simple SVG from my site. The code is for the turning arrow in the 'view my work' button on my landing page and that <line> was my first SVG code!

function Error() {
  return (
    <div>
      <svg role="img" aria-labelledby="arrowTitle arrowDesc" fill='none' stroke='#0E1A27' stroke-width='8' stroke-dashoffset='0' stroke-dasharray='0' stroke-linecap='round' stroke-linejoin='round' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'>
    <title id="arrowTitle">Arrow</title>
    <desc id="arrowDesc">arrow that spins on hover</desc>
    <line x1="70" y1="50" x2="0" y2="50" />
    <polyline fill="none" points="30,10 80,50 30,90 "/>
    </svg>
      <p>There was an error! Try again later.</p>
    </div>
  )
}

Ultimately, I choose to take advantage of create-react-app's option to import an SVG as a component. Translating SVGs to the DOM this way is expensive, but in this case, I have less than 10 SVGs on my site imported this way, and they're all in use. For a larger site, I would look into packages like SVGR, using the Webpack Asset Modules or an icon library like Font Awesome. My Error component now looks like this:

import React from 'react';
import {ReactComponent as ConfusedShiba} from '../images/confused-shiba-inu.svg'

function Error() {
  return (
    <div>
      <ConfusedShiba />
      <p>There was an error! Try again later.</p>
    </div>
  )
}

export default Error

And I import both my Error component and my very similar Loading component into my Blog component like this:

import Error from '../components/Error';
import Loading from '../components/Loading';
  } else if (!state.isLoading && state.error) {
    return (
      <Error />
    )
  } else {
    return (
      <Loading />
    )
  }
}

Now my Shibas are in my site but because there's no styling, they're HUGE and still on the wrong background. Time to add some CSS. First, I know I'll want some padding and a max-width rule for my Shibas.

/* error and loading graphics */

.error-graphic {
  padding: 20px 20px 0px 20px;
  max-width: 200px;
}

.loading-graphic {
  padding: 20px 20px 0px 20px;
  max-width: 200px;
}

200px is looking nice on my laptop screen, so that's probably about the largest I'll want to go. That means that I need to add in media queries and change the width in this rule to the smallest I'll go, as I used mobile-first design to make my site responsive down to 280px.

.error-graphic {
  padding: 20px 20px 0px 20px;
  max-width: 100px;
}

.loading-graphic {
  padding: 20px 20px 0px 20px;
  max-width: 100px;
}

@media screen and (min-width: 350px) {
  .error-graphic, .loading-graphic {
    max-width: 150px;
  }
}

@media screen and (min-width: 525px) {
  .error-graphic, .loading-graphic {
    max-width: 200px;
  }
}

Next, I add container styling to match the rest of my site, and the result looks like this:

a chibi shiba inu smiling and sticking its tongue out with a yellow construction hat in a light blue box with "Blogs loading!" on a darker background

But that's not all! I noticed that my error Shiba's question mark doesn't meet minimum contrast standards on my container background. Because this image doesn't add information to the page, it's not super important that it does, but I could animate it to cycle through many colors, at least one of which should meet standards. Plus, using CSS variables to change the color of my SVGs was one of my favorite parts of my Toggle Dark Mode In React post.

To do this, I'm going to have to edit my SVG code directly. First, using right click > inspect in my Chrome browser, I find the <path>s and the <circle> I want to animate. Then, I add "questionMark", "questionMarkFill", and "questionMarkDot" id properties to them, so I can always find them. Next, I remove the <style> Illustrator created in my SVG with my colors and rewrite them into CSS rules. Both this SVG and my other Shiba Inu have the same Illustrator-named classes like "cls-1", so I also rename the classes. After a fair amount of Googling variations of "SVG CSS color rotate" and settling upon using @keyframes and hsla(), I found Dan Wilson's expert color math. Using that, I write two CSS animations to cycle through colors gradually:

@keyframes colorRotate-fill {
  0%, 100% {
    fill: hsl(0,100%,50%);
  }
  10% {
    fill: hsl(36,100%,50%);
  }
  20% {
    fill: hsl(72,100%,50%);
  }
  30% {
    fill: hsl(108,100%,50%);
  }
  40% {
    fill: hsl(144,100%,50%);
  }
  50% {
    fill: hsl(180,100%,50%);
  }
  60% {
    fill: hsl(216,100%,50%);
  }
  70% {
    fill: hsl(252,100%,50%);
  }
  80% {
    fill: hsl(288,100%,50%);
  }
  90% {
    fill: hsl(324,100%,50%);
  }
}

@keyframes colorRotate-fill-hsla {
  0%, 100% {
    fill: hsla(0,100%,50%,.2);
  }
  10% {
    fill: hsla(36,100%,50%,.2);
  }
  20% {
    fill: hsla(72,100%,50%,.2);
  }
  30% {
    fill: hsla(108,100%,50%,.2);
  }
  40% {
    fill: hsla(144,100%,50%,.2);
  }
  50% {
    fill: hsla(180,100%,50%,.2);
  }
  60% {
    fill: hsla(216,100%,50%,.2);
  }
  70% {
    fill: hsla(252,100%,50%,.2);
  }
  80% {
    fill: hsla(288,100%,50%,.2);
  }
  90% {
    fill: hsla(324,100%,50%,.2);
  }
}

The 'a' in 'hsla' represents transparency, where 0 is completely transparent and 1 is completely opaque. The way I made my SVG requires a third rule called colorRotate-stroke which looks exactly like colorRotate-fill, but with the property stroke instead of the property fill. Then I apply the rules to the appropriate new classes:

.error-graphic_qm_dot {
  fill:#a19ece;
  stroke:#524f77;
  stroke-miterlimit:10;
  stroke-width:3px;
  animation-name: colorRotate-stroke, colorRotate-fill-hsla;
  animation-duration: 3000ms;
  animation-fill-mode: forwards;
  transition: all 360ms ease-in;
  animation-iteration-count: infinite;
}

The result looks like this:

On a light blue background, a confused-looking chibi shiba inu with a question over its head - the question mark gradually cycles through many colors, the outline maintaining a darker color than the color in the middle. Below it reads "There was an error! Try again later."

A note on SVG accessibility

In doing research on SVGs, I found the recommended tags to include to make SVGs accessible. I've updated all the svgs on my site to have a <title>, <desc>, and the role="img" and aria-labelledby="titleID descID" properties in the <svg> tag.

While looking into animating SVGs, I saw color animation could trigger some accessibility issues, so I applied a rule I learned about in my demo of the updated blog portion of my site:

@media (prefers-reduced-motion) {
  .error-graphic_qm-fill, .error-graphic_qm-lines, .error-graphic_qm-lines {
    animation-name: dissolve;
  }
}

Conclusion

I really enjoyed making and styling these Shiba Inu SVGs. For an in depth breakdown of image types for the web and how to make or find your own for free, check out this article's sister blog, Sourcing Images and Optimizing Them for the Web. You can check these Shibes out live at https://abbeyperini.dev and see all the code for my site in the repo.

Images

Part 2 of 7

When I sat down to write about my Shiba Inu SVGs, out came a tutorial for SVGs in React, and an article demystifying sourcing images for your website. Additional image tutorials will be added here.

Up next

What is WebP?

I right click > save images off the web constantly, and I've started coming across .webp file types more and more. What is this Google-made open source image file format? WebP The stated goal for this file format is improving website speed, so WebP m...

More from this blog

A

Abbey Perini Codes

85 posts

Passionate about accessibility, Abbey's worked in Vue, React, and even AngularJS (2013). She's happiest problem solving in the front-end, back-end, and all the APIs and microservices in between.