CSS中的遮罩分层

时间:2018-09-01 09:04:48

标签: css svg less mask bem

我试图找出CSS中是否可能使用图层蒙版。基本上,我有一个表示某种阶段的SVG。使用mask-image将其显示为mask,并且具有黑色背景色。类似于:

mask-image: url(image.svg);
background-color: #000;
...

根据某些相关状态,我需要通过在其上分层放置另一个svg(例如,带有感叹号)来提请注意该被屏蔽的svg。它可能会有另一种颜色,例如红色,但可能会根据情况而改变。

下面显示了一个粗略的示例,其中有一个带有一些文本的按钮。正方形是svg,仅当存在某些状态(状态A)时才会出现,在这种情况下,将一个类添加到div中。正方形内的圆是相关状态,并且仅在正方形是状态A为真以及一些其他状态时才显示。因此,在Less / BEM结构中,这种额外的状态将被实现为修饰符,例如:

&__state {
  mask-image: url(state.svg);
  background-color: #000;
  ...

  &--inner-state {
    mask-image: url(inner-state.svg);
    background-color: red;
    ...
  }
}

enter image description here

该按钮对svgs一无所知,因为我根据状态动态添加div和上述CSS。

这在CSS中容易实现吗?如前所述,我正在使用带有BEM结构的Less,但是我不一定需要与此相关的答案。我对这个概念更感兴趣。

如有需要,随时询问更多信息,我们将不胜感激!

2 个答案:

答案 0 :(得分:1)

如果我正确理解了您的问题,则可以将多余的覆盖svg放置为<img>或内联<svg>,如下所示:

.masked{
  width: 100px;
  position: relative;
}
.masked img{
  width: 100%;
  -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg'><circle cx='50' cy='50' r='50' fill='#fff'></circle></svg>") top left / cover;
  mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg'><circle cx='50' cy='50' r='50' fill='#fff'></circle></svg>") top left / cover;
}

.masked svg{
  width: 100%;
  position: absolute;
  top: 0;
  opacity: 0;
}

.masked:hover svg{
  opacity: 1;
}
<div class="masked">
  <img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/Harry-Potter-1-.jpg" />
  <svg viewBox="0 0 100 100">
    <rect x="25" y="25" width="50" height="50" fill="red"></rect>
  </svg>
</div>

答案 1 :(得分:1)

(发布另一个答案,因为这超级不一样)

演示:

(理想情况下,您应该先阅读说明,但是如果您想先看到最终结果...)

前端:https://codepen.io/devanshj/pen/OomRer

后端:https://glitch.com/edit/#!/mature-teller?path=server.js:8:0

说明:

直到我遇到本文Coloring SVGs in CSS Background Images ...

时,我才无法理解您要使用这些蒙版和背景(而不是直接的svgs)实现什么。

本文中的解决方案对您不起作用的原因是,您需要多个彩色svg(并且本文中的解决方案仅适用于单个svg)

结合本文所要解决的问题和最终目标,我将重新设计这个问题:

  1. 我要在一个元素上具有多个svg背景
  2. 我也想控制每个svg的颜色
  3. 仅CSS解决方案。您不允许更改html。

这几乎是不可能的。我说“很漂亮”,因此有可能(使用超乎寻常的解决方案)。

几乎不可能的部分是给svg上色。仅使用CSS的多个svg背景很简单。

但是,如果我做了一些从URL本身为svg着色的事情,例如url(my-icon.svg?fill=#f00),如果可以,那么您的问题就可以解决了,我们可以这样做:

.icon-a{
    background-image: url("a.svg?fill=%23000"); // # encoded to %23 so that server doesn't think #000 is the hash part of the request

    &.icon-b{
        background-image: url("a.svg?fill=%23000"), url("b.svg?fill=%23fff");

        &:hover{
            background-image: url("a.svg?fill=%23000"), url("b.svg?fill=%23f00");
        }
    }
}

这可以通过一些服务器代码来完成(这里使用express和nodejs,也可以为其他语言/框架编写类似的代码):

app.get("/icons/*.svg", async (req, res) => {
    let svgCode = await readFileAsync(path.join(__dirname, req.path), {encoding: "utf8"});
    svgCode = svgCode.replace(/{{queryFill}}/g, req.query.fill);
    res.set("Content-Type", "image/svg+xml");
    res.send(svgCode);
});

和svg:

<svg xmlns="http://www.w3.org/2000/svg">
    <style>
        .query-fill{
            fill: {{queryFill}};
        }
    </style>
    <rect x="0" y="0" width="100" height="100" class="query-fill"></rect>
</svg>

替代:

如果您允许我更改html,则通过使用内联svg和<use>,该解决方案将变得非常简单。但是我想您只想使用css解决方案...

PS:如果您想知道是否有没有服务器代码的解决方案?不。

PPS:如果重新构造的问题不是您想要的,那么仅使用CSS便无法找到您想要的东西(分层蒙版)。