How to make SVG “fill” act in a similar way to CSS “background-position:right top” - css

I have the following SVG image:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 66.667 108">
<pattern id="i" width="100%" height="100%">
<image xlink:href="https://upload.wikimedia.org/wikipedia/commons/3/38/Bangalore_Panorama_edit1.jpg" width="45" height="49" preserveAspectRatio="xMinYMin slice"/>
</pattern>
<rect x="21.667" y="0" width="45" height="49" fill="url(#i)"/>
</svg>
I need the rectangle to fill with an image equivalent to the following CSS syntax:
background-size:cover;
background-image:url("image.jpg");
background-repeat:no-repeat;
background-position:right top;
Thanks to this post, I got them all except background-position:right top. Is this possible in an SVG image? If so, how can I achieve this?

To mimic the behavior, so that the top right corner of the picture is located at the top right corner of the rect, you just need to change the preserveAspectRatio="xMinYMin slice" of the image to preserveAspectRatio="xMaxYMin slice":
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 66.667 108">
<pattern id="i" width="100%" height="100%">
<image xlink:href="https://upload.wikimedia.org/wikipedia/commons/3/38/Bangalore_Panorama_edit1.jpg" width="45" height="49" preserveAspectRatio="xMaxYMin slice"/>
</pattern>
<rect x="21.667" y="0" width="45" height="49" fill="url(#i)"/>
</svg>

Related

Responsive SVG Mask

I have looked at several other answers on Stack:
Responsive SVG Clip Path or Mask Image
Responsive SVG image mask
But none seem to work for me. I have an SVG mask based on a path. I want it to expand to fill all available space (or contract) whilst keeping the aspect ratio of the path.
svg {
width: 100%;
height: 100%;
}
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100%" height="100%" viewBox="0 0 237.859 264.582" preserveAspectRatio="xMinYMin meet">
<defs>
<pattern id="triangle-image" patternUnits="userSpaceOnUse" width="3918" height="3918">
<image xlink:href="images/aspirational-photos/christian-buehner-JQFHdpOKz2k-unsplash.jpg" x="0" y="0" width="100%" height="100%" />
</pattern>
<pattern id="triangle-pattern" width="100%" height="100%" patternUnits="userSpaceOnUse">
<path id="triangle-path" d="M237.844,32.946c-0.001-9.981-4.42-19.279-12.121-25.512c-7.82-6.331-17.85-8.78-27.518-6.721
c-3.373,0.717-6.639,1.979-9.707,3.751l-129.11,74.56l-42.942,24.8C6.147,109.771-0.001,120.42,0,132.312
c0,11.892,6.149,22.541,16.449,28.487l84.623,48.833l87.457,50.486c7.179,4.143,15.193,5.435,23.174,3.736
c15.41-3.279,26.166-16.532,26.156-32.222L237.844,32.946z"
fill="#fff" fill-rule="evenodd" width="100%" height="100%" />
</pattern>
<mask id="triangle-mask" width="100%">
<rect x="0" y="0" width="100%" height="100%" fill="url(#triangle-pattern)" />
</mask>
</defs>
<rect x="0" y="0" width="100%" height="100%" fill="url(#triangle-image)" mask="url(#triangle-mask)"/>
</svg>
The SVG seems to obey the path values no matter what I do. Is there a way to make it expand or contract like an image would?
I've simplified your code in the sense that I'm applying the mask to the image instead of using patterns. Also the mask is the path. I'm not using width="100%" since the width af an svg element will take all the space available i.e 100%.
I would like to understand why you need it height="100%"
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 240 265">
<defs>
<mask id="triangle-mask">
<path d="M237.844,32.946c-0.001-9.981-4.42-19.279-12.121-25.512c-7.82-6.331-17.85-8.78-27.518-6.721
c-3.373,0.717-6.639,1.979-9.707,3.751l-129.11,74.56l-42.942,24.8C6.147,109.771-0.001,120.42,0,132.312
c0,11.892,6.149,22.541,16.449,28.487l84.623,48.833l87.457,50.486c7.179,4.143,15.193,5.435,23.174,3.736
c15.41-3.279,26.166-16.532,26.156-32.222L237.844,32.946z"
fill="#fff" />
</mask>
</defs>
<image xlink:href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/222579/beagle400.jpg" mask="url(#triangle-mask)"/>
</svg>
Alternatively if you need all those patterns please remove width="100%"for the mask in your code.

I need to create 2 color Curve Responsive background with SVG

I need to create curve Responsive SVG background, with two color.
i Tried this below code:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100%" height="100%" viewBox="0 0 100% 100%" class="hidden-xs hidden-sm">
<defs>
<clipPath id="clip-Nye">
<rect width="100%" height="100%"/>
</clipPath>
</defs>
<g id="Nye" data-name="Nye" clip-path="url(#clip-Nye)">
<rect width="100%" height="100%" fill="#fff"/>
<path id="Rectangle" d="M0,453.226,817.641,0s696,663.078,406.715,730.84q-335.194,78.515-815.961,459.149C142.369,1400.607,0,453.226,0,453.226Z" transform="matrix(-0.485, 0.875, -0.875, -0.485, 1914.704, 197.622)" fill="#01b0f0"/>
</g>
</svg>
The Issue is that, when i minimize page with CTRL + -, SVG not show properly and side show blank.
what i do wrong? any idea?
You can try the use of radial-gradient:
body {
margin:0;
height:100vh;
background:radial-gradient(100% 200% at left,white 50%,#01b0f0 50.1%);
}

How does SVG image pattern work with preserving aspect ratio?

I have the following svg:
<svg height="100%" width="100%" viewBox="0 0 100 100" preserveAspectRatio="none" style="display: block; position: absolute; top: 0;">
<defs>
<pattern id="img1" patternUnits="objectBoundingBox" width="100%" height="100%">
<image xlink:href="https://media.npr.org/assets/img/2016/06/22/gettyimages-467390112_custom-e8fa0c9a7224b7172555577fde25a08949bde2d2-s900-c85.jpg" x="0" y="-20" width="100" height="100"/>
</pattern>
</defs>
<polygon points="0 100, 50,50 100,100" id="abajo" style="stroke-width:0" fill="url(#img1)"/>
</svg>
It's not working as expected because it enlarge te face of the people on the image as follows:
But it should look like this:
Does having a triangular polygon affects the image? How can I solve it, I need 4 triangle figures with images inside to be clickables.
Well this is working as intended. You specify a pattern whose unit should fill the bounding box of the container, and then specify a 2:1 container - so it stretches the image. There are lots of permutations that preserve the aspect ratio of the image - it depends on exactly what behavior you want.
This is one version that preserves the aspect ratio of the SVG itself even when it's asked to fill a larger space.
<svg height="100%" width="100%" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid slice" style="display: block; position: absolute; top: 0;">
<defs>
<pattern id="img1" patternUnits="objectBoundingBox" width="100%" height="100%">
<image xlink:href="https://media.npr.org/assets/img/2016/06/22/gettyimages-467390112_custom-e8fa0c9a7224b7172555577fde25a08949bde2d2-s900-c85.jpg" x="0" y="-20" width="100" height="100"/>
</pattern>
</defs>
<polygon points="0 100, 50,50 100,100" id="abajo" fill="url(#img1)" />
</svg>
Or if you want to adjust the pattern itself, you can double the height of the pattern and offset it in Y to adjust for the 2:1 ratio of your container:
<svg height="100%" width="100%" viewBox="0 0 100 100" style="display: block; position: absolute; top: 0;">
<defs>
<pattern id="img1" patternUnits="objectBoundingBox" y="-100%" width="100%" height="200%">
<image xlink:href="https://media.npr.org/assets/img/2016/06/22/gettyimages-467390112_custom-e8fa0c9a7224b7172555577fde25a08949bde2d2-s900-c85.jpg" x="0" y="0" width="100" height="100" preserveAspectRatio="xMidYMax meet"/>
</pattern>
</defs>
<polygon points="0 100, 50,50 100,100" id="abajo" fill="url(#img1)" />
</svg>
This is another version that uses a filter to fill in the image.
<svg height="100%" width="100%" viewBox="0 0 100 100" style="display: block; position: absolute; top: 0; background:grey">
<defs>
<filter id="img1" x="0%" y="0%" width="100%" height="100%" >
<feImage xlink:href="https://media.npr.org/assets/img/2016/06/22/gettyimages-467390112_custom-e8fa0c9a7224b7172555577fde25a08949bde2d2-s900-c85.jpg" x="0" y="0" width="100" height="100" preserveAspectRatio="xMidYMax meet"/>
<feComposite operator="in" in2="SourceGraphic"/>
</filter>
</defs>
<polygon points="0 100, 50,50 100,100" id="abajo" filter="url(#img1)" />
</svg>

Center an element of a SVG mask

I'm a newbie in SVG so it's probably an easy question. I'm trying to make an SVG Mask with a simple triangle shape inside a rectangle. What I want to achieve is to get the rectangle responsive with his width but the triangle should
- get a fixed size
- be always at the center of the viewport
You'll understand better with my snippet:
.header-arrow {
height: 70px;
}
svg {
height: inherit;
}
#arrow-down-alpha {
transform: translateX(calc(50vw - 130px/2));
}
<div class="header-arrow">
<svg width="100%">
<defs>
<mask id="myMask" x="0" y="0" width="100%" height="100%">
<rect fill="white" x="0" y="0" width="100%" height="100%" />
<polygon id="arrow-down-alpha" fill="black" x="00" y="0" width="165px" height="100%" points="55.91 37.8 111.81 0 0 0 55.91 37.8" />
</mask>
</defs>
<rect id="base-mask" mask="url(#myMask)" x="0" y="0" width="100%" height="100%" />
</svg>
</div>
It's workning right now in chrome, but the translateX (or translate) is not working in firefox and edge. I've tried to use the transform SVG attribute but it seems that I can't use percentages values.
I'm not realy familiar with the viewbox but I'm not sure it will help in this case.
Thanks anyway for any kind of help !
Here's one way to achieve what you want without relying on new units or calc(). It should be cross-browser compatible also.
How it works:
We wrap the triangle in a nested SVG. We use an SVG because it has an x attribute which can take percentages.
We position this nested SVG at x="50%". It is now centred in the mask (roughly, see next step).
We move the triangle shape so it is centred at x=0. That's so that it is not offset from the centre of the mask.
We set overflow="visible" on the nested SVG so the part of the triangle that is now off the left of the SVG (ie. x < 0) are not clipped.
.header-arrow {
height: 70px;
}
svg {
height: inherit;
}
<div class="header-arrow">
<svg width="100%">
<defs>
<mask id="myMask" x="0" y="0" width="100%" height="100%">
<rect fill="white" x="0" y="0" width="100%" height="100%" />
<svg x="50%" overflow="visible">
<polygon fill="black" points="0 38 56 0 -56 0" />
</svg>
</mask>
</defs>
<rect id="base-mask" mask="url(#myMask)" x="0" y="0" width="100%" height="100%" />
</svg>
</div>

Show hidden rect with text on hover of another poly

I need to use pure svg for a project. I know how to get this effect simply with divs but I dont know how to make it work with svg, I dont know what im doing wrong.
I want to show a hidden black rect with white text when you hover on another polygon (and the polygon is 0.1 of opacity normal and changes to 0.8 of opacity on the same hover) Something like a tooltip with opacity and with a nice smooth transition, but pure SVG.
.showme {
opacity: 0.3;
}
.showme:hover {
opacity: 0.8;
}
.desc {
visibility: hidden;
}
.showme:hover + .desc {
visibility: visible;
}
<svg width="200" height="200" viewBox="0 0 1000 300"
xmlns="http://www.w3.org/2000/svg" version="1.1" >
<rect x="1" y="1" width="998" height="298" fill="blue" class="showme"/>
</svg>
<svg width="200" height="200" viewBox="0 0 1000 300"
xmlns="http://www.w3.org/2000/svg" version="1.1" class="desc" >
<rect x="1" y="1" width="998" height="298" fill="black" />
<text x="250" y="150" font-family="Verdana" font-size="55" fill="white">Hello world!</text>
</svg>
Please help :/
Thanks.
Keeping your svg, you can do with like this, but you'll need some slight changes:
<svg width="200" height="200" viewBox="0 0 1000 300"
xmlns="http://www.w3.org/2000/svg" version="1.1" >
<rect onmouseover='document.getElementById("desc").style.visibility = "visible"' onmouseout='document.getElementById("desc").style.visibility = "hidden"' x="1" y="1" width="998" height="298" fill="blue" class="showme"/>
</svg>
<svg width="200" height="200" viewBox="0 0 1000 300"
xmlns="http://www.w3.org/2000/svg" version="1.1" id="desc" >
<rect x="1" y="1" width="998" height="298" fill="black" />
<text x="250" y="150" font-family="Verdana" font-size="55" fill="white">Hello world!</text>
</svg>
https://jsfiddle.net/q6kkhvz7/2/

Resources