i think this might be very simple for some of you. i just want to mask an image with an SVG-graphic.
i created an SVG with the clipPath element in it:
<svg id="heart-path-container" version="1.1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px"
viewBox="0 0 50 50" xml:space="preserve">
<clipPath id="heart-path" clipPathUnits="objectBoundingBox">
<path d="M24.85,10.126c2.018-4.783,6.628-8.125,11.99-8.125c7.223,0,12.425,6.179,13.079,13.543
c0,0,0.353,1.828-0.424,5.119c-1.058,4.482-3.545,8.464-6.898,11.503L24.85,48L7.402,32.165c-3.353-3.038-5.84-7.021-6.898-11.503
c-0.777-3.291-0.424-5.119-0.424-5.119C0.734,8.179,5.936,2,13.159,2C18.522,2,22.832,5.343,24.85,10.126z">
</path>
</clipPath>
</svg>
and an SVG with the image in it:
<svg id="heart-image-container" version="1.1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px"
viewBox="0 0 50 50" xml:space="preserve">
<image class="clip-image" xlink:href="https://images.unsplash.com/photo-1490810277975-e64342ceecf0?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=88e69bf894f334456f8ae269752556e1&auto=format&fit=crop&w=2250&q=80"></image>
</svg>
i basically say in CSS that this image should be clipped with that SVG clipPath element.
.clip-image{
width: 100%;
height: 100%;
clip-path: url(#heart-path);
}
but it does not do it.
i created a fiddle to show that nothing is getting clipped.
what am i doing wrong?
https://codepen.io/Marvbuster/pen/MXvbXo
When you specify objectBoundingBox coordinates, the corrdinate have to be between 0 and 1. Your clip path coordinates go up to approx 50, so your clip path is 50x too big.
The simple fix is use a transform to scale your path back down to the correct size.
body, html{
height: 100%;
}
svg{
position: absolute;
width: 100%;
height: 100%;
}
.clip-image{
width: 100%;
height: 100%;
clip-path: url(#heart-path);
}
.wrapper{
position: relative;
margin: 0 auto;
height: 100%;
max-width: 500px;
display: flex;
flex-direction: column;
}
section{
position: relative;
background: red;
flex: 1;
width: 100%;
}
<div class="wrapper">
<section></section>
<section>
<svg x="0px" y="0px">
<clipPath id="heart-path" clipPathUnits="objectBoundingBox">
<path d="M24.85,10.126c2.018-4.783,6.628-8.125,11.99-8.125c7.223,0,12.425,6.179,13.079,13.543
c0,0,0.353,1.828-0.424,5.119c-1.058,4.482-3.545,8.464-6.898,11.503L24.85,48L7.402,32.165c-3.353-3.038-5.84-7.021-6.898-11.503
c-0.777-3.291-0.424-5.119-0.424-5.119C0.734,8.179,5.936,2,13.159,2C18.522,2,22.832,5.343,24.85,10.126z"
transform="scale(0.02,0.02)"></path>
</clipPath>
</svg>
<svg id="heart-image-container" version="1.1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px"
viewBox="0 0 50 50" xml:space="preserve">
<image class="clip-image" xlink:href="https://images.unsplash.com/photo-1490810277975-e64342ceecf0?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=88e69bf894f334456f8ae269752556e1&auto=format&fit=crop&w=2250&q=80"></image>
</svg>
</section>
<section></section>
</div>
Related
i created a video with clip-path. It works fine on Chrome and Firefox. But it dont work in Safari. The video is not visibile. Only if i deactivate the clip Path in the browser console of safari, i can see the video. So the problem seems to happen because of the clip path or in the svg tag of the clip path is a problem. Does anybody know why and how i can solve this?
My Code is below:
body {
margin: 0;
width: 100%;
height: 100%;
overflow-x: hidden;
}
video {
margin-right: 0;
width: 46vw;
height: 100vh;
object-fit: cover;
}
.video-container {
position: absolute;
margin-left: 54vw;
height: 100vh;
}
.border-container {
position: absolute;
right: 0;
height: 100vh;
width: 50vw;
}
.svg-clipped-text {
-webkit-clip-path: url(#svgTextPath);
clip-path: url(#svgTextPath);
}
.st0{fill:#E30D45;}
.svg-border {
left: 0;
height: 100vh;
margin-left: 54vw;
position: absolute;
}
<div class="video-container">
<video id="video1" width="1452" height="2000" class="svg-clipped-text" muted autoplay loop>
<source src="https://www.w3schools.com/html/movie.mp4" type="video/mp4">
</video>
</div>
<svg viewBox="0 0 A B" max-width="100%" width="100" max-height="100vh" height="100">
<clipPath id="svgTextPath">
<polygon class="st0" points="243.1,1997.3 0,0 1851.2,0 1851.2,1997.3 "/>
</clipPath>
</svg>
<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 4410.9 1997.3" class="svg-border" xml:space="preserve">
<g>
<g>
<path class="st0" d="M4330.9,80v1837.3H314L90.3,80H4330.9 M4410.9,0H0l243.1,1997.3h4167.8V0L4410.9,0z"/>
</g>
</g>
</svg>
I don't know why clipping directly on the video does not work, but if we move the clipping to the container element then the video does get clipped so this may help in your case:
body {
margin: 0;
width: 100%;
height: 100%;
overflow-x: hidden;
}
video {
margin-right: 0;
width: 46vw;
height: 100vh;
object-fit: cover;
}
.video-container {
position: absolute;
margin-left: 54vw;
height: 100vh;
}
.border-container {
position: absolute;
right: 0;
height: 100vh;
width: 50vw;
}
.svg-clipped-text {
-webkit-clip-path: url(#svgTextPath);
clip-path: url(#svgTextPath);
}
.st0{fill:#E30D45;}
.svg-border {
left: 0;
height: 100vh;
margin-left: 54vw;
position: absolute;
}
<div class="video-container svg-clipped-text">
<video id="video1" width="1452" height="2000" muted autoplay loop>
<source src="https://www.w3schools.com/html/movie.mp4" type="video/mp4">
</video>
</div>
<svg viewBox="0 0 A B" max-width="100%" width="100" max-height="100vh" height="100">
<clipPath id="svgTextPath">
<polygon class="st0" points="243.1,1997.3 0,0 1851.2,0 1851.2,1997.3 "/>
</clipPath>
</svg>
<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 4410.9 1997.3" class="svg-border" xml:space="preserve">
<g>
<g>
<path class="st0" d="M4330.9,80v1837.3H314L90.3,80H4330.9 M4410.9,0H0l243.1,1997.3h4167.8V0L4410.9,0z"/>
</g>
</g>
</svg>
I can confirm both issue reported by Luis and the solution from A Haworth to work.
Apparently, even though Safari is webkit, and Chrome is webkit, some quirks cause only Safari to fail applying clip-path when specified directly on a <video>. Wrapping the video with <div class="container><video/></div> and applying clip-path to the container is valid workaround.
Funny thing: with clipping directly on the <video> it is rendered correctly (even clipped) on Safari tab overview 🤦
I'm trying to use an inline svg as a background-image (data url), but background-size:cover does not seems to work well, however with 200% its fits perfectly.
I'd like to understand the issue so that I can make sure I have a consistent render with different browsers. Ideally I'd like to keep using background-size:cover if possible
.card {
display: inline-flex; /* required in my context */
width: 45vmax;
background-color: lightblue;
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="none" viewBox="0 0 2 2"><g fill="red"><path d="M0,1v-1h1z" opacity=".4" /><path d="M1,0v1h-1z" opacity=".2"/></g></svg>');
background-size: cover;
}
._200percent {
background-size: 200%;
}
.video {
padding-top: 56.25%;
}
body {
margin: 0;
}
<a class="card">
<div class="video"></div>
</a>
<a class="card _200percent">
<div class="video"></div>
</a>
As commented you can adjust the viewbox to cover the path and avoid having extra spaces and the use of 200%
svg {
border:1px solid;
width:200px;
}
<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="none" viewBox="0 0 2 2"><g fill="red"><path d="M0,1v-1h1z" opacity=".4" /><path d="M1,0v1h-1z" opacity=".2"/></g></svg>
<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="none" viewBox="0 0 1 1"><g fill="red"><path d="M0,1v-1h1z" opacity=".4" /><path d="M1,0v1h-1z" opacity=".2"/></g></svg>
You can also do this using CSS and gradient without the need of SVG
.card {
display: inline-flex; /* required in my context */
width: 45vmax;
background:
linear-gradient(to bottom right,rgba(255,0,0,0.4) 49.5%,rgba(255,0,0,0.2) 50%),
lightblue;
}
.video {
padding-top: 56.25%;
}
body {
margin: 0;
}
<a class="card">
<div class="video"></div>
</a>
I would like to accomplish two things:
The SVG width scales dynamically to take up 100% of the container's width.
SVG's is either stretched or smushed when the container's width changes (meaning the wave drawn with the svg's path)
SVG's height remains fixed to 760px. Currently if you resize the container, the SVG's height is reduced which is not desired.
.container {
width: 100%;
background: green;
height: 760px;
}
svg {
width: 100%;
}
svg path {
width: 100%;
}
<div class="container">
<svg width="1440" height="760" viewBox="0 0 1440 760" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M677.112 54.1657C400.36 -43.9336 110.391 13.291 0 54.1657V760H1440V54.1657C1301.02 95.0404 953.865 152.265 677.112 54.1657Z"
fill="purple"
/>
</svg>
</div>
I would probably use the SVG as background of a div and you can make the height of the div fixed and adjust the background-position to be top
.container {
width: 100%;
background: green;
height: 760px;
}
.container>div {
height: 100%;
background:
url('data:image/svg+xml;utf8,<svg width="1440" height="760" viewBox="0 0 1440 760" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M677.112 54.1657C400.36 -43.9336 110.391 13.291 0 54.1657V760H1440V54.1657C1301.02 95.0404 953.865 152.265 677.112 54.1657Z" fill="purple"/></svg>') top/100% no-repeat,
/*cover the bottom part with the same color*/
linear-gradient(purple, purple) bottom/ 100% calc(100% - 20vw) no-repeat;
}
<div class="container">
<div>
</div>
</div>
You can also reduce the code to keep only the container:
.container {
height: 760px;
background:
url('data:image/svg+xml;utf8,<svg width="1440" height="760" viewBox="0 0 1440 760" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M677.112 54.1657C400.36 -43.9336 110.391 13.291 0 54.1657V760H1440V54.1657C1301.02 95.0404 953.865 152.265 677.112 54.1657Z" fill="purple"/></svg>') top/100% no-repeat,
/*cover the bottom part with the same color*/
linear-gradient(purple, purple) bottom/ 100% calc(100% - 20vw) no-repeat,
green;
}
<div class="container">
</div>
You can try adding preserveAspectRatio="none" to the svg tag. This does seem to mess with the position a bit but might be a good start.
.container {
width: 100%;
background: green;
height: 760px;
}
svg {
width: 100%;
}
svg path {
width: 100%;
}
<div class="container">
<svg width="1440" height="760" viewBox="0 0 1440 760" fill="none" preserveAspectRatio="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M677.112 54.1657C400.36 -43.9336 110.391 13.291 0 54.1657V760H1440V54.1657C1301.02 95.0404 953.865 152.265 677.112 54.1657Z"
fill="purple"
/>
</svg>
</div>
I want to make that wave effect over a parallax background image.
So far I have the parallax effect and full-width (over parent container width).
section.parallax {
width: 100vw;
position: relative;
margin-left: -50vw;
left: 50%;
background-image: url(../images/parallax.jpg); // this image
height: 500px;
background-attachment: fixed;
background-position: center;
background-repeat: no-repeat;
background-size: cover;
}
What can I do to have that wave effect on the image top and bottom with CSS? Is it possible?
Here is an idea using SVG and multiple background. Simply adjust the path of the SVG to fit your needs:
.container {
width: 500px;
height: 400px;
background:
url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="500" ><path d="M0 48 C30 60 38 40 64 48 L64 64 L0 64 Z" fill="white" stroke="rgba(255,255,255,0.5)" stroke-width="5"/></svg>') bottom,
url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="500" ><path d="M0 10 C30 20 38 2 64 10 L64 0 L0 0 Z" fill="white" stroke="rgba(255,255,255,0.5)" stroke-width="5"/></svg>') top,
url(https://picsum.photos/2000/1000?image=1069) center/cover;
}
<div class="container">
</div>
I have moving parallax elements overlaying a large header image, however I can't seem to figure out how to separate the two so that the header image isn't affected by the parallax movement.
I'd like for only the circles to be moving upwards as you scroll, but it looks like the header image is attached to the same movement as the black circle.
Something I've tried was taking
<div class="background">...</div>
outside of
<div class="parallax">...</div>
but then the circles were no longer overlaying the header image.
Here is my JSFiddle: https://jsfiddle.net/uk0x33mj/3/
Thank you - I really appreciate the help!
As I understood you, you need something like that. Please let me know, if you need something else.
.parallax {
perspective: 1px;
height: 100vh;
overflow-x: hidden;
overflow-y: auto;
}
.parallax__layer {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index:9999;
}
.parallax__layer--base {
transform: translateZ(0);
}
.parallax__layer--back {
transform: translateZ(-1px) scale(2);
}
.circle {
position:absolute;
top:400px;
left:300px;
color:#ffffff;
}
.circle_2 {
position:absolute;
top:300px;
}
.background {
background:red;
background-image: url('http://i59.tinypic.com/2eofekz.jpg');
background-size: cover;
height: 350px;
width: 100%;
position: fixed;
}
.spacer {
height:1000px;
}
<div class="background">
</div>
<div class="parallax">
<div class="parallax__layer parallax__layer--back">
<svg class="circle_2" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="576px" height="576px" viewBox="0 0 576 576" enable-background="new 0 0 576 576" xml:space="preserve">
<circle fill="#EC008C" cx="63.215" cy="61.778" r="41.83"/>
</svg>
</div>
<div class="parallax__layer parallax__layer--base">
<svg class="circle" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="576px" height="576px" viewBox="0 0 576 576" enable-background="new 0 0 576 576" xml:space="preserve">
<circle fill="#231F20" cx="63.215" cy="61.778" r="41.83"/>
</svg>
</div>
<div class="spacer"></div>
</div>