1

I have an image, and I need to clip it using an SVG path. It works okay with defined image sizes like 688px x 800px, but my problem is that I would ideally like this to be responsive. I've already tried to get it to work using preserveAspectRatio but no luck yet (you can find this code at the bottom of the question). I've not done this sort of thing much before so any help would be greatly appreciated.

Just to clarify, when I say responsive I would like it to be a bit more fluid with the screen size, rather than cutting of straight edges etc.

Edit: I've tried to place the image inside an SVG element but it just doesn't work right at all, I can't see how to make this idea responsive either - https://jsfiddle.net/g80unhyq/

This is at the dimensions I've listed above How the mask looks at full size

And this is how it looks as responsiveness kicks in

How the mask looks as responsiveness kicks in

I have an example of what I've done so far on Tailwind's playground - https://play.tailwindcss.com/fRq1Cv6OqP?file=css

HTML:

<div class="image-container">
  <img src="https://images.unsplash.com/photo-1691687824517-a62cfdef9c6e?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1367&q=80" alt="Your Image" class="masked-image" />
</div>

CSS:

.image-container {
    position: relative;
    width: 688px;
    height: 800px;
}

.masked-image {
    width: 100%;
    height: 100%;
    object-fit: cover;
    clip-path: path('{{ Same path data as the Tailwind link above, StackOverflow just has a character limit. }}');
}

As mentioned above, I also tried to get this to work in a slightly different way:

HTML:

<div class="image-container">
  <img src="https://images.unsplash.com/photo-1691687824517-a62cfdef9c6e?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHx" />

  <svg preserveAspectRatio="xMidYMid slice" xmlns="http://www.w3.org/2000/svg">
    <defs>
      <clipPath id="svg-mask">
        <path
          d="{{ Same path data as the Tailwind link above, StackOverflow just has a character limit. }}"/>
      </clipPath>
    </defs>
  </svg>
</div>

CSS:

.image-container img {
  clip-path: url(#svg-mask);
}

But still no luck

Andy Holmes
  • 7,817
  • 10
  • 50
  • 83
  • prefer to put your image and clip-path in a SVG element, then you can adjust a responsive size with css.. – Mister Jojo Aug 18 '23 at 17:26
  • 1
    I tried playing around with this in code, but I couldn't get it either. I found [this question](https://stackoverflow.com/questions/50449655/how-can-i-scale-clip-path-area-in-css) but in the end I couldn't get it to work in this case. I don't know why the downvotes either, SO is strange like that sometimes. I sent an upvote your way to help even it out! – Chris Barr Aug 18 '23 at 17:27
  • @MisterJojo Thank you, but I tried that and it just produced a black SVG without masking, the only way it seemingly works is with a clip-path of sorts. As I've said in the post, this is pretty new for me, so I may still be doing things wrong but I'm trying – Andy Holmes Aug 18 '23 at 17:30
  • Thanks for trying @ChrisBarr, and thank you for the vote too. I'll take a look at that link and see if I'm able to hack something together. This is something I want to get better at but it's quite alien to me at the minute – Andy Holmes Aug 18 '23 at 17:32
  • @MisterJojo Tried it again, still doesn't work at all - https://jsfiddle.net/g80unhyq/ – Andy Holmes Aug 18 '23 at 17:46
  • related: https://stackoverflow.com/q/60491855/8620333 – Temani Afif Aug 18 '23 at 19:02
  • Also related: ["Complex SVG clip-path responsive"](https://stackoverflow.com/questions/48055893/complex-svg-clip-path-responsive#48075809) ["Problem with CSS SVG Clip path - not working"](https://stackoverflow.com/questions/71286372/problem-with-css-svg-clip-path-not-working/) – herrstrietzel Aug 21 '23 at 23:49

1 Answers1

3

Pack your image in an SVG <image> tag inside a <svg> with the viewBox dimensions that work. Then, the responsive nature of the <svg> will take care of resizing both image and clip path.

Unfortunately your clip path definition is much too large to pack into an answer here. The following snippet uses a rough approximation instead.

body {
  margin: 0;
  width: 100vw;
  height: 100vh;
  overflow: hidden;
}
.image-container {
  width: 100%;
  height: 100%;
}
.masked-image {
  width: 688px;
  height: 800px;
  clip-path: url(#clip);
}
<svg class="image-container" viewBox="0 0 688 800">
  <clipPath id="clip">
    <path d="M32.68 281.4C32.71 281.41 32.67 281.37 32.68 281.4ZM18.51 605.1C20.15 600.74 19.22 606.84 18.52 605.1M20.05 581.2C20.87 563.79 25.5 581.24 20.06 581.19M21.01 597.42C21.31 596.92 21.41 597.85 21.01 597.42ZM26.73 554.49C26.65 554.15 27.07 554.6 26.73 554.49ZM30.03 551.76C30.29 551.6 30.05 552.07 30.03 551.76ZM31.08 545.67C32.48 544.5 31.86 547.49 31.07 545.68M35.9 540.28C36.38 539.61 36.38 540.74 35.9 540.29M36.36 537.42C39.92 537.94 37.07 540.65 36.37 537.42M49.62 322.43C49.68 321.98 49.83 322.67 49.62 322.42M262.17 666.05C279.96 654.53 306.42 663.91 323.62 662.83 351.29 663.22 298.63 674.94 288.14 685.37 290.32 683.48 286.28 689.6 281.41 692.13 281.22 692.89 272.28 705.22 272.61 691.12 270.06 682.4 266.87 673.92 262.19 666.06M300.61 676.74C310.77 673.91 298.28 683.44 300.61 676.74ZM288.11 765.66C288.91 765.06 289.45 767.46 288.11 765.66ZM445.37 696.69C445.18 696.78 445.18 696.78 445.37 696.69ZM555.56 749.05C558.88 747.82 556.84 752.66 555.56 749.05ZM572.43 764.47C581.23 765.02 576.05 772.49 572.43 764.47ZM8.78 614.66C8.58 614.89 8.68 614.36 8.78 614.66ZM.04 633.28C9.22 646.18 12.58 607.11 18.46 616.12 24.03 622.62 18.81 635.39 15.8 645.03 22.45 658.99 65.17 649.53 85.23 653.02 125.76 655.55 167.06 651.62 207.05 659.3 222.39 674.57 254.91 653.23 261.82 668.72 279.34 691.13 264.63 712.33 268.22 743.53 271.56 756.68 288.95 770.18 276.71 760.25 289.5 775.39 327.29 779.96 351.54 786.63 385.16 794.26 344.19 781.85 334.28 781.16 315.08 774.89 297.46 774.23 281.91 761.01 259.37 743.69 265.93 705.43 286.7 691.78 294.45 681.78 303.96 681.08 314.48 674.29 328.61 668.76 335.11 667.14 347.36 663.5 359.24 653.89 381.97 679.59 373.8 665.6 387.9 670.94 401.97 666.39 402.61 667.91 416.23 673.73 390.75 659.53 413.55 664.98 433.4 667.26 481.06 662.33 445.71 686.98 432.41 695.16 425.73 753.4 440.45 716.67 438.08 700.78 453.97 696.1 466.01 677.96 488.79 665.99 442.81 708.93 458.72 724.79 459.3 739.27 455.03 767.11 461.27 738.02 454.98 710.42 463.93 669.84 496.47 671.67 512.5 692.5 525.8 721.34 543.64 733.57 542.8 740.72 554.83 745.46 551.49 748.97 542.34 744.29 570.61 756.3 557.48 755.33 565.4 756.07 573.9 772.08 578.73 769.77 579.94 780.73 589.17 777.21 589.67 785.59 601.83 799.7 606.59 803.75 594.44 783.09 593.98 787.61 586.4 773.49 581.07 773.11 582.53 768.01 563.77 756.41 558.91 750.24 555.59 745.11 548.06 737.98 547.54 736.55 539.05 730.54 536.29 719.98 531.69 718.28 529.24 699.9 479.21 666.91 520.83 671.22 534.4 662.72 553.09 682.4 550.62 673.24 558.49 678.75 560.97 672.99 567.71 671.33 573.19 667.41 581.58 672.43 585.66 671.92 580.5 667.85 593.6 665.59 605.82 666.52 613.89 666.92 609.33 660.34 622.11 662.27 618.53 661.93 605.65 663.86 611.75 657.02 603.79 654.64 609.64 651.44 610.44 653.1 611.57 651.17 605.69 651.24 611.73 649.79 604.79 647.54 612.55 648.42 611.94 645.91 611.07 643.34 607.14 643.11 612.21 640.53 610.91 639.03 611.88 638.26 611.64 636.95 613.44 640.33 613.11 634.38 612.05 633.09 611.38 627.01 610.78 628.68 611.57 623.47 607.73 623.97 613.17 621.6 608.98 618.39 615.98 620.15 611.8 608.95 612.64 604.94 608.34 598.08 610.68 599.01 619.85 598.6 616.3 600.71 609.75 592.56 609.02 592.47 620.08 592 605.28 589.84 609.22 588.31 607.93 587.68 608.55 581.84 608.88 583.26 608.29 581.76 608.08 578.04 609.08 579.24 606.64 579.13 611.13 575.96 609.61 575.78 609.42 572.6 609.75 575.13 611.29 571.75 608.04 569.17 611.33 565.16 608.54 563.59 614.1 562.62 605.81 559.27 610.29 558.9 607.63 555.5 611.77 552.7 610.85 546.29 610.52 539.59 608.92 536.36 610.87 531.59 609.72 527.87 610.27 519.77 611.09 511.46 617.64 477.05 621.31 534.96 642.73 536.28 653.69 554.8 712.32 551.47 667.53 547.17 641.93 538.15 618.75 516.36 617.79 487.75 620.12 469.53 612.24 452.75 614.75 434.54 615.54 412.61 615.12 396.59 618.36 377.9 623.44 393.4 619.4 368.04 616.6 356.89 618.68 342.01 622.85 342.38 621.36 330.6 627.01 311.18 617.45 318.68 623.1 306.02 613.12 319.84 622.54 267.61 622.59 256.81 629.21 244.4 622.76 226.51 626.34 212.38 623.08 193.9 626.11 173.98 628 166.1 632.39 159.97 627.05 157.08 625.02 151.07 620.53 145.88 620.28 134.79 624.55 134.58 623.6 123.99 629.28 107.89 626.42 94.46 633.83 80.49 623.55 71.69 628.42 56.35 628.7 54.52 636.58 78.31 630.37 53.68 624.28 40.79 639.82 23.08 612.93 28.73 421.72 19.15 230.52 9.58 39.31 0 58.39 6.15 29.03 2.38 44.56 7.88 27.55 5.23 49.84 26.2 39.09 21.73 38.03 27.29 46.41 32.05 34.11 34.51 7.01 37.07 27.44 33.19 41.28 37.49 29.53 48.91 64.06 50.19 38.22 49.41 49.71 53.23 33.78 53.23 42.87 57.15 31.59 55.75 49.02 64.68 39.14 64.19 39.96 69.86 40.2 71.1 41.68 73.86 33.83 73.46 40.8 85.07 37.19 81.18 35.14 81.89 35.12 89.59 38.15 96.48 43.18 100.39 29.27 109.76 48.4 109.88 19.6 106.98 62.65 118.37 35.82 118.86 35.8 127.18 36.14 137.57 35.68 146.53 52.47 153.47 20.13 161.79 46.95 165.76 47.38 168.24 29.66 160.83 36.49 170.26 39.82 175.16 55.66 174.05 35.19 175.74 38.64 181.06 33.29 185.66 33.83 195.84 57.28 202.69 8.52 222.93 27.93 215.16 43.38 205.94 42.82 220.4 37.08 219.76 47.38 215.15 53.11 230.47 44.51 231.37 27.55 234.33 36.83 245.04 42.01 244.13 19.53 241.78 46.5 264.66 33.54 260.07 37.07 264.29 51.06 259.35 32.18 263.5 54.77 263.49 22.86 267.71 33.95 273.75 41.06 274.81 25.9 285.06 39.65 281.24 42.78 283.12 46.28 284.9 42.52 289.8 26.74 305.08 45.73 298.29 43.29 295.27 53.53 282.75 50.48 297.89 50.26 308.04 36.76 316.96 48.85 329.91 48.3 340.66 41.98 350.62 57.45 380.01 37.47 366.76 23.73 357.38-3.29 353.92 27.48 364.68 39.69 372.15 52.28 372.44 34.7 373.27 55.51 368.38 49.38 407.23 32.62 387.17 31.22 358.83 24.02 402.11 43.49 394.78 52.01 399.58 47.9 426.8 29.95 412.41-3.58 403.96 17.89 415.51 39.02 417.95 52.31 419.56 43.45 437.93 45.34 448.38 32.04 447.99 2.69 453.45 33.56 452.59 49.85 444.6 50.26 475.7 34.12 472.59 14.93 470.66 65.83 478.72 34.95 483.54 16.33 487.13 56.57 480.2 43.53 500.08 40.1 511.72 41.09 525.35 37.81 532.44 37.11 536.73-2.2 500.2 24.8 526.75 39.97 537.43 24.83 537.39 27.22 550.46 22.61 560.68 15.35 583.85 18.64 592.57-4.09 615.14 33.42 583.02 13.46 606.67 1.86 618.75 12.47 616.2.04 633.37" />
  </clipPath>
  <image href="https://images.unsplash.com/photo-1691687824517-a62cfdef9c6e?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1367&q=80" alt="Your Image" class="masked-image" />
</div>
ccprog
  • 20,308
  • 4
  • 27
  • 44
  • Thank you SO MUCH! This is absolutely spot on, I've adjusted it to use my clip path (I know, it is absolutely massive), but it works beautifully - https://play.tailwindcss.com/PYZIjamNKe - Thank you, I've learnt plenty from your answer – Andy Holmes Aug 18 '23 at 18:11
  • 1
    remove css `.masked-image {...}` and use ` – Mister Jojo Aug 18 '23 at 20:50
  • 1
    @MisterJojo All three attributes are [presentation attributes](https://www.w3.org/TR/SVG2/styling.html#PresentationAttributes), so you can do both. Which you choose is a matter of the semantics you want to present. As long as [geometry properties](https://www.w3.org/TR/SVG2/geometry.html) are used in CSS context, the units are needed. (Background is that CSS and SVG attributes use different parsers for values.) – ccprog Aug 18 '23 at 22:07