Skip to content

Instantly share code, notes, and snippets.

@lunule
Created April 12, 2026 00:09
Show Gist options
  • Select an option

  • Save lunule/c0ac047824da2703898553b220dc8976 to your computer and use it in GitHub Desktop.

Select an option

Save lunule/c0ac047824da2703898553b220dc8976 to your computer and use it in GitHub Desktop.
[WordPress, SVG, and ACF - Get Original SVG Code by Image ID] #wp #acf #svg #images #performance
<?php
/**
* FYKI: ONLY USE THIS IF THERE ARE MAX 4-5 SVGs ON THE PAGE - even if caching is handled with
* transients, THERE'S ALWAYS A FIRST LOAD, and with 10-20-30-more SVGs on the same page
* file_get_contents kills your site's performance upon the first load, AND I MEAN IT!!!
* WE'RE TALKING ABOUT LOSING 4-5-10 SECONDS BECAUSE OF THIS SHIT!!!
*
* WHAT'S THE FIX THEN?
*
* NO FIX: if there are tons of svgs on one page, you MUST NOT USE SVGs AS IMAGES UPLOADED
* TO THE MEDIA LIBRARY or an ACF FIELD GROUP - INSTEAD, YOU SHOULD USE THE
* ORIGINAL SVG CODES. Use hardcoding or ACF code editor field - and if the
* client doesn't like the idea, explain to her that the only way she gets a more
* user-friendly SVG "embed" solution with the media library IS BY KILLING HER
* SITE PERFORMANCE!!!.
*/
function ctr26_get_inline_svg($attachment_id, $args = []) {
if (!$attachment_id) {
return '';
}
// Config
$defaults = [
'cache' => true,
'cache_time' => DAY_IN_SECONDS,
];
$args = wp_parse_args($args, $defaults);
$transient_key = 'inline_svg_' . $attachment_id;
// Try cache first
if ($args['cache']) {
$cached = get_transient($transient_key);
if ($cached !== false) {
return $cached;
}
}
// Get file path
$file_path = get_attached_file($attachment_id);
if (!$file_path || !file_exists($file_path)) {
return '';
}
// Only allow SVGs
if (pathinfo($file_path, PATHINFO_EXTENSION) !== 'svg') {
return '';
}
// Get raw SVG
$svg = file_get_contents($file_path);
if (!$svg) {
return '';
}
// Sanitize SVG
$allowed_tags = [
'svg' => [
'xmlns' => true,
'viewbox' => true,
'width' => true,
'height' => true,
'fill' => true,
'stroke' => true,
'class' => true,
'role' => true,
'aria-hidden' => true,
],
'g' => [
'fill' => true,
'stroke' => true,
'transform' => true,
],
'path' => [
'd' => true,
'fill' => true,
'stroke' => true,
],
'rect' => [
'width' => true,
'height' => true,
'x' => true,
'y' => true,
'fill' => true,
'stroke' => true,
],
'circle' => [
'cx' => true,
'cy' => true,
'r' => true,
'fill' => true,
'stroke' => true,
],
'line' => [
'x1' => true,
'y1' => true,
'x2' => true,
'y2' => true,
'stroke' => true,
],
'polygon' => [
'points' => true,
'fill' => true,
'stroke' => true,
],
'title' => [],
'defs' => [],
'clipPath' => ['id' => true],
];
$svg = wp_kses($svg, $allowed_tags);
// Cache it
if ($args['cache']) {
set_transient($transient_key, $svg, $args['cache_time']);
}
return $svg;
}
/**
* USAGE:
*
* DEFAULT:
* echo ctr26_get_inline_svg(get_field('logo'));
*
* NO CACHE:
* echo ctr26_get_inline_svg(get_field('logo'), ['cache' => false]);
*
* FLUSH CACHE:
* Right now, if you replace the SVG → cached version stays. Quick fix:
*
* add_action('edit_attachment', function($attachment_id) {
* delete_transient('inline_svg_' . $attachment_id);
* });
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment