songololo
songololo

Reputation: 4954

How to apply SVG clip path relative to origin SVG instead of target element

I am trying to apply an SVG clipPath to a separate background div which has fixed positioning. I would like the clip-path to remain at the exact location of the origin SVG element, and to accordingly move when scrolling (or otherwise transformed).

What is happening instead, is that the clip path is inserted relative to the target element's origin and loses all positioning, scrolling, and transforms. Is there a way to preserve origin properties and apply these to a separate div?

In the embedded snippet below, the blue circle is where I would like the clip-path to be, whereas the red circle is where it is showing up.

#container {
  clip-path: url(#myClip);
  position: fixed;
  width: 100vw;
  height: 100vh;
  background-color: red;
}

#offset-container {
  position: absolute;
  top: 200px;
  left: 200px;
  width: 200px;
  height: 200px;
  border-style: solid;
  border-color: blue;
}
<div id='container'>

</div>

<div id='offset-container'>
  <svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg">
  <defs>
    <clipPath id="myClip">
      <circle cx="50%" cy="50%" r="50%"/>
    </clipPath>
  </defs>
  <circle cx="50%" cy="50%" r="50%" fill='blue' fill-opacity='0.5'/>
</svg>
</div>

JSFiddle: https://jsfiddle.net/shongololo/pa0qLs45/1/

Upvotes: 0

Views: 785

Answers (1)

ccprog
ccprog

Reputation: 21811

This works (almost) in Firefox, but not in Chrome, where it shows a really strange bug.

You'll need two divs: The outer is positioned relative and defines the clip-path so it moves. The inner is positioned fixed. Apparently, the explicit setting of top/left/width/height is needed and then refers to viewport coordinates.

body { margin: 0 }

#container {
  position: relative;
  overflow: hidden;
  top: 202px; /* border! */
  left: 202px;
  clip-path: url(#myClip);
  width: 200px;
  height: 200px;
}

#fixed {
  position: fixed;
  top: 0px;
  left: 0px;
  width: 100vw;
  height: 100vh;
  background-color: red;
}

#offset-container {
  position: absolute;
  top: 200px;
  left: 200px;
  width: 200px;
  height: 200px;
  border: 2px solid blue;
}
<div id='container'>
    <div id="fixed"></div>
</div>

<div id='offset-container'>
  <svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg">
  <defs>
    <clipPath id="myClip">
      <circle cx="50%" cy="50%" r="50%"/>
    </clipPath>
  </defs>
  <circle cx="50%" cy="50%" r="50%" fill='blue' fill-opacity='0.5'/>
</svg>
</div>

Upvotes: 1

Related Questions