Responsively Position SVG within a Parent - html

I have an SVG overlay that is a shape with a hole punched out of it. Is there anyway I can set it so the overlay is effectively pinned to the bottom right corner and keeps the circle in proportionately the same position, whilst expanding the rest of the SVG to fill the remaining area of the container?
I've managed to get the SVG to (seemingly) stay in the bottom right corner, but I can't work out how to get it to fill the rest of the container? I'll need to do this without contorting the circle shape obviously.
codepen: https://codepen.io/emilychews/pen/KQmZEd
body {
width: 100%;
height: 100vh;
padding: 0; margin: 0;
display: flex;}
#box {
margin: auto;
position: relative;
width: 33%;
height: 200px;
background: url(https://lorempixel.com/400/400/) center/cover;
overflow: hidden;
}
#overlay {
position: absolute;
bottom: 0;
right: 0;
}
<div id="box">
<svg id="overlay" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 232.71 170.5"><g id="Layer_2" data-name="Layer 2"><g id="Layer_2-2" data-name="Layer 2-2"><path d="M0,0V170.5H232.71V0ZM187.37,148.19a23,23,0,1,1,23-23h0A23,23,0,0,1,187.37,148.19Z" transform="translate(0 0)" fill="#015668"/></g></g></svg>
</div>

I would consider another idea to create the hole using mask where you can easily control the circle position and size. Then the trick is to make the whole svg to overflow with big width/height to always cover the div and to keep the same size of the circle:
body {
width: 100%;
height: 100vh;
padding: 0;
margin: 0;
display: flex;
}
#box {
margin: auto;
position: relative;
width: 33%;
height: 200px;
background: url(https://lorempixel.com/400/400/) center/cover;
overflow: hidden;
}
#overlay {
position: absolute;
bottom: 0;
right: 0;
width:1000px;
height:1000px;
}
<div id="box">
<svg id="overlay" viewbox="0 0 400 400" >
<defs>
<mask id="hole">
<rect width="100%" height="100%" fill="white"/>
<!-- This circle is your hole -->
<circle r="20" cx="370" cy="370" fill="black"/>
</mask>
</defs>
<rect x=0 y=0 width=400 height=400 mask="url(#hole)" fill="green" />
</svg>
</div>
If you want the circle to be resized on width change you can try this:
body {
width: 100%;
height: 100vh;
padding: 0;
margin: 0;
display: flex;
}
#box {
margin: auto;
position: relative;
width: 33%;
height: 200px;
background: url(https://lorempixel.com/400/400/) center/cover;
overflow: hidden;
}
#overlay {
position: absolute;
bottom: 0;
right: 0;
width:100%;
}
<div id="box">
<svg id="overlay" viewbox="0 0 400 10000" >
<defs>
<mask id="hole">
<rect width="100%" height="100%" fill="white"/>
<!-- This circle is your hole -->
<circle r="80" cx="300" cy="9900" fill="black"/>
</mask>
</defs>
<rect x=0 y=0 width=400 height=10000 mask="url(#hole)" fill="green" />
</svg>
</div>
And you can easily have the opacity you needed in the previous question:
body {
width: 100%;
height: 100vh;
padding: 0;
margin: 0;
display: flex;
}
#box {
margin: auto;
position: relative;
width: 33%;
height: 200px;
background: url(https://lorempixel.com/400/400/) center/cover;
overflow: hidden;
}
#overlay {
position: absolute;
bottom: 0;
right: 0;
width:100%;
}
<div id="box">
<svg id="overlay" viewbox="0 0 400 10000" >
<defs>
<mask id="hole">
<rect width="100%" height="100%" fill="white"/>
<!-- This circle is your hole -->
<circle r="80" cx="300" cy="9900" fill="black"/>
</mask>
</defs>
<rect x=0 y=0 width=400 height=10000 mask="url(#hole)" fill="rgba(0,0,255,0.5)" />
</svg>
</div>

Here's how I would do it. I'll provide step-by-step instructions so it's easier to follow the "magic". :)
The idea is to use a simple square SVG with a viewBox width and height of 100x100. Then we can position the circle that will be our future hole in the bottom right of the viewBox.
body {
width: 100%;
height: 100vh;
padding: 0; margin: 0;
display: flex;}
#box {
margin: auto;
position: relative;
width: 33%;
height: 200px;
background: url(https://lorempixel.com/400/400/) center/cover;
overflow: hidden;
}
<div id="box">
<svg width="100%" height="100%" viewBox="0 0 100 100">
<rect x="0" y="0" width="100" height="100" fill="#015668"/>
<circle cx="70" cy="70" r="20" fill="black"/><!-- the hole -->
</svg>
</div>
Then we use preserveAspectRatio="xMaxYMax meet" to tell the renderer that we want the SVG contents in the bottom right corner.
body {
width: 100%;
height: 100vh;
padding: 0; margin: 0;
display: flex;}
#box {
margin: auto;
position: relative;
width: 33%;
height: 200px;
background: url(https://lorempixel.com/400/400/) center/cover;
overflow: hidden;
}
<div id="box">
<svg width="100%" height="100%" viewBox="0 0 100 100" preserveAspectRatio="xMaxYMax meet">
<rect x="0" y="0" width="100" height="100" fill="#015668"/>
<circle cx="70" cy="70" r="20" fill="black"/><!-- the hole -->
</svg>
</div>
The next step is make the rectangle wider and start off the left of the viewBox so that it fills the area of the viewport that is to the left of the SVG. We'll do that by making it start at x="-900" and be width="1000". That means it extends to the left 9X more than the (100 wide) viewBox. That should make it more than wide enough to cater for even the most humongous monitors around.
We will also do the same thing in the vertical direction. Just in case the viewport ever gets tall and skinny. That can happen if you resize the window so that it has narrow width.
body {
width: 100%;
height: 100vh;
padding: 0; margin: 0;
display: flex;}
#box {
margin: auto;
position: relative;
width: 33%;
height: 200px;
background: url(https://lorempixel.com/400/400/) center/cover;
overflow: hidden;
}
<div id="box">
<svg width="100%" height="100%" viewBox="0 0 100 100" preserveAspectRatio="xMaxYMax meet">
<rect x="-900" y="-900" width="1000" height="1000" fill="#015668"/>
<circle cx="70" cy="70" r="20" fill="black"/><!-- the hole -->
</svg>
</div>
Finally, we convert this to a mask and apply it to a rectangle that fills the viewport the same way.
body {
width: 100%;
height: 100vh;
padding: 0; margin: 0;
display: flex;}
#box {
margin: auto;
position: relative;
width: 33%;
height: 200px;
background: url(https://lorempixel.com/400/400/) center/cover;
overflow: hidden;
}
<div id="box">
<svg width="100%" height="100%" viewBox="0 0 100 100" preserveAspectRatio="xMaxYMax meet">
<defs>
<mask id="mymask">
<rect x="-900" y="-900" width="1000" height="1000" fill="white" fill-opacity="0.9"/>
<circle cx="70" cy="70" r="20" fill="black"/><!-- the hole -->
</mask>
</defs>
<rect x="-900" y="-900" width="1000" height="1000" fill="#015668" mask="url(#mymask)"/>
</svg>
</div>
For a final test. Let's make the "box" bigger to check it is properly responsive. We'll make it 400px high this time. Try resizing the browser windo to check the responsiveness.
body {
width: 100%;
height: 100vh;
padding: 0; margin: 0;
display: flex;}
#box {
margin: auto;
position: relative;
width: 33%;
height: 400px;
background: url(https://lorempixel.com/400/400/) center/cover;
overflow: hidden;
}
<div id="box">
<svg width="100%" height="100%" viewBox="0 0 100 100" preserveAspectRatio="xMaxYMax meet">
<defs>
<mask id="mymask">
<rect x="-900" y="-900" width="1000" height="1000" fill="white" fill-opacity="0.9"/>
<circle cx="70" cy="70" r="20" fill="black"/><!-- the hole -->
</mask>
</defs>
<rect x="-900" y="-900" width="1000" height="1000" fill="#015668" mask="url(#mymask)"/>
</svg>
</div>

Related

How to show an svg element with an fade in?

I have an svg element. How can i show it gradually (like an animation) from left to right?
You can use CSS #keyframes.
#keyframes stretchInFromLeft {
0% {
width: 100%;
}
100% {
width: 0;
}
}
img {
max-width: 100%;
width: 100%;
}
.wrapper {
position: relative;
}
.overlay {
animation: 1s ease-out 0s 1 stretchInFromLeft;
position: absolute;
top: 0;
right: 0;
background: #fff;
width: 0;
height: 100%;
}
<div class="wrapper">
<img src="https://i.stack.imgur.com/dta2g.jpg" />
<div class="overlay"></div>
</div>
Fiddle: https://jsfiddle.net/r034wcgp/1/
Source: css3 transition animation on load?
You could animate a SVG clipPath with jQuery animate() like this:
$("#cut-off-bottom rect").animate({width: "100%", duration:4000})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1440 320">
<clipPath id="cut-off-bottom">
<rect x="0" y="0" width="0" height="320" />
</clipPath>
<path fill="#0099ff" fill-opacity="1" clip-path="url(#cut-off-bottom)" d="M0,32L48,32C96,32,192,32,288,58.7C384,85,480,139,576,154.7C672,171,768,149,864,165.3C960,181,1056,235,1152,240C1248,245,1344,203,1392,181.3L1440,160L1440,320L1392,320C1344,320,1248,320,1152,320C1056,320,960,320,864,320C768,320,672,320,576,320C480,320,384,320,288,320C192,320,96,320,48,320L0,320Z"></path>
</svg>

How to disable SVG scroll?

I'm trying to disable the scrolling of the svg. I tried to put the property overflow to hidden or visible but the svg still to scroll.
I created the jsfiddle here.
https://jsfiddle.net/pct8rL03/1/
.svg {
display: inline-block;
position: absolute;
top: 0;
left: 0;
}
.wave-container {
display: inline-block;
position: absolute;
width: 100%;
vertical-align: middle;
overflow: hidden;
}
<div class="wave-container">
<svg viewBox="0 0 500 500" preserveAspectRatio="xMinYMin meet">
<path d="M0,95 C90,130 250,0 500,100 L500,00 L0,0 Z" style="stroke: none; fill:#e0efe3;"></path>
</svg>
</div>
Thank you in advance
Try using this for your wave-container css and you don't need to give a position and display css for your svg. The css for your wave-container should be enough. Hope this helps
.wave-container {
width: -webkit-fill-available;
height: -webkit-fill-available;
vertical-align: middle;
overflow: hidden;
}
<div class="wave-container">
<svg viewBox="0 0 500 500" preserveAspectRatio="xMinYMin meet">
<path d="M0,95 C90,130 250,0 500,100 L500,00 L0,0 Z" style="stroke: none; fill:#e0efe3;"></path>
</svg>
</div>
<div class="wave-container">
<svg viewBox="0 0 500 500" preserveAspectRatio="xMinYMin meet">
<path d="M0,95 C90,130 250,0 500,100 L500,00 L0,0 Z" style="stroke: none; fill:#e0efe3;"></path>
</svg>
</div>
body{
margin:0px 0px;
padding:0px px;
}
.svg {
display: inline-block;
position: absolute;
top: 0;
left: 0;
}
.wave-container {
display: inline-block;
position: absolute;
width: 100%;
vertical-align: middle;
overflow: hidden;
height:100%;
}
There is nothing to do here. Your SVG is just to big and add to much blank space at the bottom. To fix it just update your SVG file.
Not a good practice:
You can use the property overflow: hidden; on your .wave-container but to make it work you have to set a height or max-height to it

How to get svg clipPath sized correctly

I have a problem with scaling my inline SVG which is used for clip-path only. The element which is clipped has a width of 150px and a height of 150px. It's the 2nd day I'm trying to fix this, but I feel like running in circles.
In Chrome (latest) the SVG has the correct width of 150px.
In Opera (latest) the SVG has the correct width of 150px
In Firefox (54.0.1) the SVG doesn't have the correct width.
body {
background: #333;
}
.image {
background-size: cover;
background-repeat: no-repeat;
background-position: center center;
clip-path: url(#clipPath);
height: 150px;
left: 0;
position: absolute;
top: 0;
width: 150px;
}
#clipPath {
transform: scale(2.63, 2.63);
}
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 1 1">
<defs>
<clipPath id="clipPath" clipPathUnits="objectBoundingBox">
<!-- <path d="M28.487,10.847C21.13-6.364,0.18-2.348,0.08,17.628C0,33.538,27.699,46.784,28.531,49.636C29.285,46.675,57,33.785,56.92,17.509C56.823-2.517,35.506-5.678,28.487,10.847z">-->
<path d="M0.189913333333,0.0723133333333C0.140866666667-0.0424266666667,0.0012-0.0156533333333,0.000533333333333,0.11752C0,0.223586666667,0.18466,0.311893333333,0.190206666667,0.330906666667C0.195233333333,0.311166666667,0.38,0.225233333333,0.379466666667,0.116726666667C0.37882-0.01678,0.236706666667-0.0378533333333,0.189913333333,0.0723133333333z">
</clipPath>
</defs>
</svg>
<div class="image" style="background-image: url('https://images.unsplash.com/photo-1468793195345-d9d67818016d?dpr=1&auto=format&fit=crop&w=1500&h=994&q=80&cs=tinysrgb&crop=');"></div>
Apply transform using attribute, not via CSS to fix this in Firefox.
body {
background: #333;
}
.image {
background-size: cover;
background-repeat: no-repeat;
background-position: center center;
clip-path: url(#clipPath);
height: 150px;
left: 0;
position: absolute;
top: 0;
width: 150px;
}
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 1 1">
<defs>
<clipPath id="clipPath" clipPathUnits="objectBoundingBox" transform="scale(2.63, 2.63)">
<path d="M0.189913333333,0.0723133333333C0.140866666667-0.0424266666667,0.0012-0.0156533333333,0.000533333333333,0.11752C0,0.223586666667,0.18466,0.311893333333,0.190206666667,0.330906666667C0.195233333333,0.311166666667,0.38,0.225233333333,0.379466666667,0.116726666667C0.37882-0.01678,0.236706666667-0.0378533333333,0.189913333333,0.0723133333333z">
</path>
</clipPath>
</defs>
</svg>
<div class="image" style="background-image: url('https://images.unsplash.com/photo-1468793195345-d9d67818016d?dpr=1&auto=format&fit=crop&w=1500&h=994&q=80&cs=tinysrgb&crop=');"></div>

vertical center svg in div container

Can you help me to understand why my svg refuse to resize the height for helping me to center vertically in a div container ?
How can I process for align vertical svg in a container ? I seem to svg behaviour is not standard like div...
The main idea is that center horizontally AND vertically svg into a div.
I try this : https://jsfiddle.net/gbz7rp7u/1/#&togetherjs=0n9iL62pHv
<div id="svg-container">
<svg id="svg-1" height="50%" width="50%" viewBox="0 0 1000 1000" xmlns="http://www.w3.org/2000/svg" version="1.1">
<circle r="15" cx="350" cy="80"></circle>
</svg>
</div>
#svg-container
{
background-color: red;
}
#svg-1
{
margin: auto auto;
display: block;
height: 30%;
}
html, body {
height: 100%;
}
#svg-container
{
display: flex;
align-items: center;
background-color: red;
height: 100%;
}
#svg-1
{
margin: 0 auto;
display: block;
}
<div id="svg-container">
<svg id="svg-1" height="15px" width="15px" viewBox="0 0 30 30" xmlns="http://www.w3.org/2000/svg" version="1.1">
<circle r="15" cx="15" cy="15"></circle>
</svg>
</div>
html, body {
height: 100%;
}
#svg-container {
background-color: red;
height: 100%;
}
#svg-1 {
display: block;
margin: auto;
height: 100%;
}
<div id="svg-container">
<svg id="svg-1" height="15px" width="15px" viewBox="0 0 30 30" xmlns="http://www.w3.org/2000/svg" version="1.1">
<circle r="15" cx="15" cy="15"></circle>
</svg>
</div>

CSS one side cut circle image with border

How I can make following shape with a colored border:
My first try was pure CSS but the attached code makes more an egg shape than a circle:
img {
border: 2px #ff00ff solid;
border-top-left-radius: 60% 50%;
border-bottom-left-radius: 60% 50%;
border-top-right-radius: 50% 20%;
border-bottom-right-radius:50% 20%;
}
<img src="https://d1wn0q81ehzw6k.cloudfront.net/additional/thul/media/4e34feee0acdc38a?w=400&h=400" style="width:100%">
Second try, working with SVG isn't supported in Opera and IE and I have no idea how to make borders. The "cut" doesn't work every time.
img {
clip-path: url(#myClip);
}
<svg width="120" height="120"
viewBox="0 0 120 120"
xmlns="http://www.w3.org/2000/svg">
<defs>
<clipPath id="myClip">
<circle cx="260" cy="256" r="256" style="fill:none;stroke:#00df0b;stroke-width:6"/>
</clipPath>
</defs>
</svg>
<img src="https://d1ra4hr810e003.cloudfront.net/media/27FB7F0C-9885-42A6-9E0C19C35242B5AC/0/D968A2D0-35B8-41C6-A94A0C5C5FCA0725/F0E9E3EC-8F99-4ED8-A40DADEAF7A011A5/dbe669e9-40be-51c9-a9a0-001b0e022be7/thul-IMG_2100.jpg" style="width:100%">
The simplest solution is probably just to make an SVG.
<svg width="400px" height="400px" viewBox="0 0 1 1"
overflow="visible">
<defs>
<mask id="myMask" x="0" y="0" width="1" height="1"
maskContentUnits="objectBoundingBox" fill="white">
<path id="myPath" d="M 0.8 0.9 L 0.8 0.1 A 0.5 0.5 0 1 0 0.8 0.9 Z"/>
</mask>
</defs>
<image xlink:href="https://d1ra4hr810e003.cloudfront.net/media/27FB7F0C-9885-42A6-9E0C19C35242B5AC/0/D968A2D0-35B8-41C6-A94A0C5C5FCA0725/F0E9E3EC-8F99-4ED8-A40DADEAF7A011A5/dbe669e9-40be-51c9-a9a0-001b0e022be7/thul-IMG_2100.jpg"
x="0" y="0" width="1" height="1" mask="url(#myMask)"/>
<use xlink:href="#myPath" fill="none" stroke="#f0f" stroke-width="0.01"/>
</svg>
You could use a pseudo element to create something like this:
div {
height: 300px;
width: 300px;
position: relative;
overflow: hidden;
cursor: pointer;
transition: all 0.4s;
}
div:hover {
height: 500px;
width: 500px;
}
div:before {
content: "";
box-sizing: border-box;
position: absolute;
top: 0;
left: 15%;
height: 100%;
width: 100%;
background: url(http://lorempixel.com/300/300);
background-size: 100% 100%;
border-radius: 50%;
border: 10px solid tomato;
}
div:after {
content: "";
position: absolute;
right: 0;
top: 15%;
height: 70%;
background: tomato;
width: 10px;
}
<div></div>