Search code examples
svgresizestretch

Can I get elements within an SVG to size proportionately and others to stretch disproportionally?


I am trying to get the red area to stretch disproportionately on the X axis (100% horizontal stretching with a fixed height) while keeping both the left and right ends fixed so the rounded edges and the die don't become distorted. How can I get this working?

Here's the image output:

Screenshot of SVG output

And here is the SVG code that generates it:

<svg viewBox="0 0 3550 1471" fill="none" xmlns="http://www.w3.org/2000/svg">
  <g clip-path="url(#clip0)">
    <g filter="url(#filter0_d)">
      <path d="M110.532 215.494C110.532 157.583 162.448 110.637 226.489 110.637C226.489 110.637 804.924 131.357 1738.56 131.357C2672.19 131.357 3243.07 110.637 3243.07 110.637C3307.11 110.637 3359.03 157.583 3359.03 215.494L3359.03 1175.29C3359.03 1233.2 3307.11 1280.15 3243.07 1280.15C3243.07 1280.15 2664.64 1259.43 1731.01 1259.43C797.372 1259.43 226.489 1280.15 226.489 1280.15C162.448 1280.15 110.532 1233.2 110.532 1175.29L110.532 215.494Z" fill="white"/>
    </g>
    <path d="M3223.7 921.19V1070.39C3223.7 1077.79 3219.44 1084.54 3212.75 1087.72L3093.94 1144.28C3091.33 1145.53 3088.5 1146.15 3085.67 1146.15C3082.85 1146.15 3080.02 1145.53 3077.41 1144.28L2958.59 1087.72C2951.91 1084.54 2947.65 1077.79 2947.65 1070.39V921.19C2947.65 917.345 2948.79 913.679 2950.84 910.595C2952.73 907.742 2955.38 905.388 2958.6 903.865L3077.41 847.298C3082.64 844.81 3088.71 844.81 3093.94 847.298L3212.75 903.865C3215.97 905.387 3218.62 907.742 3220.5 910.595C3222.55 913.679 3223.7 917.344 3223.7 921.19Z" fill="#E53935"/>
    <path d="M3085.67 974.787V1146.15C3082.85 1146.15 3080.02 1145.53 3077.41 1144.28L2958.59 1087.72C2951.91 1084.54 2947.65 1077.79 2947.65 1070.39V921.19C2947.65 917.345 2948.79 913.679 2950.84 910.595L3085.67 974.787Z" fill="#FFC700"/>
    <path d="M3223.7 921.19V1070.4C3223.7 1077.72 3219.52 1084.4 3212.95 1087.63C3212.89 1087.66 3212.82 1087.69 3212.75 1087.72L3093.94 1144.28C3091.33 1145.53 3088.5 1146.15 3085.67 1146.15V974.787L3220.5 910.595C3222.55 913.679 3223.7 917.344 3223.7 921.19Z" fill="#01CADE"/>
    <path d="M3175.67 1027.03C3176.83 1018.44 3172.64 1010.78 3166.3 1009.92C3159.96 1009.06 3153.89 1015.34 3152.72 1023.93C3151.56 1032.52 3155.76 1040.19 3162.09 1041.04C3168.43 1041.9 3174.5 1035.63 3175.67 1027.03Z" fill="#F1F1F1"/>
    <path d="M3048.19 1015.76C3054.54 1015.41 3059.31 1008.1 3058.83 999.437C3058.35 990.774 3052.82 984.034 3046.46 984.383C3040.11 984.733 3035.34 992.04 3035.82 1000.7C3036.3 1009.37 3041.84 1016.11 3048.19 1015.76Z" fill="#F1F1F1"/>
    <path d="M2982.29 1072.76C2988.65 1072.41 2993.41 1065.1 2992.93 1056.43C2992.46 1047.77 2986.92 1041.03 2980.56 1041.38C2974.21 1041.73 2969.45 1049.04 2969.92 1057.7C2970.4 1066.36 2975.94 1073.1 2982.29 1072.76Z" fill="#F1F1F1"/>
    <path d="M3030.63 918.135C3039.3 917.658 3046.04 912.121 3045.69 905.767C3045.34 899.413 3038.03 894.649 3029.37 895.126C3020.7 895.603 3013.96 901.141 3014.31 907.494C3014.66 913.848 3021.97 918.612 3030.63 918.135Z" fill="#F1F1F1"/>
    <path d="M3085.02 891.226C3093.69 890.749 3100.43 885.211 3100.08 878.858C3099.73 872.504 3092.42 867.74 3083.76 868.217C3075.09 868.694 3068.35 874.231 3068.7 880.585C3069.05 886.939 3076.36 891.703 3085.02 891.226Z" fill="#F1F1F1"/>
    <path d="M3142 920C3150.67 919.523 3157.41 913.985 3157.06 907.632C3156.71 901.278 3149.4 896.514 3140.74 896.991C3132.07 897.468 3125.33 903.005 3125.68 909.359C3126.03 915.713 3133.34 920.477 3142 920Z" fill="#F1F1F1"/>
    <path d="M3088.89 944.989C3097.55 944.512 3104.29 938.974 3103.94 932.62C3103.59 926.267 3096.29 921.503 3087.62 921.98C3078.96 922.457 3072.22 927.994 3072.57 934.348C3072.92 940.702 3080.23 945.466 3088.89 944.989Z" fill="#F1F1F1"/>
    <g filter="url(#filter1_i)">
    <path d="M0 604.921C0 588.905 12.9837 575.921 29 575.921H110.532V814.863H29C12.9837 814.863 0 801.88 0 785.863V604.921Z" fill="#F26267"/>
  </g>
  <path fill-rule="evenodd" clip-rule="evenodd" d="M354.359 649.227C383.729 649.227 407.538 625.417 407.538 596.047C407.538 566.677 383.729 542.867 354.359 542.867C324.988 542.867 301.179 566.677 301.179 596.047C301.179 625.417 324.988 649.227 354.359 649.227ZM354.359 637.632C377.2 637.632 395.717 619.115 395.717 596.274C395.717 573.432 377.2 554.916 354.359 554.916C331.517 554.916 313 573.432 313 596.274C313 619.115 331.517 637.632 354.359 637.632Z" fill="#F26267"/>
  <path fill-rule="evenodd" clip-rule="evenodd" d="M354.359 866.791C383.729 866.791 407.538 842.982 407.538 813.611C407.538 784.241 383.729 760.432 354.359 760.432C324.988 760.432 301.179 784.241 301.179 813.611C301.179 842.982 324.988 866.791 354.359 866.791ZM354.359 855.196C377.2 855.196 395.717 836.68 395.717 813.838C395.717 790.997 377.2 772.48 354.359 772.48C331.517 772.48 313 790.997 313 813.838C313 836.68 331.517 855.196 354.359 855.196Z" fill="#01CADE"/>
  <path fill-rule="evenodd" clip-rule="evenodd" d="M352.812 1078.96C382.182 1078.96 405.991 1055.15 405.991 1025.78C405.991 996.414 382.182 972.605 352.812 972.605C323.441 972.605 299.632 996.414 299.632 1025.78C299.632 1055.15 323.441 1078.96 352.812 1078.96ZM352.812 1067.37C375.653 1067.37 394.17 1048.85 394.17 1026.01C394.17 1003.17 375.653 984.653 352.812 984.653C329.97 984.653 311.453 1003.17 311.453 1026.01C311.453 1048.85 329.97 1067.37 352.812 1067.37Z" fill="#FFC700"/>
  </g>
  <defs>
    <filter id="filter0_d" x="0.531982" y="0.637085" width="3548.5" height="1469.51" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
      <feFlood flood-opacity="0" result="BackgroundImageFix"/>
      <feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
      <feOffset dx="40" dy="40"/>
      <feGaussianBlur stdDeviation="75"/>
      <feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0"/>
      <feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
      <feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
    </filter>
    <filter id="filter1_i" x="0" y="575.921" width="110.532" height="238.942" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
      <feFlood flood-opacity="0" result="BackgroundImageFix"/>
      <feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
      <feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
      <feOffset dx="-17"/>
      <feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
      <feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.18 0"/>
      <feBlend mode="normal" in2="shape" result="effect1_innerShadow"/>
    </filter>
    <clipPath id="clip0">
      <rect width="3550" height="1471" fill="white"/>
    </clipPath>
  </defs>
</svg>


Solution

  • The basic technique for this sort of situations is to play with the existence of viewBox attributes and percentage units. for your problem, some things work, others do not.

    • The outermost <svg> element gets no viewBox attribute. It will stretch as needed.
    • The white background is not a perfect rectangle in your code. For this to work out it has to be exchanged for a <rect> element. The reason is that now it can have width and height attributes of 100%, so that its size will change together with the enclosing <svg>. The rounded corners are sized by a rx attribute with a unitless number - effectively px units of the viewport the <svg> sits in. This ensures the corner is not distorted with changing aspect ratio.
    • The left side elements sit inside a nested <svg> element that has a viewBox attribute. Its default size is 100% for width and height, The viewbox size is chosen such that it encloses just the left-side elements and the height of the white rectangle. Its left side is flush with the white rectangle. Now this means the aspect ratio will not fit that of the <svg> element. To make sure the content stays on the left side and in the vertical middle, there is a preserveAspectRatio="xMinYMid meet".
    • The strategy for the right side is the same, just mirrored.

    Some extra care is to be used for content that ends up outside the <svg> elements. You need to set overflow: visible for them to be visible. Otherwise, the box borders of the <svg> element act as clip paths.

    • The filter drawing the shadow effect is rendered outside the white rectangle that fills the outermost <svg>. Therefore, you need to make space to display it, which I have solved here with a margin. (For the inner <svg> elements, the margin has no effect.)
    • The left-side red form is part of the left-side inner <svg>, but it sits outside its viewbox. This will not cut off its display as long as the overflow is made visible.
    • Another important detail is the units for the filter effects. With the removal of filterUnits="userSpaceOnUse" the value for this attribute falls back to objectBoundingBox. Together with the removal of the x, y, width and height attributes, this makes sure the filter will be applied no matter where or with which size its application ends up. You might need to still fiddle with the numbers to get sizes right.

    svg {
      margin: 50px;
      overflow: visible;
    }
    <svg width="650" height="234" xmlns="http://www.w3.org/2000/svg">
      <g filter="url(#filter0_d)">
          <rect width="100%" height="100%" rx="20" fill="white"/>
      </g>
      <svg viewBox="110 110 500 1170" preserveAspectRatio="xMinYMid meet">
        <g filter="url(#filter1_i)">
          <path d="M0 604.921C0 588.905 12.9837 575.921 29 575.921H110.532V814.863H29C12.9837 814.863 0 801.88 0 785.863V604.921Z" fill="#F26267"/>
      </g>
      <path fill-rule="evenodd" clip-rule="evenodd" d="M354.359 649.227C383.729 649.227 407.538 625.417 407.538 596.047C407.538 566.677 383.729 542.867 354.359 542.867C324.988 542.867 301.179 566.677 301.179 596.047C301.179 625.417 324.988 649.227 354.359 649.227ZM354.359 637.632C377.2 637.632 395.717 619.115 395.717 596.274C395.717 573.432 377.2 554.916 354.359 554.916C331.517 554.916 313 573.432 313 596.274C313 619.115 331.517 637.632 354.359 637.632Z" fill="#F26267"/>
      <path fill-rule="evenodd" clip-rule="evenodd" d="M354.359 866.791C383.729 866.791 407.538 842.982 407.538 813.611C407.538 784.241 383.729 760.432 354.359 760.432C324.988 760.432 301.179 784.241 301.179 813.611C301.179 842.982 324.988 866.791 354.359 866.791ZM354.359 855.196C377.2 855.196 395.717 836.68 395.717 813.838C395.717 790.997 377.2 772.48 354.359 772.48C331.517 772.48 313 790.997 313 813.838C313 836.68 331.517 855.196 354.359 855.196Z" fill="#01CADE"/>
      <path fill-rule="evenodd" clip-rule="evenodd" d="M352.812 1078.96C382.182 1078.96 405.991 1055.15 405.991 1025.78C405.991 996.414 382.182 972.605 352.812 972.605C323.441 972.605 299.632 996.414 299.632 1025.78C299.632 1055.15 323.441 1078.96 352.812 1078.96ZM352.812 1067.37C375.653 1067.37 394.17 1048.85 394.17 1026.01C394.17 1003.17 375.653 984.653 352.812 984.653C329.97 984.653 311.453 1003.17 311.453 1026.01C311.453 1048.85 329.97 1067.37 352.812 1067.37Z" fill="#FFC700"/>
      </svg>
      <svg viewBox="2860 110 500 1170" preserveAspectRatio="xMaxYMid meet">
        <path d="M3223.7 921.19V1070.39C3223.7 1077.79 3219.44 1084.54 3212.75 1087.72L3093.94 1144.28C3091.33 1145.53 3088.5 1146.15 3085.67 1146.15C3082.85 1146.15 3080.02 1145.53 3077.41 1144.28L2958.59 1087.72C2951.91 1084.54 2947.65 1077.79 2947.65 1070.39V921.19C2947.65 917.345 2948.79 913.679 2950.84 910.595C2952.73 907.742 2955.38 905.388 2958.6 903.865L3077.41 847.298C3082.64 844.81 3088.71 844.81 3093.94 847.298L3212.75 903.865C3215.97 905.387 3218.62 907.742 3220.5 910.595C3222.55 913.679 3223.7 917.344 3223.7 921.19Z" fill="#E53935"/>
        <path d="M3085.67 974.787V1146.15C3082.85 1146.15 3080.02 1145.53 3077.41 1144.28L2958.59 1087.72C2951.91 1084.54 2947.65 1077.79 2947.65 1070.39V921.19C2947.65 917.345 2948.79 913.679 2950.84 910.595L3085.67 974.787Z" fill="#FFC700"/>
        <path d="M3223.7 921.19V1070.4C3223.7 1077.72 3219.52 1084.4 3212.95 1087.63C3212.89 1087.66 3212.82 1087.69 3212.75 1087.72L3093.94 1144.28C3091.33 1145.53 3088.5 1146.15 3085.67 1146.15V974.787L3220.5 910.595C3222.55 913.679 3223.7 917.344 3223.7 921.19Z" fill="#01CADE"/>
        <path d="M3175.67 1027.03C3176.83 1018.44 3172.64 1010.78 3166.3 1009.92C3159.96 1009.06 3153.89 1015.34 3152.72 1023.93C3151.56 1032.52 3155.76 1040.19 3162.09 1041.04C3168.43 1041.9 3174.5 1035.63 3175.67 1027.03Z" fill="#F1F1F1"/>
        <path d="M3048.19 1015.76C3054.54 1015.41 3059.31 1008.1 3058.83 999.437C3058.35 990.774 3052.82 984.034 3046.46 984.383C3040.11 984.733 3035.34 992.04 3035.82 1000.7C3036.3 1009.37 3041.84 1016.11 3048.19 1015.76Z" fill="#F1F1F1"/>
        <path d="M2982.29 1072.76C2988.65 1072.41 2993.41 1065.1 2992.93 1056.43C2992.46 1047.77 2986.92 1041.03 2980.56 1041.38C2974.21 1041.73 2969.45 1049.04 2969.92 1057.7C2970.4 1066.36 2975.94 1073.1 2982.29 1072.76Z" fill="#F1F1F1"/>
        <path d="M3030.63 918.135C3039.3 917.658 3046.04 912.121 3045.69 905.767C3045.34 899.413 3038.03 894.649 3029.37 895.126C3020.7 895.603 3013.96 901.141 3014.31 907.494C3014.66 913.848 3021.97 918.612 3030.63 918.135Z" fill="#F1F1F1"/>
        <path d="M3085.02 891.226C3093.69 890.749 3100.43 885.211 3100.08 878.858C3099.73 872.504 3092.42 867.74 3083.76 868.217C3075.09 868.694 3068.35 874.231 3068.7 880.585C3069.05 886.939 3076.36 891.703 3085.02 891.226Z" fill="#F1F1F1"/>
        <path d="M3142 920C3150.67 919.523 3157.41 913.985 3157.06 907.632C3156.71 901.278 3149.4 896.514 3140.74 896.991C3132.07 897.468 3125.33 903.005 3125.68 909.359C3126.03 915.713 3133.34 920.477 3142 920Z" fill="#F1F1F1"/>
        <path d="M3088.89 944.989C3097.55 944.512 3104.29 938.974 3103.94 932.62C3103.59 926.267 3096.29 921.503 3087.62 921.98C3078.96 922.457 3072.22 927.994 3072.57 934.348C3072.92 940.702 3080.23 945.466 3088.89 944.989Z" fill="#F1F1F1"/>
      </svg>
      <defs>
        <filter id="filter0_d" color-interpolation-filters="sRGB">
          <feFlood flood-opacity="0" result="BackgroundImageFix"/>
          <feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
          <feOffset dx="8" dy="8"/>
          <feGaussianBlur stdDeviation="15"/>
          <feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0"/>
          <feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
          <feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
        </filter>
        <filter id="filter1_i" color-interpolation-filters="sRGB">
          <feFlood flood-opacity="0" result="BackgroundImageFix"/>
          <feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
          <feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
          <feOffset dx="-3.4"/>
          <feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
          <feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.18 0"/>
          <feBlend mode="normal" in2="shape" result="effect1_innerShadow"/>
        </filter>
      </defs>
    </svg>