SVG样式中的CSS类名是全局的吗?

ukqbszuj  于 2023-06-25  发布在  其他
关注(0)|答案(3)|浏览(140)

如果我在HTML主体中有几个SVG元素,其中每个SVG引用一个CSS类名,并且这个类名在下面的一个SVG元素中定义,那么所有SVG元素都受此样式的影响。我试图找出这是否是设计的,以及如何确保CSS类名对于定义它的SVG是本地的。

<svg xmlns="http://www.w3.org/2000/svg" width=100 viewBox="0 0 15 10">
    <path class="iconMain" d="M7.5,9,1,4.78789l.46713-.91645L7.5,7.85543l6.03287-3.984L14,4.78789ZM14,1.91646,13.53287,1,7.5,4.98349,1.46713,1,1,1.91646l6.5,4.2121Z" />
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width=100 viewBox="0 0 15 10">
    <defs>
        <style>
            .iconMain {
                fill: #9cbacf;
            }
        </style>
    </defs>
    <path class="iconMain"
        d="M7.5,9,1,4.78789l.46713-.91645L7.5,7.85543l6.03287-3.984L14,4.78789ZM14,1.91646,13.53287,1,7.5,4.98349,1.46713,1,1,1.91646l6.5,4.2121Z" />
</svg>

https://codepen.io/napsta32/pen/ExOPGae

aiqt4smr

aiqt4smr1#

你误解了defs的用法,他们习惯于define图形元素,稍后使用use标签,如果你在里面放一些不是图形元素的东西,它会直接进入文档,例如样式或脚本。即使def也是全局的,如果你在svg中定义了一个元素,你可以在另一个svg中使用它。

<svg xmlns="http://www.w3.org/2000/svg" width=100 viewBox="0 0 15 10">
  <defs>
  <circle id="circle_defined_in_first_svg" cx="1" cy="2" r="6" />
 </defs>
  
    <path class="iconMain" d="M7.5,9,1,4.78789l.46713-.91645L7.5,7.85543l6.03287-3.984L14,4.78789ZM14,1.91646,13.53287,1,7.5,4.98349,1.46713,1,1,1.91646l6.5,4.2121Z" />
</svg>

<svg xmlns="http://www.w3.org/2000/svg" width=100 viewBox="0 0 15 10">
    <defs>
        <style>
            .iconMain {
                fill: #9cbacf;
                background-color:pink;
            }
        </style>       
      <script>
        var variableInsideDef = 7987;
      </script>      
    </defs>
    <path class="iconMain"
        d="M7.5,9,1,4.78789l.46713-.91645L7.5,7.85543l6.03287-3.984L14,4.78789ZM14,1.91646,13.53287,1,7.5,4.98349,1.46713,1,1,1.91646l6.5,4.2121Z" />
  
  <use x="5" y="5" href="#circle_defined_in_first_svg"/>
  
</svg>

<p class="iconMain"> P ELEMENT IN ROOT AFFECTED BY THE STYLE INSIDE DEF</p>

<script>
  alert("Variable declared inside def: " + variableInsideDef)
</script>

我能想到的唯一方法是让样式只适用于一个特定的svg是为每一个样式都有一个不同的类。

pxiryf3j

pxiryf3j2#

是的,SVG内容是全局内容。

  • id属性变为重复,以下SVG将<use>第一个元素与该id
  • <style>成为全局样式。

最简单、最现代的方法是:

创建一个*原生 * JavaScript Web组件(JSWC)

innerHTML Package 在shadowDOM中,创建您所要的“scope”,
所以样式不会 * 泄漏 *(除了CSS属性,partsinheritable styles

  • 或泄露出去 *
    Symantic HTML:
<svg-chevron></svg-chevron>
    <svg-chevron color="green"></svg-chevron>
    <svg-chevron color="blue"></svg-chevron>
    <svg-chevron color="gold"></svg-chevron>

然后创建:

<svg-chevron></svg-chevron>
<svg-chevron color="green"></svg-chevron>
<svg-chevron color="blue"></svg-chevron>
<svg-chevron color="gold"></svg-chevron>

<style>
 [color] { --iconhovercolor:beige }
 path { fill:red!important } /* never applied to shadowDOM */
</style>

<script>
  customElements.define('svg-chevron', class extends HTMLElement {
    connectedCallback(){
      Object.assign( this.style , {
        display : "inline-block",
        width   : "100px",
        cursor  : "pointer"
      });
      let color = this.getAttribute("color") || "black";
      let d = "m75 90-65-42 5-9 60 40 60-40 5 9zm65-71-5-9-60 40-60-40-5 9 65 42z";
      this.attachShadow({mode:"open"})
          .innerHTML = `<style>
                          path{fill:${color}}
                          svg:hover{background:var(--iconhovercolor,red)}
                        </style>
                        <svg viewBox="0 0 150 100">
                         <path d="${d}" stroke="${color}"/>
                        </svg>`;
      this.onclick = (evt) => {
           console.log("You clicked me!", color);
      }
    }
  });
</script>

将Web组件重构为<svg-icon>,您就拥有了自己的图标设计系统:

<svg-icon is="chevron"></svg-icon>
  <svg-icon is="menu"></svg-icon>
  <svg-icon is="settings"></svg-icon>

来自另一个StackOverflow问题的fishice图标:

<style>
  svg-icon {  --iconhovercolor:beige;  width: 120px  }
</style>

<svg-icon></svg-icon>
<svg-icon is="fish" color="green"></svg-icon>
<svg-icon is="fish" color="blue"></svg-icon>
<svg-icon color="teal"></svg-icon>

<script>
  customElements.define('svg-icon', class extends HTMLElement {
        connectedCallback() {
          Object.assign(this.style, {
            display: "inline-block",
            cursor: "pointer"
          });
          let is = this.getAttribute("is") || "ice";
          let color = this.getAttribute("color") || "black";
          let d = {
            "fish": "m64 46s-.7 2.7-2.6 5.3c-1.9 2.5-4 3.4-4 3.4s11.53 0 21.23 2.2c9.7 2 17.5 10.12 17.5 10.12s-.8-1.2-1.8-3.02c-1-1.8.8-4.4.8-4.4s-2.7.5-5.8-.2c-3-.6-3.9-5.2-3.9-5.2s-2.8.5-6 .5-3.6-4.5-3.6-4.5-4.5 1.2-7.7-.2c-3.13-1.4-4.03-4-4.03-4zm-2.5 10.7c-24.1 0-39.4 22.62-39.4 22.62l9 3.1h-6.8s8.2 16.7 27.9 20c.7 1.4 1.8 3.5 3.4 4.8 2.6 2 7.6 3.7 7.6 3.7s-3.3-2.9-3.7-5c-.2-.9-.3-2-.3-2.9 1.6 0 3.3-.1 5.1-.3 28.33-2.7 32.43-17.7 41.13-17.7 8.8 0 21 10.6 21 10.6l-11-16.9 11-14.66c-1.6 1.66-8.1 8.76-19.1 8.76-12.5 0-21.9-15.76-45.98-15.76zm5.93 5c2.1.8 3.6 3.1 3.6 5.22 0 1.9-1.7 3.7-3.9 4.5 1.7-1.1 2.5-2.7 2.5-4.5 0-2.02-.6-4.12-2.2-5.22zm-18.03 1.3c5.2 2.62 7.6 10.12 7.6 16.82s-3 12.4-8.1 15.1c4-3.6 5.9-9 5.9-15.1 0-6.2-1.4-13.3-5.4-16.82zm-7.4 3.82c1.9 0 3.5 1.6 3.5 3.5s-1.6 3.5-3.5 3.5c-2 0-3.6-1.6-3.6-3.5s1.6-3.5 3.6-3.5zm34.03 1.2c2 .8 3.7 3.1 3.7 5.2 0 1.9-1.8 3.7-4 4.5 1.6-1.1 2.5-2.7 2.5-4.5 0-2-.5-4.1-2.2-5.2zm7.2 5.9c2.3.8 3.8 3.1 3.8 5.2 0 1.9-1.8 3.7-4 4.5 1.7-1.1 2.5-2.7 2.5-4.5 0-2-.5-4.1-2.3-5.2zm-16 1.1c2.1.8 3.6 3.1 3.6 5.2 0 1.9-1.7 3.7-3.9 4.5 1.7-1.1 2.5-2.7 2.5-4.5 0-2-.6-4.1-2.2-5.2zm7.9 6.2c2.1.8 3.7 3.1 3.7 5.2 0 1.9-1.8 3.7-3.9 4.5 1.6-1.1 2.4-2.7 2.4-4.5 0-2-.6-4.1-2.2-5.2zm-7.9 6.8c2.2.8 3.8 3.1 3.7 5.2.1 1.9-1.7 3.7-3.9 4.5 1.7-1.1 2.5-2.7 2.5-4.5 0-2-.6-4.1-2.3-5.2z",
            "ice": "m15.5 39h-1.6c6.9 6.64 6.6 11.74 10.1 19.64 2.9 6.4 5.8 11.6 10.5 15.1h-12.2c-1.5 0-2.9 1.3-2.9 2.9v.1c0 1.6 1.4 2.9 2.9 2.9h94.5c1.6 0 3-1.3 3-2.9v-.1c0-1.5-1.4-2.9-3-2.9h-26.4c.1-.7.2-1.4.2-2.1 0-8.9-7.4-16.1-16.5-16.1s-16.5 7.2-16.5 16.1c-1.6.7-3.3 1.3-5 1.5-4 .4-7.5-.9-10.5-2.8-5.4-3.3-9.1-8.6-11.5-14.2-1.6-3.8-3.8-7.3-6-10.8 1 1.1 2 2.3 2.9 3.5 2.8 3.2 4.6 7.1 6.8 10.7 2.1 3.7 5.2 6.8 8.9 9.1 3 1.8 6.8 2.2 10.2 2 1.1-.1 2.3 0 3.3-.4 2.2-3 .9-7.3-.4-10.1-.5-1.1-1-2.4-1.8-3.4-1.4.7-2.9 1.4-4.3 1.9 1-2.2 3.1-4.5 1.7-5.7-1.8-1.7-3.3-3.6-5.4-5-.9 1.5-1.7 3.1-2.7 4.4-.1-2.1-.1-4.3-.3-6.5-2.6-1.6-6.1-3.34-9.5-4.34-.6.2-.2 4.04-.5 5.74-.9-2.2-1.7-4.44-2.5-6.54-3.5-.80-11.1-1.7-15.5-1.7zm5.9 41.14c0 8.2 8.7 15.4 21.9 19.6h52.5c13.2-4.2 21.9-11.4 22-19.6h-96.4z"
          }[is];
          this.attachShadow({mode:"open"})
              .innerHTML = `<style>
                              path{fill:${color}}
                              svg{vertical-align:top}
                              svg:hover{background:var(--iconhovercolor,red)}
                            </style>
                            <svg viewBox="0 0 140 140"><path d="${d}" stroke="${color}"/></svg>`;
          this.onclick = (evt) => {
               console.log("You clicked me!", is, color);
          }
        }});
</script>
wydwbb8l

wydwbb8l3#

包含<style>元素的内联SVG会像任何其他附加样式表一样影响全局文档样式。
正如Paulo Fernando指出的那样
请参见以下示例也影响HTML元素

<svg xmlns="http://www.w3.org/2000/svg" width=100 viewBox="0 0 15 10">
    <path class="iconMain" d="M7.5 9l-6.5-4.2l0.5-0.9l6 4l6-4l0.5 0.9zm6.5-7.1l-0.5-0.9l-6 4l-6-4l-0.5 0.9l6.5 4.2z" />
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width=100 viewBox="0 0 15 10">
    <defs>
        <style>
            .iconMain {
                fill: #9cbacf;
            }
          p{
            color: red
          }
          body{
            background: #ccc
          }
          h1{
            color:green
          }
        </style>
    </defs>
    <path class="iconMain"
        d="M7.5 9l-6.5-4.2l0.5-0.9l6 4l6-4l0.5 0.9zm6.5-7.1l-0.5-0.9l-6 4l-6-4l-0.5 0.9l6.5 4.2z" />
</svg>

<h1>New Heading</h1>
<p>New paragraph</p>

用例一:圣像

常见做法:保持图标图形尽可能中性以便于样式化,例如更改每个示例的填充/描边颜色。
你可以从流行的图标库中获得灵感,比如fontAwesome,羽毛图标,材质图标等。
主要概念:将你的图标组织为<symbol>元素,并通过<use>元素创建示例。

svg{
  width:1em;
  border:1px solid #ccc;
}
<svg viewBox="0 0 15 10">
  <use href="#angle-double-down" fill="red"/>
</svg>

<svg viewBox="0 0 15 10">
  <use href="#angle-double-down" fill="green"/>
</svg>

<svg viewBox="0 0 15 10">
  <use href="#angle-double-down" fill="purple"/>
</svg>

<!-- hidden svg icon asset -->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 15 10" style="position:absolute; height:0; width:0;">
  <symbol id="angle-double-down">
    <path d="M7.5 9l-6.5-4.2l0.5-0.9l6 4l6-4l0.5 0.9zm6.5-7.1l-0.5-0.9l-6 4l-6-4l-0.5 0.9l6.5 4.2z" />
  </symbol>
</svg>

在某种程度上,您还可以使用外部<use>引用,如

<svg viewBox="0 0 15 10">
  <use href="icons.svg#angle-double-down" fill="green"/>
</svg>

然而,存在关于渐变、遮罩、剪辑路径等的一些限制或问题。(相关的“SVG忽略渐变样式”)。

用例二:具有预定义颜色的复杂SVG图形

并不总是需要操作SVG样式,例如,在显示复杂的矢量图时。
在本例中-只需使用引用SVG文件的<img>元素。
此文件也可以包含样式规则,但不会覆盖任何全局HTML元素样式。

<img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='100' viewBox='0 0 15 10'%3E%3Cdefs%3E%3Cstyle%3E .iconMain %7B fill: %239cbacf; %7D body %7B background: red; %7D %3C/style%3E%3C/defs%3E%3Cpath class='iconMain' d='M7.5,9,1,4.78789l.46713-.91645L7.5,7.85543l6.03287-3.984L14,4.78789ZM14,1.91646,13.53287,1,7.5,4.98349,1.46713,1,1,1.91646l6.5,4.2121Z' /%3E%3C/svg%3E" />

否则,使用本机Web组件可能是一个很好的替代方案,如下所述:“如何更改'svg'元素的颜色?“

相关问题