Optimize SVG images

SVG images use XML-based markup to describe vector graphics. Optimize SVG markup using SVGO.

Face with waiting expression Nothing to see yet!

Loading takeymakey...
TakeyMakey code
Want this tool to do something else? Edit the code below and make it do whatever you want.
({
  take: [
    { type: "code", label: "Source SVG" },
    { type: "toggle", label: "Multipass" },
    { type: "toggle", label: "Pretty" },
    { type: "dropdown", label: "Indent", options: [2, 4] },
    {
      type: "dropdown",
      label: "Float precision",
      value: 1,
      options: [0, 1, 2, 3, 4, { label: "Ignore", value: 14 }],
    },
    {
      type: "dropdown",
      label: "Transform precision",
      value: 1,
      options: [0, 1, 2, 3, 4, { label: "Ignore", value: 14 }],
    },
    { type: "toggle", label: "Remove groups", value: true },
    { type: "toggle", label: "Merge paths", value: true },
    {
      type: "import",
      value: "https://cdn.jsdelivr.net/npm/svgo@3.2.0/dist/svgo.browser.js",
      module: true,
    },
  ],
  make: ([
    svg,
    multipass,
    pretty,
    indent,
    floatPrecision,
    transformPrecision,
    collapseGroups,
    mergePaths,
    svgo,
  ]) => {
    const overrides = {}

    const plugins = [
      "removeDoctype",
      "removeXMLProcInst",
      "removeComments",
      "removeMetadata",
      "removeEditorsNSData",
      "cleanupAttrs",
      "mergeStyles",
      "inlineStyles",
      "minifyStyles",
      "removeUselessDefs",
      "cleanupNumericValues",
      "convertColors",
      "removeUnknownsAndDefaults",
      "removeNonInheritableGroupAttrs",
      "removeUselessStrokeAndFill",
      "removeViewBox",
      "cleanupEnableBackground",
      "removeHiddenElems",
      "removeEmptyText",
      "convertShapeToPath",
      "moveElemsAttrsToGroup",
      "moveGroupAttrsToElems",
      "collapseGroups",
      "convertPathData",
      "convertEllipseToCircle",
      "convertTransform",
      "removeEmptyAttrs",
      "removeEmptyContainers",
      "mergePaths",
      "removeUnusedNS",
      "sortAttrs",
      "sortDefsChildren",
      "removeTitle",
      "removeDesc",
    ]

    plugins.forEach((key) => {
      overrides[key] = { floatPrecision, transformPrecision }
    })

    if (!collapseGroups) overrides.collapseGroups = false
    if (!mergePaths) overrides.mergePaths = false

    const value = svgo.optimize(svg, {
      multipass,
      js2svg: { indent, pretty },
      plugins: [
        {
          name: "preset-default",
          params: {
            overrides,
          },
        },
      ],
    }).data

    const scale = value.length / svg.length
    const message = `The new SVG is ${
      scale === 1
        ? "equal to"
        : +(scale * 100).toFixed(1) +
          "% " +
          (scale < 1 ? "smaller" : "larger") +
          " than"
    }  the source image.`

    return [
      {
        label: "Optimized SVG",
        type: "code",
        value,
      },
      {
        type: "image",
        label: "Preview",
        value,
        format: "svg",
      },
      {
        label: "Optimized SVG",
        type: "status",
        value: scale < 1,
        message,
      },
    ]
  },
})