SVG エスケープツール(SVG URL Encoder)

SVG 用に URL エンコード(エスケープ)するツールです。

CSS の疑似要素(::before ::after)や背景画像(background-image)にデータ URL を使って svg 要素を指定する場合、svg のマークアップを URI エンコードする必要がありますが、マニュアルで変換するのは面倒なので作成したものです。

JavaScript の encodeURIComponent 関数を使って変換することもできますが、スペースなども変換されてサイズが大きくなってしまいます。

関連ページ:SVG の使い方(CSS で svg 要素を表示)

作成日:2021年03月21日

変換ツール

<、>、# 文字をそれぞれ %3C、%3E、%23 にパーセントエンコード変換します。

また、その際にダブルクオート(")はシングルクォート(')に変換し、改行は削除します。

例えば、以下を入力して「変換」をクリックすると

<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="#ab1f1f" viewBox="0 0 16 16">
  <path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14m0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16"/>
  <path d="M4.285 9.567a.5.5 0 0 1 .683.183A3.5 3.5 0 0 0 8 11.5a3.5 3.5 0 0 0 3.032-1.75.5.5 0 1 1 .866.5A4.5 4.5 0 0 1 8 12.5a4.5 4.5 0 0 1-3.898-2.25.5.5 0 0 1 .183-.683M7 6.5C7 7.328 6.552 8 6 8s-1-.672-1-1.5S5.448 5 6 5s1 .672 1 1.5m4 0c0 .828-.448 1.5-1 1.5s-1-.672-1-1.5S9.448 5 10 5s1 .672 1 1.5"/>
</svg>

以下のように変換されます。

%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='%23ab1f1f' viewBox='0 0 16 16'%3E  %3Cpath d='M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14m0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16'/%3E  %3Cpath d='M4.285 9.567a.5.5 0 0 1 .683.183A3.5 3.5 0 0 0 8 11.5a3.5 3.5 0 0 0 3.032-1.75.5.5 0 1 1 .866.5A4.5 4.5 0 0 1 8 12.5a4.5 4.5 0 0 1-3.898-2.25.5.5 0 0 1 .183-.683M7 6.5C7 7.328 6.552 8 6 8s-1-.672-1-1.5S5.448 5 6 5s1 .672 1 1.5m4 0c0 .828-.448 1.5-1 1.5s-1-.672-1-1.5S9.448 5 10 5s1 .672 1 1.5'/%3E%3C/svg%3E

SVG を入力

変換結果


        

使用例

CSS の疑似要素(::before ::after)を使って svg を表示する場合、content または、background-image の値に url() 関数でデータ URL スキーム(data:image/svg+xml)を使って URI エンコードした svg のコードを指定します。

以下は URI エンコードした上記サンプルの svg を ::before を使って background-image に指定して表示する例です。

background-image の url() 関数で data:image/svg+xml, 以降に変換したコードを指定します。

.icon-smile::before {
  content: "";
  display: inline-block;
  height: 16px;
  width: 16px;
  vertical-align: -3px;
  margin-right: 8px;
  background-repeat: no-repeat;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='%23ab1f1f' viewBox='0 0 16 16'%3E  %3Cpath d='M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14m0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16'/%3E  %3Cpath d='M4.285 9.567a.5.5 0 0 1 .683.183A3.5 3.5 0 0 0 8 11.5a3.5 3.5 0 0 0 3.032-1.75.5.5 0 1 1 .866.5A4.5 4.5 0 0 1 8 12.5a4.5 4.5 0 0 1-3.898-2.25.5.5 0 0 1 .183-.683M7 6.5C7 7.328 6.552 8 6 8s-1-.672-1-1.5S5.448 5 6 5s1 .672 1 1.5m4 0c0 .828-.448 1.5-1 1.5s-1-.672-1-1.5S9.448 5 10 5s1 .672 1 1.5'/%3E%3C/svg%3E");
}

以下を記述すると、

<p class="icon-smile">Smile Icon</p>

以下のように表示されます。

Smile Icon

ツールのコード

以下は上記変換ツールの HTML です。

<div>
  <textarea id="input" rows="20" cols="60"></textarea>
</div>
<button id="encode">変換</button>
<button id="clear">クリア</button>
<button id="restore">リストア</button>
<div class="output">
  <button id="copy-btn">結果をコピー</button>
  <p>変換結果</p>
  <pre id="output"></pre>
</div>

以下は上記ツールの JavaScript です。

const encodeBtn = document.getElementById('encode');
const clearBtn = document.getElementById('clear');
const restoreBtn = document.getElementById('restore');
const input =  document.getElementById('input');
const output =  document.getElementById('output');
const copyBtn = document.getElementById('copy-btn');
let inputValue = '';
let outputValue = '';

encodeBtn.addEventListener('click', () => {
  inputValue = input.value;
  outputValue = inputValue.replace(/#/g,"%23")
  .replace(/</g,"%3C")
  .replace(/>/g,"%3E")
  .replace(/"/g,"'")
  .replace(/\r?\n/g,'');
  output.textContent = outputValue;
});

clearBtn.addEventListener('click', () => {
  output.textContent = '';
  input.value = '';
});

restoreBtn.addEventListener('click', () => {
  output.textContent = outputValue;
  input.value = inputValue;
});

copyBtn.addEventListener('click', () => {
  copyToClipboard(copyBtn, output.textContent)
}, false);

function copyToClipboard(btn, text) {
  if (!navigator.clipboard) {
    alert('お使いのブラウザではコピーできません。');
  }
  navigator.clipboard.writeText(text).then(
    () => {
      btn.textContent = 'コピー完了';
      resetCopyBtnText(btn, 1500);
    },
    (error) => {
      btn.textContent = '失敗';
      resetCopyBtnText(btn, 1500);
      console.log(error.message);
    }
  );
};

function resetCopyBtnText(btn, delay) {
  setTimeout(() => {
    btn.textContent = '結果をコピー'
  }, delay)
}

サンプルコード

以下のコードをコピーして html ファイルとして保存すれば、ローカルで使用できます。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>SVG エスケープツール</title>
  <style>
    body {
      margin: 50px auto;
      max-width: 840px;
    }

    button {
      border: 1px solid #999;
      padding: .5rem;
      cursor: pointer;
    }

    textarea {
      width: 95%;
      margin: 10px auto;
    }

    #copy-btn {
      margin-top: 20px;
    }

    #output {
      width: 95%;
      border: 1px solid #ccc;
      padding: 10px;
      background-color: #efefef;
      font-family: "Lucida Console", Monaco, monospace;
      white-space: pre-wrap;
      overflow: auto;
      margin: 30px 0;
      min-height: 100px;
    }
  </style>
</head>
<body>
  <div>
    <textarea id="input" rows="20" cols="60"></textarea>
  </div>
  <button id="encode">変換</button>
  <button id="clear">クリア</button>
  <button id="restore">リストア</button>
  <div class="output">
    <button id="copy-btn">結果をコピー</button>
    <p>変換結果</p>
    <pre id="output"></pre>
  </div>

  <script>
    const encodeBtn = document.getElementById('encode');
    const clearBtn = document.getElementById('clear');
    const restoreBtn = document.getElementById('restore');
    const input = document.getElementById('input');
    const output = document.getElementById('output');
    const copyBtn = document.getElementById('copy-btn');
    let inputValue = '';
    let outputValue = '';

    encodeBtn.addEventListener('click', () => {
      inputValue = input.value;
      outputValue = inputValue.replace(/#/g, "%23")
        .replace(/</g, "%3C")
        .replace(/>/g, "%3E")
        .replace(/"/g, "'")
        .replace(/\r?\n/g, '');
      output.textContent = outputValue;
    });

    clearBtn.addEventListener('click', () => {
      output.textContent = '';
      input.value = '';
    });

    restoreBtn.addEventListener('click', () => {
      output.textContent = outputValue;
      input.value = inputValue;
    });

    copyBtn.addEventListener('click', () => {
      copyToClipboard(copyBtn, output.textContent)
    }, false);

    function copyToClipboard(btn, text) {
      if (!navigator.clipboard) {
        alert('お使いのブラウザではコピーできません。');
      }
      navigator.clipboard.writeText(text).then(
        () => {
          btn.textContent = 'コピー完了';
          resetCopyBtnText(btn, 1500);
        },
        (error) => {
          btn.textContent = '失敗';
          resetCopyBtnText(btn, 1500);
          console.log(error.message);
        }
      );
    };

    function resetCopyBtnText(btn, delay) {
      setTimeout(() => {
        btn.textContent = '結果をコピー'
      }, delay)
    }
  </script>
</body>
</html>

関連ページ: