0

When using primitiveUnits="objectBoundingBox" with a SVG filter and animating a child outside the bounding box, the representation of the filter jumps when the animation is done. In the example below this is shown by the gap between the two boxes (one is a clone of the other).

Is there a way to prevent this and enforce overflow:none?

(There is no jump, as the animation is inifinite. To test, remove the id #animate: The two boxes will then be next to one another.)

#container {
  filter: url(#offset);
  width: 120px;
  height: 80px;
  border: 1px solid #000;
  overflow: hidden;
}

#animate {
    animation: move_in 3s linear reverse infinite;
}

@keyframes move_in {
    100% {
        transform: translateX(-50%);
    }
}

svg {
  display: none:
}
<div id="container">
  <div id="animate" >Test</div>
  <div>Test 2</div>
</div>

<svg xmlns="http://www.w3.org/2000/svg">
    <filter id="offset" primitiveUnits="objectBoundingBox" width="200%" height="100%" x="0" y="0" color-interpolation-filters="sRGB">
        <feOffset      result="SourceGraphicOffset"   in="SourceGraphic"  dx="1" dy="0" />
        <feMerge>
            <feMergeNode in="SourceGraphic" />
            <feMergeNode in="SourceGraphicOffset" />
        </feMerge>
    </filter>
</svg>

EDIT: Added two screenshots depicting snippet (as some browsers seem to displaying it differently).

With running animation (with gap): With running animation (with gap)

Without animation (without gap): Without animation (without gap)

sqwk
  • 2,649
  • 1
  • 28
  • 42
  • I'm really not sure what I'm supposed to be seeing (or not) here. I've tried Firefox and Chrome on a Mac and removing the animate just stops the animation. – Robert Longson Mar 12 '18 at 18:50
  • I added two screenshots that show the gap that the animation creates. Running on Chrome on a Mac — Safari breaks and overlays both rectangles; Firefox is rendering like it is supposed to be. Note that I am tied to Chrome as everything is running inside Electron. – sqwk Mar 12 '18 at 19:00

1 Answers1

0

Just found out that the same can be achieved using viewBox, essentially providing the feOffsetNode with the a similar relative size as the objectBoundingBox previously. (Thanks to this answer: svg viewBox attribute)

#container {
  filter: url('#offset');
  width: 120px;
  height: 80px;
  border: 1px solid #000;
  overflow: hidden;
}

#animate {
    animation: move_in 3s linear reverse infinite;
}

@keyframes move_in {
    100% {
        transform: translateX(-50%);
    }
}

svg {
  display: none:
}
<div id="container">
  <div id="animate" >Test</div>
  <div>Test 2</div>
</div>

<svg xmlns="http://www.w3.org/2000/svg">
    <filter id="offset" viewBox="0 0 120 80" width="200%" height="100%" x="0" y="0" color-interpolation-filters="sRGB">
        <feOffset result="SourceGraphicOffset" in="SourceGraphic" dx="120" dy="0" />
        <feMerge>
            <feMergeNode in="SourceGraphic" />
            <feMergeNode in="SourceGraphicOffset" />
        </feMerge>
    </filter>
</svg>
sqwk
  • 2,649
  • 1
  • 28
  • 42