当在 <img> 标记中使用 SVG 时,为什么 linearGradient ID 中的冒号会中断它们?
Why do colons in linearGradient IDs break them when the SVG is used in an <img> tag?
获取以下源并将其保存为 test.svg
文件。
<svg viewBox="0 0 10 10" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<linearGradient id="myGradient:1234" gradientTransform="rotate(90)">
<stop offset="5%" stop-color="gold"></stop>
<stop offset="95%" stop-color="red"></stop>
</linearGradient>
</defs>
<circle cx="5" cy="5" r="4" fill="url('#myGradient:1234')"></circle>
</svg>
打开Chrome中的test.svg
文件,你会看到一个从黄色到红色混合的圆圈。但是,如果您创建一个 HTML 文件并以 <img src="text.svg" />
的形式包含此 SVG,您将看到,至少在 Chrome 中,没有颜色应用于圆。
如果您更新 test.svg
以将 ID 从 myGradient:1234
更改为 myGradient
,那么当在 <img>
标签中使用图像时颜色将开始工作。
为什么这种行为不同?
实际上包含 ':'(冒号)的 ID 也不应该在独立文件中工作。
这是 XML 命名合规性的问题。
It must be valid in XML documents. A stand-alone SVG document uses XML 1.0 syntax, which specifies that valid IDs only include designated characters (letters, digits, and a few punctuation marks), and do not start with a digit, a full stop (.) character, or a hyphen-minus (-) character.
根据经验:
应用相同的命名规则,您还需要 html/css/js 选择器:
- 保持 ansi:避免非英文字符,如 diacritics/accents 等
- 不要以任何数字开头选择器名称 - 像 'element-01' 一样附加它们是完全可以的
- 避免使用也用作运算符的字符:例如用于伪元素的冒号、用于相邻兄弟元素的加号或波浪号等。
#myGradient\:1234{
color:red
}
#myGradient\:1234,
# 234myGradient{
color:#000
}
#myGradient-1234{
color:green
}
<ul>
<li id="myGradient-1234">Selectable!</li>
<li id="myGradient:1234">Not selectable: selector contains <strong>colon operator reserved for pseudo elements</strong>. You might however escape the colon by a backslash</li>
<li id="1234myGradient">Not Selectable: selector starts with <strong>numbers</strong></li>
</ul>
编辑:这是一个检查有效性的辅助函数。
checkIDs(document.body);
// check id validity
function checkIDs(el) {
let Ids = el.querySelectorAll('[id]');
let allIds = [];
let IdIssues = {
'non-unique': {},
'not-selectable': [],
}
for (let i = 0; i < Ids.length; i++) {
let thisId = Ids[i].id;
if (allIds.indexOf(thisId) == -1) {
allIds.push(thisId);
} else {
let idKey = '\'' + thisId + '\'';
if (!IdIssues['non-unique'][idKey]) {
IdIssues['non-unique'][idKey] = 2;
} else {
IdIssues['non-unique'][idKey] += 1;
}
}
try {
let selection = document.querySelector('#' + thisId);
} catch {
if (IdIssues['not-selectable'].indexOf(thisId) == -1) {
IdIssues['not-selectable'].push(thisId);
}
}
}
let errorCount = 0;
let nonUniqueCount = Object.keys(IdIssues['non-unique']).length;
let notSelectableCount = IdIssues['not-selectable'].length;
errorCount = nonUniqueCount + notSelectableCount;
if (errorCount) {
console.log('Id naming issues found:\n' + 'non unique Ids: ' + nonUniqueCount + '\n' + 'not selectable Ids: ' + notSelectableCount);
console.log(IdIssues);
} else {
console.log('Well done! – all Ids are valid and unique!')
}
}
<svg id="test" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
<circle id="circle" fill="none" cx="50%" cy="100%" r="50%" stroke="red" stroke-width="2" />
<circle id="circle:123" fill="none" cx="25%" cy="25%" r="25%" stroke="green" stroke-width="2" />
</svg>
<p id="p1@test">test1</p>
<p id="p1!test">test1</p>
<p id="c'mon">test1</p>
<p id="p2">test1</p>
<p id="p2">test1</p>
<p id="p2:1:2">test1</p>
<p id="0123id">test1</p>
这个 js 辅助函数使用一个简单的 try/catch 来检查一个元素是否在 DOM 中实际上是可选的。所以我们不需要检查数百个著名的不合规 character/naming 问题。
此外,该脚本还将检查可能也会引起问题的非唯一 ID。
获取以下源并将其保存为 test.svg
文件。
<svg viewBox="0 0 10 10" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<linearGradient id="myGradient:1234" gradientTransform="rotate(90)">
<stop offset="5%" stop-color="gold"></stop>
<stop offset="95%" stop-color="red"></stop>
</linearGradient>
</defs>
<circle cx="5" cy="5" r="4" fill="url('#myGradient:1234')"></circle>
</svg>
打开Chrome中的test.svg
文件,你会看到一个从黄色到红色混合的圆圈。但是,如果您创建一个 HTML 文件并以 <img src="text.svg" />
的形式包含此 SVG,您将看到,至少在 Chrome 中,没有颜色应用于圆。
如果您更新 test.svg
以将 ID 从 myGradient:1234
更改为 myGradient
,那么当在 <img>
标签中使用图像时颜色将开始工作。
为什么这种行为不同?
实际上包含 ':'(冒号)的 ID 也不应该在独立文件中工作。 这是 XML 命名合规性的问题。
It must be valid in XML documents. A stand-alone SVG document uses XML 1.0 syntax, which specifies that valid IDs only include designated characters (letters, digits, and a few punctuation marks), and do not start with a digit, a full stop (.) character, or a hyphen-minus (-) character.
根据经验:
应用相同的命名规则,您还需要 html/css/js 选择器:
- 保持 ansi:避免非英文字符,如 diacritics/accents 等
- 不要以任何数字开头选择器名称 - 像 'element-01' 一样附加它们是完全可以的
- 避免使用也用作运算符的字符:例如用于伪元素的冒号、用于相邻兄弟元素的加号或波浪号等。
#myGradient\:1234{
color:red
}
#myGradient\:1234,
# 234myGradient{
color:#000
}
#myGradient-1234{
color:green
}
<ul>
<li id="myGradient-1234">Selectable!</li>
<li id="myGradient:1234">Not selectable: selector contains <strong>colon operator reserved for pseudo elements</strong>. You might however escape the colon by a backslash</li>
<li id="1234myGradient">Not Selectable: selector starts with <strong>numbers</strong></li>
</ul>
编辑:这是一个检查有效性的辅助函数。
checkIDs(document.body);
// check id validity
function checkIDs(el) {
let Ids = el.querySelectorAll('[id]');
let allIds = [];
let IdIssues = {
'non-unique': {},
'not-selectable': [],
}
for (let i = 0; i < Ids.length; i++) {
let thisId = Ids[i].id;
if (allIds.indexOf(thisId) == -1) {
allIds.push(thisId);
} else {
let idKey = '\'' + thisId + '\'';
if (!IdIssues['non-unique'][idKey]) {
IdIssues['non-unique'][idKey] = 2;
} else {
IdIssues['non-unique'][idKey] += 1;
}
}
try {
let selection = document.querySelector('#' + thisId);
} catch {
if (IdIssues['not-selectable'].indexOf(thisId) == -1) {
IdIssues['not-selectable'].push(thisId);
}
}
}
let errorCount = 0;
let nonUniqueCount = Object.keys(IdIssues['non-unique']).length;
let notSelectableCount = IdIssues['not-selectable'].length;
errorCount = nonUniqueCount + notSelectableCount;
if (errorCount) {
console.log('Id naming issues found:\n' + 'non unique Ids: ' + nonUniqueCount + '\n' + 'not selectable Ids: ' + notSelectableCount);
console.log(IdIssues);
} else {
console.log('Well done! – all Ids are valid and unique!')
}
}
<svg id="test" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
<circle id="circle" fill="none" cx="50%" cy="100%" r="50%" stroke="red" stroke-width="2" />
<circle id="circle:123" fill="none" cx="25%" cy="25%" r="25%" stroke="green" stroke-width="2" />
</svg>
<p id="p1@test">test1</p>
<p id="p1!test">test1</p>
<p id="c'mon">test1</p>
<p id="p2">test1</p>
<p id="p2">test1</p>
<p id="p2:1:2">test1</p>
<p id="0123id">test1</p>
这个 js 辅助函数使用一个简单的 try/catch 来检查一个元素是否在 DOM 中实际上是可选的。所以我们不需要检查数百个著名的不合规 character/naming 问题。
此外,该脚本还将检查可能也会引起问题的非唯一 ID。