I've been trying to display SVGs consistently across browsers in my gatsby.js app. I've tried two different methods and neither work completely.
我一直试图在我的gatsby.js应用程序中跨浏览器一致地显示SVG。我尝试了两种不同的方法,但都不完全奏效。
SVG Sprites
Following this answer, I created an icon sprite file and made a component to display the information.
按照这个答案,我创建了一个图标精灵文件,并制作了一个组件来显示信息。
import * as React from "react"
import { useStaticQuery, graphql } from "gatsby"
import PropTypes from "prop-types"
import { StyledSocialList, StyledSocialLi } from "./social.styled"
import IconsFile from "../../../static/images/icons.svg"
const Icon = ({ name, color, size }) => (
<svg className={`icon icon-${name}`} fill={color} width={size} height={size}>
<use xlinkHref={`${IconsFile}#icon-${name}`} />
</svg>
)
const Icons = ({ size }) => {
const data = useStaticQuery(graphql`
query SocialQuery {
site {
siteMetadata {
social {
linkedin
orcid
github
googlescholar
}
}
}
}
`)
const social = data.site.siteMetadata?.social
let icons = [
{
src: <Icon name="linkedin-square" color="#000" size={size} />,
link: `https://www.linkedin.com/in/${social?.linkedin}`,
alt: "Click to read my Linkedin profile",
},
{
src: <Icon name="github" color="#000" size={size} />,
link: `https://www.github.com/${social?.github}`,
alt: "Click to see my Github",
},
{
src: <Icon name="google-scholar" color="#000" size={size} />,
link: `https://scholar.google.com/citations?user=${social?.googlescholar}`,
alt: "Click to see my citations on Google Scholar",
},
{
src: <Icon name="orcid" color="#000" size={size} />,
link: `https://www.orcid.org/${social?.orcid}`,
alt: "Click to see my researcher profile on Orcid",
},
]
return icons.map((icon, index) => (
<StyledSocialLi key={index}>
<a
href={icon.link}
target="_blank"
rel="noreferrer"
alt={icon.alt}
aria-label={icon.alt}
>
{icon.src}
</a>
</StyledSocialLi>
))
}
const Social = ({ size = 30 }) => {
return (
<StyledSocialList>
<Icons size={size}/>
</StyledSocialList>
)
}
export default Social
This one works in Chrome, but Safari refuses to render the SVG because it thinks the href of the use
element is a XSS violation.
这个可以在Chrome中使用,但Safari拒绝呈现SVG,因为它认为Use元素的href违反了XSS。
data:image/svg+xml;base64,PHN2Z...#icon-orcid from origin https://kyleshores.com. Domains, protocols and ports must match.
Embedded paths
As an alternative, I tried creating the SVGs by saving their paths so that the data isn't loaded from what looks like a URI to Safari.
作为替代方案,我尝试通过保存它们的路径来创建SVG,这样数据就不会从看起来像是URI的东西加载到Safari。
import * as React from "react"
import { useStaticQuery, graphql } from "gatsby"
import { StyledSocialList, StyledSocialLi } from "./social.styled"
const Svg = ({ path, color, size }) => {
const viewBox = `0 0 ${size} ${size}`;
return (
<svg xmlns="http://www.w3.org/2000/svg" viewBox={viewBox} width={size} height={size} fill={color}>
<path d={path} />
</svg>
);
};
const paths= {
'linkedin': "M29 0h-26c-1.65 0-3 1.35-3 3v26c0 1.65 1.35 3 3 3h26c1.65 0 3-1.35 3-3v-26c0-1.65-1.35-3-3-3zM12 26h-4v-14h4v14zM10 10c-1.106 0-2-0.894-2-2s0.894-2 2-2c1.106 0 2 0.894 2 2s-0.894 2-2 2zM26 26h-4v-8c0-1.106-0.894-2-2-2s-2 0.894-2 2v8h-4v-14h4v2.481c0.825-1.131 2.087-2.481 3.5-2.481 2.488 0 4.5 2.238 4.5 5v9z",
'google-scholar': "M21.485 6.666v-1.702l1.235-0.964h-13.368l-8.072 7.017h5.354c-0.010 0.133-0.014 0.253-0.014 0.389 0 1.303 0.451 2.38 1.354 3.241 0.903 0.862 2.016 1.29 3.333 1.29 0.308 0 0.609-0.023 0.902-0.064-0.182 0.406-0.273 0.783-0.273 1.134 0 0.617 0.281 1.277 0.842 1.978-2.452 0.167-4.254 0.608-5.402 1.323-0.658 0.406-1.188 0.919-1.587 1.533-0.399 0.619-0.599 1.282-0.599 1.998 0 0.603 0.129 1.146 0.389 1.629s0.599 0.879 1.019 1.186c0.42 0.311 0.904 0.569 1.451 0.779 0.546 0.209 1.088 0.357 1.629 0.441 0.539 0.084 1.075 0.125 1.607 0.125 0.842 0 1.685-0.108 2.534-0.324 0.848-0.218 1.643-0.54 2.386-0.968 0.741-0.425 1.345-1.005 1.808-1.732 0.462-0.73 0.693-1.55 0.693-2.459 0-0.689-0.141-1.315-0.422-1.884-0.279-0.567-0.621-1.034-1.028-1.396s-0.813-0.697-1.22-0.998c-0.406-0.303-0.75-0.609-1.029-0.926-0.28-0.315-0.421-0.628-0.421-0.936s0.108-0.604 0.326-0.892c0.216-0.288 0.48-0.566 0.788-0.832s0.617-0.56 0.925-0.883c0.308-0.322 0.571-0.739 0.788-1.251s0.325-1.090 0.325-1.735c0-0.841-0.159-1.529-0.472-2.082-0.037-0.064-0.076-0.113-0.117-0.189l3.557-2.917v1.070c-0.462 0.058-0.414 0.334-0.414 0.665v8.042c0 0.372 0.305 0.677 0.677 0.677h0.249c0.372 0 0.677-0.305 0.677-0.677v-8.042c0-0.33 0.049-0.606-0.41-0.664zM14.775 20.571c0.071 0.047 0.232 0.174 0.482 0.377 0.253 0.203 0.425 0.356 0.517 0.463 0.090 0.104 0.224 0.26 0.399 0.472s0.295 0.394 0.357 0.546c0.063 0.155 0.126 0.341 0.19 0.559 0.062 0.215 0.093 0.436 0.093 0.66 0 1.066-0.41 1.855-1.229 2.366-0.82 0.511-1.798 0.767-2.934 0.767-0.574 0-1.138-0.068-1.691-0.2-0.553-0.132-1.082-0.334-1.587-0.6s-0.911-0.638-1.219-1.112c-0.309-0.477-0.463-1.026-0.463-1.641 0-0.645 0.175-1.206 0.526-1.682 0.35-0.477 0.809-0.837 1.377-1.082 0.566-0.247 1.141-0.421 1.723-0.525 0.582-0.106 1.175-0.16 1.777-0.16 0.279 0 0.496 0.016 0.65 0.044 0.028 0.014 0.19 0.129 0.483 0.348 0.294 0.216 0.477 0.35 0.547 0.399zM14.565 14.285c-0.463 0.554-1.108 0.831-1.935 0.831-0.741 0-1.394-0.298-1.954-0.895-0.563-0.595-0.964-1.271-1.209-2.027-0.246-0.757-0.369-1.499-0.369-2.228 0-0.856 0.225-1.585 0.674-2.186 0.449-0.603 1.094-0.905 1.934-0.905 0.742 0 1.398 0.315 1.965 0.947 0.568 0.63 0.976 1.338 1.22 2.123 0.245 0.784 0.367 1.533 0.367 2.249 0 0.84-0.231 1.538-0.692 2.091z",
'orcid': "M21.039 12.159c-0.446-0.208-0.867-0.347-1.266-0.413-0.398-0.068-1.036-0.101-1.919-0.101h-2.294v9.547h2.352c0.917 0 1.63-0.063 2.139-0.189s0.933-0.283 1.272-0.477c0.34-0.192 0.651-0.429 0.934-0.712 0.905-0.92 1.359-2.080 1.359-3.482 0-1.378-0.465-2.503-1.396-3.374-0.344-0.323-0.739-0.59-1.181-0.8zM16 0.5c-8.561 0-15.5 6.94-15.5 15.5s6.939 15.5 15.5 15.5c8.561 0 15.5-6.94 15.5-15.5s-6.939-15.5-15.5-15.5zM10.854 22.845h-1.837v-12.835h1.837zM9.934 8.668c-0.696 0-1.263-0.563-1.263-1.263 0-0.695 0.566-1.262 1.263-1.262 0.699 0 1.265 0.566 1.265 1.262-0.001 0.701-0.566 1.263-1.265 1.263zM25.021 18.893c-0.331 0.784-0.802 1.474-1.416 2.068-0.624 0.615-1.35 1.075-2.178 1.387-0.484 0.189-0.927 0.316-1.332 0.382-0.406 0.063-1.177 0.094-2.317 0.094h-4.060v-12.816h4.327c1.748 0 3.127 0.26 4.145 0.784 1.017 0.523 1.824 1.296 2.424 2.311 0.601 1.017 0.902 2.126 0.902 3.325 0.001 0.86-0.167 1.682-0.496 2.465z",
'github': "M16 0.395c-8.836 0-16 7.163-16 16 0 7.069 4.585 13.067 10.942 15.182 0.8 0.148 1.094-0.347 1.094-0.77 0-0.381-0.015-1.642-0.022-2.979-4.452 0.968-5.391-1.888-5.391-1.888-0.728-1.849-1.776-2.341-1.776-2.341-1.452-0.993 0.11-0.973 0.11-0.973 1.606 0.113 2.452 1.649 2.452 1.649 1.427 2.446 3.743 1.739 4.656 1.33 0.143-1.034 0.558-1.74 1.016-2.14-3.554-0.404-7.29-1.777-7.29-7.907 0-1.747 0.625-3.174 1.649-4.295-0.166-0.403-0.714-2.030 0.155-4.234 0 0 1.344-0.43 4.401 1.64 1.276-0.355 2.645-0.532 4.005-0.539 1.359 0.006 2.729 0.184 4.008 0.539 3.054-2.070 4.395-1.64 4.395-1.64 0.871 2.204 0.323 3.831 0.157 4.234 1.026 1.12 1.647 2.548 1.647 4.295 0 6.145-3.743 7.498-7.306 7.895 0.574 0.497 1.085 1.47 1.085 2.963 0 2.141-0.019 3.864-0.019 4.391 0 0.426 0.288 0.925 1.099 0.768 6.354-2.118 10.933-8.113 10.933-15.18 0-8.837-7.164-16-16-16z",
}
const Icons = props => {
const data = useStaticQuery(graphql`
query SocialQuery {
site {
siteMetadata {
social {
linkedin
orcid
github
googlescholar
}
}
}
}
`)
const social = data.site.siteMetadata?.social
let icons = [
{
src: <Svg path={paths['linkedin']} {...props}/>,
link: `https://www.linkedin.com/in/${social?.linkedin}`,
},
{
src: <Svg path={paths['github']} {...props}/>,
link: `https://www.github.com/${social?.github}`,
},
{
src: <Svg path={paths['google-scholar']} {...props}/>,
link: `https://scholar.google.com/citations?user=${social?.googlescholar}`,
},
{
src: <Svg path={paths['orcid']} {...props}/>,
link: `https://www.orcid.org/${social?.orcid}`,
},
]
return icons.map((icon, index) => (
<StyledSocialLi key={index}>
<a href={icon.link} target="_blank" rel="noreferrer">
{icon.src}
</a>
</StyledSocialLi>
))
}
const Social = ({ size = 10, color = "black" }) => {
return (
<StyledSocialList>
<Icons size={size} color={color} />
</StyledSocialList>
)
}
export default Social
In this case, the icons render in both browsers, but the size is not respected. The svg
element is sized appropriately, but the enclosing path is always 32 x 32.
在这种情况下,图标在两个浏览器中都会呈现,但不考虑大小。SVG元素的大小适当,但封闭路径始终为32x32。
Here's how it looks:
它看起来是这样的:
I don't have a preference for either approach, but I would appreciate some advice on how I might correct this.
我对这两种方法都没有偏爱,但我希望得到一些关于如何纠正这一点的建议。
Styles
In both cases, the styled components are this:
在这两种情况下,样式化组件如下所示:
import styled from 'styled-components';
const StyledSocialList = styled.ul`
list-style-type: none;
margin: 0;
padding: 0;
`
const StyledSocialLi = styled.li`
display: inline;
padding: 0 var(--spacing-1);
`
export {
StyledSocialList,
StyledSocialLi,
}
更多回答
I think for example 2 your viewbox should be 0 0 32 32
since that's the coordinate system used by the paths. I'm not clear what problematic output you're getting though.
我想例如,你的视框应该是0,0,32,32,因为这是路径使用的坐标系。我不清楚您得到的是什么有问题的输出。
@James I added a picture to show the erroneous rendering. You are correct that setting the viewbox to 0 0 32 32
fixes the issue. I don't have a ton of knowledge about SVGs. I don't see how I can know what the coordinate system is from those paths. Frankly, I'd rather not have to do it this way, but this seems to be something that works in both Safari and Chrome.
@James I添加了一张图片来显示错误的渲染。将视图框设置为0 0 32 32可以解决问题,这一点是正确的。我没有太多关于SVG的知识。我不明白我怎么能从这些路径知道坐标系是什么。坦率地说,我不想这样做,但这似乎是Safari和Chrome都能用的东西。
Isn't the viewBox usually given as part of the icon? Example - instagram icon if you look at the "svg" tab.
视框不是通常作为图标的一部分给出的吗?例子--Instagram图标,如果你看“SVG”标签。
And so it was. The original was set to 0 0 512 512
. That makes everything too small and 0 0 32 32
works. Either way, thanks for your help
事实就是如此。原始设置为0 0 512 512。这使得所有东西都太小了,0 0 32 32就行了。不管怎样,谢谢你的帮助
Another solution that works in both browsers is to embed the SVG data into the component so that Safari doesn't think something is loaded from another URL.
另一种在两种浏览器中都适用的解决方案是将SVG数据嵌入到组件中,这样Safari就不会认为是从另一个URL加载的内容。
import * as React from "react"
import { useStaticQuery, graphql } from "gatsby"
import { StyledSocialList, StyledSocialLi } from "./social.styled"
since it thought the data was from some other place
const Icon = ({ name, color, size }) => (
<svg className={`icon icon-${name}`} fill={color} width={size} height={size}>
<use xlinkHref={`#icon-${name}`} />
<symbol id="icon-google-scholar" viewBox="0 0 512 512">
<path d="m408 107l0-28 20-15-214 0-130 112 86 0c0 2 0 4 0 7 0 20 7 38 22 51 14 14 32 21 53 21 5 0 10 0 14-1-3 6-4 13-4 18 0 10 4 21 13 32-39 2-68 10-86 21-11 6-19 15-25 24-7 10-10 21-10 32 0 10 2 19 6 26 4 8 10 15 17 19 6 5 14 10 23 13 9 3 17 6 26 7 8 1 17 2 26 2 13 0 27-2 40-5 14-4 26-9 38-16 12-6 22-16 29-27 8-12 11-25 11-40 0-11-2-21-6-30-5-9-10-16-17-22-6-6-13-11-19-16-7-5-12-10-17-15-4-5-7-10-7-15 0-5 2-10 6-14 3-5 7-9 12-14 5-4 10-9 15-14 5-5 9-12 13-20 3-8 5-17 5-27 0-14-3-25-8-34 0-1-1-2-2-3l57-46 0 17c-7 1-6 5-6 10l0 129c0 6 5 11 10 11l4 0c6 0 11-5 11-11l0-129c0-5 1-9-6-10z m-108 222c2 1 4 3 8 6 4 3 7 6 8 8 2 1 4 4 7 7 3 4 4 6 5 9 1 2 2 5 4 9 1 3 1 7 1 10 0 17-7 30-20 38-13 8-28 13-47 13-9 0-18-2-27-4-8-2-17-5-25-9-8-5-15-10-20-18-4-8-7-16-7-26 0-11 3-20 8-27 6-8 13-14 23-18 9-3 18-6 27-8 9-2 19-3 29-3 4 0 7 1 10 1 0 0 3 2 8 6 4 3 7 5 8 6z m-3-100c-7 8-18 13-31 13-12 0-22-5-31-14-9-10-16-21-20-33-3-12-5-24-5-36 0-13 3-25 10-35 8-9 18-14 31-14 12 0 23 5 32 15 9 10 15 22 19 34 4 13 6 25 6 36 0 14-4 25-11 34z" />
</symbol>
<symbol id="icon-orcid" viewBox="0 0 512 512">
<path d="m337 195c-8-4-14-6-21-7-6-1-16-2-30-2l-37 0 0 153 38 0c14 0 26-1 34-3 8-2 15-4 20-8 6-3 11-6 15-11 15-15 22-33 22-56 0-22-8-40-22-54-6-5-12-9-19-12z m-81-187c-137 0-248 111-248 248 0 137 111 248 248 248 137 0 248-111 248-248 0-137-111-248-248-248z m-82 358l-30 0 0-206 30 0z m-15-227c-11 0-20-9-20-21 0-11 9-20 20-20 11 0 20 9 20 20 0 12-9 21-20 21z m241 163c-5 13-12 24-22 33-10 10-22 18-35 23-8 3-15 5-21 6-7 1-19 1-38 1l-64 0 0-205 69 0c28 0 50 4 66 13 16 8 29 20 39 37 9 16 14 34 14 53 0 14-2 27-8 39z" />
</symbol>
<symbol id="icon-linkedin-square" viewBox="0 0 512 512">
<path d="m104 404l66 0 0-198-66 0z m71-259c-1-10-4-19-11-25-6-6-15-10-26-10-11 0-20 4-27 10-7 6-11 15-11 25 0 9 4 17 10 24 7 7 16 10 27 10l0 0c11 0 20-3 27-10 7-7 11-15 11-24z m167 259l66 0 0-114c0-29-7-51-21-66-14-15-32-23-55-23-26 0-46 11-60 34l1 0 0-29-66 0c0 12 0 78 0 198l66 0 0-111c0-7 0-12 2-16 2-7 7-12 12-17 6-5 13-7 22-7 22 0 33 15 33 45z m133-285l0 274c0 23-8 42-24 58-16 16-35 24-58 24l-274 0c-23 0-42-8-58-24-16-16-24-35-24-58l0-274c0-23 8-42 24-58 16-16 35-24 58-24l274 0c23 0 42 8 58 24 16 16 24 35 24 58z" />
</symbol>
<symbol id="icon-github" viewBox="0 0 512 512">
<path d="m475 256c0 48-14 91-41 129-28 38-64 65-109 79-5 1-8 1-11-2-2-2-3-5-3-8l0-61c0-18-5-32-15-40 11-1 20-3 29-5 9-3 18-6 27-11 9-6 17-12 23-19 6-8 11-18 15-30 4-13 6-27 6-43 0-23-8-43-23-59 7-18 7-37-2-59-5-1-13 0-23 4-10 3-19 8-26 12l-11 7c-18-5-36-7-55-7-19 0-37 2-55 7-3-2-7-5-12-8-5-3-13-6-24-11-11-4-19-5-24-4-9 22-9 41-2 59-15 16-23 36-23 59 0 16 2 30 6 42 4 13 9 23 15 30 6 8 14 14 23 20 9 5 18 8 27 11 8 2 18 4 29 5-8 7-12 17-14 29-4 2-8 4-13 5-4 1-10 1-16 1-6 0-13-2-19-6-6-4-11-10-16-18-3-6-8-11-14-15-5-4-10-6-14-7l-5-1c-4 0-7 1-9 2-1 1-2 2-1 3 0 1 1 3 2 4 2 1 3 2 4 3l2 2c4 2 8 5 13 11 4 5 7 10 9 14l2 7c3 7 7 13 13 17 6 5 12 8 19 9 7 1 14 2 20 2 6 0 12 0 16-1l6-1c0 7 0 16 1 25 0 10 0 15 0 16 0 3-2 6-4 8-2 3-6 3-11 2-45-14-81-41-109-79-27-38-41-81-41-129 0-40 9-77 29-110 20-34 46-60 80-80 33-20 70-29 110-29 40 0 77 9 110 29 34 20 60 46 80 80 20 33 29 70 29 110z" />
</symbol>
</svg>
)
const Icons = props => {
const data = useStaticQuery(graphql`
query SocialQuery {
site {
siteMetadata {
social {
linkedin
orcid
github
googlescholar
}
}
}
}
`)
const social = data.site.siteMetadata?.social
let icons = [
{
src: <Icon name="linkedin-square" {...props} />,
link: `https://www.linkedin.com/in/${social?.linkedin}`,
alt: "Click to read my Linkedin profile",
},
{
src: <Icon name="github" {...props} />,
link: `https://www.github.com/${social?.github}`,
alt: "Click to see my Github",
},
{
src: <Icon name="google-scholar" {...props} />,
link: `https://scholar.google.com/citations?user=${social?.googlescholar}`,
alt: "Click to see my citations on Google Scholar",
},
{
src: <Icon name="orcid" {...props} />,
link: `https://www.orcid.org/${social?.orcid}`,
alt: "Click to see my researcher profile on Orcid",
},
]
return icons.map((icon, index) => (
<StyledSocialLi key={index}>
<a
href={icon.link}
target="_blank"
rel="noreferrer"
alt={icon.alt}
aria-label={icon.alt}
>
{icon.src}
</a>
</StyledSocialLi>
))
}
const Social = ({ size = 30, color = "black" }) => {
return (
<StyledSocialList>
<Icons size={size} color={color} />
</StyledSocialList>
)
}
export default Social
更多回答
我是一名优秀的程序员,十分优秀!