Responsive clip-path with inline SVG

19,641

References to SVG clip paths are to the clip path definitions themselves and the dimensions or other attributes of the <svg> are meaningless in this context.

What is happening in your example is that you are applying a 4000 px wide clip path to your header. Which is probably only of the order of 900 px wide. So the curvature isn't visible.

If you want a responsive clip path, you should define it using clipPathUnits="objectBoundingBox".

#block-header {
    background: Red;
    min-height: 100px;
    -webkit-clip-path: url(#myClip);
	clip-path: url(#myClip);
}
<h1>SVG image</h1>
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100" viewBox="0 0 1 1" preserveAspectRatio="none"><path d="M0,0 1,0 1,0.9 C 1,0.9, 0.77,1, 0.5,1 0.23,1, 0,0.9,0,0.9z"/></svg>

<h1><code>clip-path</code> using the same SVG</h1>
<header id="block-header">
    <svg width="0" height="0">
        <defs>
          <clipPath id="myClip" clipPathUnits="objectBoundingBox">
            <path d="M0,0 1,0 1,0.9 C 1,0.9, 0.77,1, 0.5,1 0.23,1, 0,0.9,0,0.9z"/>
          </clipPath>
        </defs>
    </svg>
</header>    

Fiddle here

Share:
19,641

Related videos on Youtube

spliter
Author by

spliter

Front–end developer with craving for perfectionism.

Updated on June 04, 2022

Comments

  • spliter
    spliter almost 2 years

    On an element with a background (image or solid color don't really matter):

    <header id="block-header"></header>
    

    I am trying to apply a clip-path using SVG. To achieve this, I am putting SVG inline into the same element like this:

    <header id="block-header">
        …
        <svg width="100%" height="100%" viewBox="0 0 4000 1696" preserveAspectRatio="none">
            <defs>
              <clipPath id="myClip">
                <path d="M0 1568.18V0h4000v1568.18S3206.25 1696 2000 1696C984.37 1696 0 1568.18 0 1568.18z"/>
              </clipPath>
            </defs>
        </svg>
        …
    </header>
    

    You can run the code snippet below or check the JSFiddle. You can see original SVG image (in black) put inline, having curviness along the bottom and being responsive. In contrast, the red rectangle shows the same image applied (or, rather, not applied) as a clip-path.

    I guess I misunderstand either viewBox or preserveAspectRatio attributes though can not find what is exactly wrong here. Any help would be appreciated.

    #block-header {
        background: Red;
        min-height: 100px;
        -webkit-clip-path: url(#myClip);
    	clip-path: url(#myClip);
    }
    <h1>SVG image</h1>
    <svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100" viewBox="0 0 4000 1696" preserveAspectRatio="none"><path d="M0 1568.18V0h4000v1568.18S3206.25 1696 2000 1696C984.37 1696 0 1568.18 0 1568.18z"/></svg>
    
    <h1><code>clip-path</code> using the same SVG</h1>
    <header id="block-header">
        <svg width="100%" height="100" viewBox="0 0 4000 1696" preserveAspectRatio="none">
            <defs>
              <clipPath id="myClip">
                <path d="M0 1568.18V0h4000v1568.18S3206.25 1696 2000 1696C984.37 1696 0 1568.18 0 1568.18z"/>
              </clipPath>
            </defs>
        </svg>
    </header>
  • spliter
    spliter about 9 years
    Worked like a charm, Paul! Thank you very much for the explanation!
  • kmgdev
    kmgdev almost 9 years
    From what I can tell, this only works if a) you're using a <path> element, and b) you're not drawing any diagonal lines beyond a triangle. <circle>, <polygon>, etc. will not work with the clipPathUnits="objectBoundingBox" attribute, and any diagonal lines beyond a triangle will be filled into a square. Bummer.
  • Paul LeBeau
    Paul LeBeau almost 9 years
    Circle, polygon etc will work just fine. What I suspect you are doing is using values that are too large. When using clipPathUnits="objectBoundingBox" coordinates should be in the range of 0..1. Think of them as percentages of the bounding box. (0,0) is top-left corner of the element, (1,1) is the bottom right corner of the element.
  • Jordi Nebot
    Jordi Nebot over 7 years
    But, how do you transform d="M0 1568.18V0h4000v1568.18S3206.25 1696 2000 1696C984.37 1696 0 1568.18 0 1568.18z" into d="M0,0 1,0 1,0.9 C 1,0.9, 0.77,1, 0.5,1 0.23,1, 0,0.9,0,0.9z"? Thank you!
  • Paul LeBeau
    Paul LeBeau over 7 years
    You scale the original clip coordinates by the viewBox. So 1568/1696 ~= 0.9 etc. However, my clip-path is only an approximation of the original one. It's not exact.
  • Roko C. Buljan
    Roko C. Buljan about 7 years
    The SVG with defs should be outside of the header... this way is totally confusing and does not hints on reusability.
  • giovannipds
    giovannipds over 6 years
    There's an EXCELLENT script to convert this data here: stackoverflow.com/a/29509756/842768
  • alboth - undkonsorten.com
    alboth - undkonsorten.com over 5 years
    Worked fine with Sketch: Just resizing the Object to 1px, Export, Copy Path, add clipPathUnits="objectBoundingBox", Done.
  • Gavin Kemp
    Gavin Kemp about 3 years
    I found this online tool that you enter path coordinates into and it will convert it to the fraction/decimal based system needed for objectBoundingBox - yoksel.github.io/relative-clip-path
  • joshmillgate
    joshmillgate about 3 years
    @GavinKemp YOU ARE A LIFE SAVER THANK YOU FOR THIS LINK