megclaypool
11/6/2019 - 8:54 PM

Inline svg background image SCSS awesomeness :)

[Inline svg background image SCSS awesomeness :) ]

Okie dokie, this one's pretty simple to implement once you've got the backend set up, but has a few moving parts that need explaining.

Set up your "svg" scss files

Find an svg you'd like to use. (You can get all the Font Awesome svgs by downloading the Desktop version of Font Awesome 5 Pro). Open your svg in a text editor and you'll see something like:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M207.029 381.476L12.686 187.132c-9.373-9.373-9.373-24.569 0-33.941l22.667-22.667c9.357-9.357 24.522-9.375 33.901-.04L224 284.505l154.745-154.021c9.379-9.335 24.544-9.317 33.901.04l22.667 22.667c9.373 9.373 9.373 24.569 0 33.941L240.971 381.476c-9.373 9.372-24.569 9.372-33.942 0z"/></svg>

Create a new scss file. Declare a new scss variable, and set it equal to the contents of the svg file:

$svg-chevron-down--solid: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M207.029 381.476L12.686 187.132c-9.373-9.373-9.373-24.569 0-33.941l22.667-22.667c9.357-9.357 24.522-9.375 33.901-.04L224 284.505l154.745-154.021c9.379-9.335 24.544-9.317 33.901.04l22.667 22.667c9.373 9.373 9.373 24.569 0 33.941L240.971 381.476c-9.373 9.372-24.569 9.372-33.942 0z"/></svg>'

Font Awesome icons don't have a fill attribute, so you'll need to add that so you can control the color with scss. Here's part of the secret sauce: set the fill color equal to another scss variable, $svg-color. DON'T DECLARE THE VALUE OF $svg-color IN THIS FILE!
(If your svg already has a fill attribute, just adjust it so it uses the $svg-color variable).

$svg-chevron-down--solid: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="'+$svg-color+'" d="M207.029 381.476L12.686 187.132c-9.373-9.373-9.373-24.569 0-33.941l22.667-22.667c9.357-9.357 24.522-9.375 33.901-.04L224 284.505l154.745-154.021c9.379-9.335 24.544-9.317 33.901.04l22.667 22.667c9.373 9.373 9.373 24.569 0 33.941L240.971 381.476c-9.373 9.372-24.569 9.372-33.942 0z"/></svg>'

Disinclude some files from your gulp scss task

This trick absolutely depends on NOT including these svg scss files when you run your gulp scss task.

We've just set up a variable inside a scss file without declaring it inside that file. If the file gets processed by gulp as-is, gulp-sass will shit itself over the undeclared variable. Sooo, you have to make sure gulp doesn't process the file except under specific, carefully set up circumstances.

The key: sassGlob ignorePaths and careful file naming!

Either name your scss file beginning with _! or put it in a folder whose name begins with _!. Then use the ignorePaths setting in sassGlob in your gulpfile to ignore those files:

.pipe(sassGlob({
   ignorePaths: [
     // "**/_xx_*.scss",
     "**/_!*",
     "**/_!*/**",
   ]
 }))

My complete sass processing task looks like this:

/**
* Compile pattern library scss
*/
function css() {
 return (
   gulp
     .src(config.patternsBasePath + "/hip-styles.scss")
     .pipe(sassGlob({
       ignorePaths: [
         // "**/_xx_*.scss",
         "**/_!*",
         "**/_!*/**",
       ]
     }))
     //.pipe(sourcemaps.init())
     .pipe(
       sass({
         includePaths: [config.patternsBasePath],
         outputStyle: "compressed"
       }).on("error", sass.logError)
     )
     //.pipe(sourcemaps.write())
     .pipe(autoprefixer())
     .pipe(gulp.dest(config.distPath + "/css"))
     .pipe(gulp.dest(config.patternsDistPath + "/css"))
     .pipe(gulp.dest(config.plabPublicPath + "/css"))
     .pipe(browserSync.stream({ match: "**/*.css" }))
 );
}

Target your scss @import

We can use scope to our advantage here!

Open up one of the scss stylesheets that gulp does process. Inside a selector, declare the $svg-color variable to be whatever color you want to use for your svg. Now, rather than @importing your svg scss file into at the head of your stylesheet, @import it right after your $svg-color declaration. You've just defined an svg path (limited to this selector) whose fill color is the $svg-color you set for this element. You can reuse the same svg scss variable over again with another color in another spot :)

Using your new scss svg

Use your scss svg as the background image for any element :) Do take care with background-size, background-position, and background-repeat!
Also note that select fields need to use linear-gradients as their background to override stupid defaults. Other elements can just use a regular background-color

select {
  $svg-color: $color--light-orange; 
  @import '00-base/mixins/inline-svg/_!_svgs/_fontawesome-chevron-down--solid.scss';
  background-image: inline-svg($svg-chevron-down--solid), linear-gradient(to bottom, white 0%, white 100%);
  
  background-repeat: no-repeat, repeat;
  background-position: right .7em top 50%, 0 0;
  background-size: .65em auto, 100%;
  ...
}