ianpoley
ianpoley

Reputation: 572

Creating an irregular border using an SVG clip-path

Ultimately what I'm trying to create is this:

enter image description here

I almost have it completely working, but there seems to be a problem with the SVG path I need to use for the clip-path. In this CodePen, when I use #unusual-border2 as the clip-path, it works. However, I need to use #unusual-border1, which is the correct SVG path as depicted in the above screenshot but it does not work.

Sample <path> element that works:

<path d="M0,0.25 0.4,0.05 0.55,0.2 0.6,0.15 0.75,0.25 1,0.1 1,1 0,1z" />

path element that I need to use:

<path d="M2049,6c0,188,0,376,0,564c-682.7,0-1365.3,0-2048,0C1,380.7,1,191.3,1,2c43.6,1.1,87.3,1.7,130.9,3.5
        c49.8,2.1,99.5,5.3,149.2,7.8c36.7,1.9,73.5,3.4,110.3,4.9c16.8,0.7,33.6,1.2,50.5,1.3c25,0.1,50,0,75-0.7
        c21.6-0.6,43.2-2.4,64.8-3.6c20.9-1.2,41.9-2.3,62.8-3.4c25.1-1.2,50.2-3.2,75.3-3.4c89-0.4,178-0.1,267-0.2
        c8.3,0,16.7-0.4,25-0.7c37.3-1.7,74.5-4,111.8-5.1c23.8-0.7,47.6,0.2,71.5,0.5c44.7,0.5,89.3,1.2,133.9,1.8c40,0.6,80,1.3,120,1.8
        c54.1,0.7,108.3,2.3,162.4,1.6c80.5-1,160.9-4.4,241.3-5.6c52.6-0.8,105.3,0.3,157.9,0.9C2023.4,3.7,2036.2,5.2,2049,6z"/>

What am I doing wrong?

Upvotes: 3

Views: 457

Answers (1)

Harry
Harry

Reputation: 89780

As explained in my earlier comment to the question, when clipPathUnits = "objectBoundingBox" is specified, the coordinates should be provided like a ratio (and so it cannot exceed 1) like in the sample that works.

<path d="M0,0.25 0.4,0.05 0.55,0.2 0.6,0.15 0.75,0.25 1,0.1 1,1 0,1z" />

In the above path definition, (0,0.25) would refer to the point represented by 0% on X-axis and 25% of the container's height on Y-axis. The path that doesn't work should also be modified to be like this (or) clipPathUnits = objectBoundingBox should be avoided. I would recommend the former because it is then easier to use the same clip-path for multiple elements of different sizes.

Converting your existing path into ratio based values can be done but the complexity becomes pretty high when there are lot of path commands (which your path has). All that you'd have to see is find out the max coordinate in both X & Y-axis and then divide all values by that number to get the ratio. In the path that was provided in question, the highest X coordinate was 2049 and that for Y coordinate was 564. So the point (0,188) should be converted as (0/2049, 188/564) which is approximately (0,0.33).

The below snippet has the original and converted paths. I've put it as a snippet just to use the expand or collapse feature. A demo of this path is available here.

<!-- Original Path -->
<path d="M2049,6
         c0,188 0,376 0,564
         c-682.7,0 -1365.3,0 -2048,0
         C1,380.7 1,191.3 1,2
         c43.6,1.1 87.3,1.7 130.9,3.5
         c49.8,2.1 99.5,5.3 149.2,7.8
         c36.7,1.9 73.5,3.4 110.3,4.9
         c16.8,0.7 33.6,1.2 50.5,1.3
         c25,0.1 50,0 75,-0.7
         c21.6,-0.6 43.2,-2.4 64.8,-3.6
         c20.9,-1.2 41.9,-2.3 62.8,-3.4
         c25.1,-1.2 50.2,-3.2 75.3,-3.4
         c89,-0.4 178-0.1 267-0.2
         c8.3,0 16.7,-0.4 25,-0.7
         c37.3,-1.7 74.5,-4 111.8,-5.1
         c23.8,-0.7 47.6,0.2 71.5,0.5
         c44.7,0.5 89.3,1.2 133.9,1.8
         c40,0.6 80,1.3 120,1.8
         c54.1,0.7 108.3,2.3 162.4,1.6
         c80.5,-1 160.9,-4.4 241.3,-5.6
         c52.6,-0.8 105.3,0.3 157.9,0.9
         C2023.4,3.7 2036.2,5.2 2049,6z" />

<!-- Converted Path -->
<path d="M1,0.01 
         c0,0.33 0,0.66 0,1 
         c-0.33,0 -0.66,0 -1,0 
         C0,0.675 0,0.339 0,0.003
         c0.021,0.001 0.042,0.003 0.063,0.006
         c0.024,0.003 0.048,0.009 0.072,0.013
         c0.017,0.003 0.035,0.006 0.053,0.008
         c0.008,0.001 0.016,0.002 0.024,0.002
         c0.012,0 0.024,0 0.036,-0.001
         c0.010,-0.001 0.021,-0.004 0.031,-0.006
         c0.010,-0.002 0.020,-0.004 0.030,-0.006
         c0.012,-0.002 0.024,-0.005 0.036,-0.006
         c0.043,0 0.086,0 0.130,0
         c0.004,0 0.008,0 0.012,0.001
         c0.018,-0.003 0.132,-0.007 0.054,-0.009
         c0.011,-0.001 0.023,0 0.034,0
         c0.021,0 0.043,0.002 0.065,0.003
         c0.019,0.001 0.039,0.002 0.058,0.003
         c0.026,0.001 0.052,0.004 0.079,0.002
         c0.039,-0.001 0.078,-0.007 0.117,-0.010
         c0.025,-0.001 0.051,0 0.077,0.001
         C0.987,0.006 0.993,0.009 1,0.010z" />


Though the above clip-path works, there are few things that I personally don't like about it and they are:

  • A large number of path commands are used. It may make the curves more gracious or aesthetic but editing/maintaining them would be a pain.
  • There is a mixture of absolute (C) and relative (c) commands. In my opinion, it is better to avoid a mixture. I think this one may have been generated by a tool.

So, I've created a simpler version of the same path and it is available in the below snippet. This is just a personal choice and you can choose whichever you like.

The SVG path commands are pretty simple to understand. In this snippet, we are using the following:

  • M - Move imaginary pen to point (absolute) represented by the coordinates provided next to it.
  • C - Draw a bezier curve where the first two sets of coordinates are control points for the curve and the third set is the end point of the curve.

You can read more about each command and their syntax in this MDN article.

body{
  background: url(http://lorempixel.com/800/800/people/3);
  padding: 0;
  margin: 0;
}  
.container {
  position: relative;
  height: calc(99.75vh - 50px);
  width: 100%;
  margin-top: 50px;
  -webkit-clip-path: url(#clipper);
}
.lightblue,
.navyblue {
  position: absolute;
  height: 100%;
  padding-top: 20px;
}
.lightblue {
  width: 65%;
  background: lightblue;
}
.navyblue {
  left: 65%;
  width: 35%;
  background: navy;
}
<div class='container'>
  
  <div class='lightblue'>content</div>
  <div class='navyblue'>content</div>
</div>
<svg width="0" height="0">
  <defs>
    <clipPath id='clipper' clipPathUnits='objectBoundingBox'>
      <path d='M0,0.01 
               C0.05,0.01 0.2,0.04 0.25,0.04 
               C0.3,0.04 0.35,0.02 0.35,0.025 
               C0.355,0.0225 0.45,0.03 0.5,0.035
               C0.53,0.035 0.58,0.02 0.6,0.02
               C0.63,0.015 0.74,0.0275 0.75,0.03
               C0.78,0.032 0.925,0.0125 0.95,0.015
               C0.97,0.0125 1,0.025 1,0.025 L1,1 0,1z'/>
      </clipPath>
    </defs>
  </svg>

Upvotes: 4

Related Questions