Skip to content

Instantly share code, notes, and snippets.

@milkshoes
Forked from sergiolopes/README.md
Created July 11, 2013 20:12
Show Gist options
  • Save milkshoes/5978802 to your computer and use it in GitHub Desktop.
Save milkshoes/5978802 to your computer and use it in GitHub Desktop.

SVG sprite generator, by Sérgio Lopes

Requirements

Usage

  • Create a folder full of individual SVG files you want to sprite
    • SVG file name will be used as HTML className
    • Image size will be the default one used on CSS and PNG fallbacks
    • Folder name is important, will be used on CSS too
  • Run: build-svg-sprite.sh <sprite_folder> <output_path>

Using on HTML:

  • Import the sprite.css file
  • If your folder name was home.sprite and there you have an icon named search.svg, your HTML should be this: <span class="home home-search">Fallback text</span>
  • You also need some JS to detect SVG and retina support. Something like this on your head should do the trick:
// Feature detect, Modernizr inspired
document.documentElement.className = 

// javascript
'js '
	
// SVG
+ (!!document.createElementNS && !!document.createElementNS('http://www.w3.org/2000/svg', "svg").createSVGRect ? 'svg ':'no-svg ')

// retina pixel ratio
+ 'ratio' + (!!(window.devicePixelRatio > 1.3) ? '2x ' : '1x ');

More

  • This is an experiment, with many possible improvements. Contributions are welcome.
  • You should optimize the generated PNG files too, using pngcrunch, pngout etc
#!/bin/bash
#
# High def sprite build.
# by Sérgio Lopes - http://sergiolopes.org/
#
# Params:
# $1 Sprite folder with SVGs
# $2 Output path
#
# See original gist: https://gist.github.com/sergiolopes/4739627
# Configuration: how many pixels between each image on the sprite?
SPACING=10
# Parsing command-line paramenters
SPRITE="$1"
SPRITE_NAME="$(basename "$SPRITE" | sed 's/\.[^\.]*$//g')"
OUTPATH="$(echo "$1" | sed 's/\.[^\.]*$//g')"
OUTDIR="$2/$OUTPATH"
# Helpers: simple functions
function round {
echo "($1+0.5)/1" | bc
}
function divisionByTen {
echo "scale=2; $1/100" | bc
}
# Prepare output directories
echo Outputing to $OUTDIR
rm -rf "$OUTDIR"
mkdir -p "$OUTDIR"
# Generate the SVG sprite.
# Uses svg_stack to create the sprite and scour to optimize the file.
# Creates two files: sprite.svg and sprite.svgz
python svg_stack.py --margin $SPACING --direction=v "$SPRITE"/*.svg > "$OUTDIR"/sprite.svg
python scour.py -i "$OUTDIR"/sprite.svg -o "$OUTDIR"/sprite-opt.svg
python scour.py -i "$OUTDIR"/sprite.svg -o "$OUTDIR"/sprite.svgz
mv "$OUTDIR"/sprite-opt.svg "$OUTDIR"/sprite.svg
# Get sprite final width and height, using ImageMagick
SPRITE_WIDTH=$(divisionByTen $(round $(identify -format '%w' "$OUTDIR"/sprite.svgz)))em
SPRITE_HEIGHT=$(divisionByTen $(round $(identify -format '%h' "$OUTDIR"/sprite.svgz)))em
# Generate base CSS for this sprite.
# Includes main className, sprite URL, size, and PNG fallbacks.
cat > "$OUTDIR"/sprite.css <<CSS
.${SPRITE_NAME} {
background-repeat: no-repeat;
-moz-background-size: ${SPRITE_WIDTH} ${SPRITE_HEIGHT}; /* Firefox 3.6 */
background-size: ${SPRITE_WIDTH} ${SPRITE_HEIGHT}; /* sprite_1x size */
display: inline-block;
position: relative;
font-size: 100px;
/* image replacement */
overflow: hidden;
text-indent: -999999px;
}
/* has SVG support */
.svg .${SPRITE_NAME} {
background-image: url(${OUTPATH}/sprite.svg);
}
/* no SVG but retina (and JS) */
.no-svg.ratio2x .${SPRITE_NAME} {
background-image: url(${OUTPATH}/sprite_2x.png);
}
/* (no-JS) or (no-SVG and no-retina) */
.no-js .${SPRITE_NAME},
.no-svg.ratio1x .${SPRITE_NAME} {
background-image: url(${OUTPATH}/sprite_1x.png);
}
/* individual icons */
CSS
sprite_size=0
# Iterate on all individual SVG files to generated each CSS class.
for svg_file in "$SPRITE"/*.svg; do
# Get this file width and height
svg_file_px_height=$(round $(identify -format '%h' "${svg_file}"))
svg_file_width=$(divisionByTen $(round $(identify -format '%w' "${svg_file}")))em
svg_file_height=$(divisionByTen $svg_file_px_height)em
# Get file name without .svg extension
svg_file_name="$(basename "$svg_file" | sed 's/\.[^\.]*$//g')"
# Output CSS class to this image.
# Configures background-position accordingly
cat >> "$OUTDIR"/sprite.css <<____CSS
.${SPRITE_NAME}-${svg_file_name} {
background-position: 0 -$(divisionByTen $sprite_size)em;
height: ${svg_file_height};
width: ${svg_file_width};
}
____CSS
sprite_size=$((sprite_size + svg_file_px_height + SPACING))
done
# Export PNG (@1x and @2x) versions using Inkscape
inkscape \
--export-png="$OUTDIR"/sprite_1x.png --export-area-page --export-dpi=90 \
--export-background-opacity=0 --without-gui "$OUTDIR"/sprite.svgz
inkscape \
--export-png="$OUTDIR"/sprite_2x.png --export-area-page --export-dpi=180 \
--export-background-opacity=0 --without-gui "$OUTDIR"/sprite.svgz
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment