Skip to content

Instantly share code, notes, and snippets.

@iAugur
Last active April 4, 2025 11:03
Show Gist options
  • Save iAugur/2060fed3090af8f5d338c6240202d349 to your computer and use it in GitHub Desktop.
Save iAugur/2060fed3090af8f5d338c6240202d349 to your computer and use it in GitHub Desktop.
Make SVGs Unique with random prefix for element ids

SVGs must have unique IDS

Background

If an SVG uses things like gradients, clip paths, masks, classes etc then these must have unique names/ids if they are show on a page with other similar SVG. As would be the case with HTML for example

This can be encountered when SVGs don't display correctly - especially ones using clippaths - when show on a page with other similar SVGs, but display OK when shown alone.

They will also fail accessibility checks (WCAG 2.1 (A), WCAG 2.0 (A)).

Script to prefix elements within SVGs in a folder

The script below will run against a folder of SVGs and prefix all such elements with a random string (per file) It outputs the prefixed svgs in the same folder with the suffix - yourfilename-prefixed.svg

Refs:

StackOverflow comment that pointed me in the right direction - https://stackoverflow.com/a/76001127/348868

Spec - https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Attribute/id

#!/bin/bash
#
# This file corrects SVG files that have non unique ids, classes etc
#
# svg-prefix-all.sh /path/to/folder
#
set -e # Exit immediately if a command exits with a non-zero status
# Check if a directory is provided as an argument
if [ -z "$1" ]; then
echo "Usage: $0 <directory>"
exit 1
fi
directory="$1"
# Check if the directory exists and is a directory
if [ ! -d "$directory" ]; then
echo "Error: Directory '$directory' not found or is not a directory."
exit 1
fi
# Sed script to prefix IDs and class names, and CSS class definitions. (Define once!)
sed_script=$(cat <<EOF
# Prefix id attributes
s/id="\(.*\)"/id="__PREFIX__-\1"/g
# Prefix class attributes
s/class="\(.*\)"/class="__PREFIX__-\1"/g
# Prefix fill="url(#\(.*\))"/ attributes
s/fill="url(#\(.*\))"/fill="url(#__PREFIX__-\1"/g
# Prefix xlink:href="#\(.*\)" attributes
s/xlink:href="#\(.*\)"/xlink:href="#__PREFIX__-\1"/g
# Prefix filter="url(#\(.*\))"/ attributes
s/filter="url(#\(.*\))"/filter="url(#__PREFIX__-\1"/g
# Prefix clip-path="url(#\(.*\))"/ attributes
s/clip-path="url(#\(.*\))"/clip-path="url(#__PREFIX__-\1"/g
# Prefix mask="url(#\(.*\))"/ attributes
s/mask="url(#\(.*\))"/mask="url(#__PREFIX__-\1"/g
# Prefix CSS class definitions (handles multiple classes in selector)
s/\.cls-\([0-9]*\)/.__PREFIX__-cls-\1/g
# Prefix URL references within CSS styles
s/url(#\([a-zA-Z0-9_-]*\))/url(#__PREFIX__-\1)/g
EOF
)
# Loop through all SVG files in the directory, excluding *prefixed.svg files
find "$directory" -name "*.svg" ! -name "*-prefixed.svg" -print0 | while IFS= read -r -d $'\0' input_file; do
# Generate a unique 3-character prefix for *this* file
prefix=$(openssl rand -base64 4 | tr -dc a-z0-9 | head -c 3)
# Derive the output file name
output_file="${input_file%.svg}-prefixed.svg"
# Create a temporary sed script with the prefix substituted
temp_sed_script=$(echo "$sed_script" | sed "s/__PREFIX__/$prefix/g")
# Apply the sed script to the input file and save to the output file
sed "$temp_sed_script" "$input_file" > "$output_file"
echo "Processed: $input_file -> $output_file (Prefix: $prefix)"
done
echo "Finished processing SVG files in $directory"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment