2

I would like to add a centered image inside SVG.

It will serve as a user avatar but failing to do so

.body {
  width: 100%;
  height: 100%;
  background: #1f1b33;
  padding: 2rem;
}

svg {
width: 120px;
}
<div class="body">
    <svg viewBox="0 0 121.375 125.397">
      <g
        id="blank"
        transform="translate(-1460.94 -927.887)"
      >
        <path
          id="wrapper"
          data-name="Caminho 2257"
          d="M80.617,78.013C67.787,91.6,11.606,90.985-8.689,69.872s-20.527-73.915,0-90.659S66.834-47.3,87.13-26.188,93.447,64.424,80.617,78.013Z"
          transform="translate(1484.938 966.119)"
          fill="#fff"
          opacity="0.2"
        />
        <rect
          id="within"
          data-name="Retângulo 365"
          width="97"
          height="97"
          rx="37"
          transform="translate(1475 945)"
          fill="#fff"
        />
      </g>
    </svg>
  </div

I already tried to create an image element inside SVG and reference it as fill, but the image is not centered.

halfer
  • 19,824
  • 17
  • 99
  • 186
Yung Silva
  • 1,324
  • 4
  • 20
  • 40

5 Answers5

1

I managed to make an image stay in place of the color white.

.body {
  width: 100%;
  height: 100%;
  background: #1f1b33;
  padding: 2rem;
}

svg {
  width: 120px;
}
<div class="body">
<svg
      xmlns="http://www.w3.org/2000/svg"
      xmlns:xlink="http://www.w3.org/1999/xlink"
      width="121.375"
      height="125.397"
      viewBox="0 0 121.375 125.397"
    >
      <defs>
        <clipPath id="clip-path">
          <rect
            id="Retângulo_365"
            data-name="Retângulo 365"
            width="97"
            height="97"
            rx="37"
            transform="translate(-932 2753)"
            fill="#fff"
          />
        </clipPath>
        <pattern
          id="pattern"
          preserveAspectRatio="xMidYMid slice"
          width="100%"
          height="100%"
          viewBox="0 0 450 450"
        >
          <image
            width="450"
            height="450"
            xlink:href="https://www.espacoluzevida.com.br/wp-content/uploads/2016/05/default-female-avatar.png"
          />
        </pattern>
      </defs>
      <g
        id="profile-image-customized"
        transform="translate(-152.94 -170.887)"
      >
        <path
          id="Caminho_2257"
          data-name="Caminho 2257"
          d="M80.617,78.013C67.787,91.6,11.606,90.985-8.689,69.872s-20.527-73.915,0-90.659S66.834-47.3,87.13-26.188,93.447,64.424,80.617,78.013Z"
          transform="translate(176.938 209.119)"
          fill="#fff"
          opacity="0.2"
        />
        <g
          id="Grupo_de_máscara_7"
          data-name="Grupo de máscara 7"
          transform="translate(1099 -2565)"
          clip-path="url(#clip-path)"
        >
          <path
            id="_32814145-woman-avatar-profile-picture-icon-on-light-gray-background"
            data-name="32814145-woman-avatar-profile-picture-icon-on-light-gray-background"
            d="M0,0H97V97H0Z"
            transform="translate(-932 2753)"
            fill="url(#pattern)"
          />
        </g>
      </g>
    </svg>
</div>
Yung Silva
  • 1,324
  • 4
  • 20
  • 40
1

An image can be inserted into any SVG shape in several ways:

  1. Using clipPath
  2. Using mask
  3. Using pattern

With any method of inserting an image, you need to focus on the shape of the template.

If the template has a symmetrical shape, it is necessary to select the original image with the same aspect ratio.

In other words, if the cropping pattern is a circle or regular polygons, then you need to select images with the same width and height.

Using mask

I chose a square image

enter image description here

.body {
  
  padding: 2rem;
  background-color:#1f1b33;
}

svg {
width: 25%;
height:25%;
} 
image {
width:100%;
height:100%;
mask:url(#msk1);
}
<div class="body">
    <svg  viewBox="0 0 121.375 125.397" preserveAspectRatio="xMinYMin meet">
  <defs> 
  <mask id="msk1"> 
    <rect width="100%" height="100%" fill="black" />
   <rect
          id="within"
          data-name="Retângulo 365"
     x="10" y="10"
          width="97"
          height="97"
          rx="37"
          fill="white"
    stroke="#d5d5d5"
    stroke-width="4"
        />
  </mask>
</defs> 
  <rect width="100%" height="100%" fill="#1f1b33" />
      <g
        id="blank"
        transform="translate(-1460.94 -927.887)"
      >
        <path
          id="wrapper"
          data-name="Caminho 2257"
          d="M80.617,78.013C67.787,91.6,11.606,90.985-8.689,69.872s-20.527-73.915,0-90.659S66.834-47.3,87.13-26.188,93.447,64.424,80.617,78.013Z"
          transform="translate(1484.938 966.119)"
          fill="#fff"
          opacity="0.2"
        /> 
  </g>
        <rect
          id="within"
          data-name="Retângulo 365"
          x="10" y="10"
    width="97"
          height="97"
          rx="37"
         
          fill="none"
    stroke="black"
    stroke-width="2"
        />
       
    <image xlink:href="https://i.stack.imgur.com/UsGg5.jpg" x="0" y="0"/> 
    </svg>
  </div>

2.# Animation of image rotation when hovering

CSS rules are used to implement rotation of images

#img {
transform-origin:125px 125px;
  -webkit-transition: -webkit-transform 1s ease-in-out;
          transition:         transform 1s ease-in-out;
}

#img:hover {
  -webkit-transform: rotate(360deg);
          transform: rotate(360deg);
}

.body {
  
  padding: 2rem;
  background-color:#1f1b33;
}

svg {
width: 25%;
height:25%;
} 


#img {
width:100%;
height:100%;
mask:url(#msk1);
transform-box: fill-box;
transform-origin:50% 50%;
  -webkit-transition: -webkit-transform 1s ease-in-out;
          transition:         transform 1s ease-in-out;
}

#img:hover {
  -webkit-transform: rotate(360deg);
          transform: rotate(360deg);
}
<div class="body">
    <svg  viewBox="0 0 121.375 125.397" preserveAspectRatio="xMinYMin meet">
  <defs> 
  <mask id="msk1"> 
    <rect width="100%" height="100%" fill="black" />
   <rect
          id="within"
          data-name="Retângulo 365"
     x="10" y="10"
          width="97"
          height="97"
          rx="37"
          fill="white"
    stroke="#d5d5d5"
    stroke-width="4"
        />
  </mask>
</defs> 
 
      <g
        id="blank"
        transform="translate(-1460.94 -927.887)"
      >
        <path
          id="wrapper"
          data-name="Caminho 2257"
          d="M80.617,78.013C67.787,91.6,11.606,90.985-8.689,69.872s-20.527-73.915,0-90.659S66.834-47.3,87.13-26.188,93.447,64.424,80.617,78.013Z"
          transform="translate(1484.938 966.119)"
          fill="#fff"
          opacity="0.2"
        /> 
  </g>
               
    <image id="img" xlink:href="https://i.stack.imgur.com/UsGg5.jpg" x="0" y="0"/> 
    </svg>
  </div>
Alexandr_TT
  • 13,635
  • 3
  • 27
  • 54
0

As @Zuber suggests on his comments, you can learn how to do this here.

Example with your code:

.body {
  width: 100%;
  height: 100%;
  background: #1f1b33;
  padding: 2rem;
}

svg { width: 120px; }
<div class="body">
  <svg viewBox="0 0 121.375 125.397">
    <defs>
      <pattern id="img1" patternUnits="userSpaceOnUse" width="100" height="100">
        <image xlink:href="https://cdn.pixabay.com/photo/2019/09/14/21/47/dog-4476989_960_720.jpg" x="0" y="0" width="100" height="100" />
      </pattern>
    </defs>
    <g
        id="blank"
        transform="translate(-1460.94 -927.887)"
    >
      <path
          id="wrapper"
          data-name="Caminho 2257"          d="M80.617,78.013C67.787,91.6,11.606,90.985-8.689,69.872s-20.527-73.915,0-90.659S66.834-47.3,87.13-26.188,93.447,64.424,80.617,78.013Z"
          transform="translate(1484.938 966.119)"
          fill="#fff"
          opacity="0.2"
      />
      <rect
          id="within"
          data-name="Retângulo 365"
          width="97"
          height="97"
          rx="37"
          transform="translate(1475 945)"

          fill="url(#img1)"
      />
    </g>
  </svg>
</div>
A. Meshu
  • 4,053
  • 2
  • 20
  • 34
0

Using a pattern fill is the way to go - if your image aspect ratio is square it will work nicely. Notice the patterns width and height are the same as your rectangle. It's important in this case to set the patternUnits to userSpaceOnUse which for simplicity keeps the pattern fill from scaling to the objects bounding box.

.body {
  width: 100%;
  height: 100%;
  background: #1f1b33;
  padding: 2rem;
}

svg {
  width: 120px;
}
<div class="body">
    <svg viewBox="0 0 121.375 125.397">
      <defs>
        <pattern id="patt" patternUnits="userSpaceOnUse" width="97" height="97">
          <image xlink:href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/17496/flace.jpg" width="97" height="97"></image>
        </pattern>
      </defs>
      <g
        id="blank"
        transform="translate(-1460.94 -927.887)"
      >
        <path
          id="wrapper"
          data-name="Caminho 2257"
          d="M80.617,78.013C67.787,91.6,11.606,90.985-8.689,69.872s-20.527-73.915,0-90.659S66.834-47.3,87.13-26.188,93.447,64.424,80.617,78.013Z"
          transform="translate(1484.938 966.119)"
          fill="#fff"
          opacity="0.2"
        />
        <rect
          id="within"
          data-name="Retângulo 365"
          width="97"
          height="97"
          rx="37"
          transform="translate(1475 945)"
          fill="url(#patt)"
        />
      </g>
    </svg>
</div>
Zevan
  • 10,097
  • 3
  • 31
  • 48
-1

How about using the pseudo element ::After or ::Before, setting it to relative, then giving it a background image and set your opacity or z-index to whatever you want? Just shooting a shot out there.

  • 1
    It's better to add some code to your answer... In this case you can edit his code in the way that you described and add it to the answer... cheers – Saman Salehi Sep 21 '19 at 19:14