Emma Andersson
Emma Andersson

Reputation: 21

How can i "crop" the svg to fit the shape of the parent?

How can i "crop" the svg filter to fit the shape of the parent?

Right now I have a div as a circle, with an svg in it. But the svg filter creates an rectangel.

Edit: I tried to implement a wrapping div with border-radius:100% as suggested below, but then it removes the blur.

original codepen

updated codepen with wrapping div

svg{
  width:100%; 
  height: 100%;  

}
.custom-cursor {
  border-radius: 50%;
  overflow: hidden; 
  width: 20px;
  height: 20px;
    background-image: conic-gradient( cyan, magenta, yellow, cyan); 
  filter: blur(5px) url("#blur-plus-grain");
}
<div class="custom-cursor">
  <svg preserveAspectRatio="none">
    <filter id="blur-plus-grain">
      <feGaussianBlur stdDeviation="0.8" result="blur" />
      <feTurbulence type="fractalNoise" numOctaves="26" baseFrequency="40" stitchTiles="stitch" result="grain" />
      <feComposite operator="in" in="blur" in2="grain" />
    </filter>
    <circle fill="transparent" r="10" cx="50%" cy="50%" filter="url(#blur-plus-grain)" />
  </svg>

</div>

without the filter

with filter

Upvotes: 2

Views: 572

Answers (1)

herrstrietzel
herrstrietzel

Reputation: 17240

You apply the svg noise-blur filter to your round gradient-filled div.
But there is still a css box context.

You actually need some padding to provide enough 'canvas' area. Otherwise any kind of blur might exceed for div elements boundaries:

cropped blur area

* {
  box-sizing: border-box;
}

svg {
  width: 100%;
  height: 100%;
}

.custom-cursor-clip {
  width: 50px;
  height: 50px;
  padding:2%;
  filter: url("#blur-plus-grain");
}
.custom-cursor {
  width: 100%;
  height: 100%;
  border-radius: 100%;
  background-image: conic-gradient(from 20deg, #003399, #74b4da, #e0bbd9);
}
<div class="custom-cursor-clip">
  <div class="custom-cursor">
    <svg preserveAspectRatio="none">
      <filter id="blur-plus-grain">
        <feGaussianBlur stdDeviation="4" result="blur" />
        <feTurbulence type="fractalNoise" numOctaves="26" baseFrequency="40" stitchTiles="stitch" result="grain" />
        <feComposite operator="in" in="blur" in2="grain" />
      </filter>
    </svg>
  </div>
</div>

Edit:
Essentially you apply the conic gradient to the inner div.
The wrapping/outer div provides some padding as well as the svg-filter.

Edit 2:

You might also use the <foreignObject> element for a more self-contained svg img asset:

    <svg  width="50" height="50" viewBox="0 0 100 100">
      <style>
        .conicGradient{
          width: 100%;
          height: 100%;
          border-radius: 100%;
          background-image: conic-gradient(from 20deg, #003399, #74b4da, #e0bbd9);
        }
      </style>
      <filter id="blur-plus-grain" filterUnits="userSpaceOnUse" >
        <feGaussianBlur stdDeviation="4" result="blur" />
        <feTurbulence type="fractalNoise" numOctaves="26" baseFrequency="40" stitchTiles="stitch" result="grain" />
        <feComposite operator="in" in="blur" in2="grain" />
      </filter>  
      <foreignObject filter="url(#blur-plus-grain)" 
      x="10" y="10" width="80" height="80">
        <div class="conicGradient" xmlns="http://www.w3.org/1999/xhtml" ></div>
      </foreignObject>
    </svg>

However, you still need some sort of padding/inner offset to prevent undesired cropping.

Upvotes: 1

Related Questions