Video with Clip Path is not showing / working in Safari - html

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 🤦

Related

why do I need background-size 200% instead of cover

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>

How to get an SVG to have a fluid width without changing its height?

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>

SVG + CSS; Clippath in flexbox environment

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>

How do you separate parallax elements from header?

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>

How to create a polygon shape div

I would like to create HTML element like on image here:
A problem is the DIV element has polygon shape instead of regular rectangle, will be placed above other elements as something like popup and inside that element there is necessary to show an image with rectangular shape in source but showed on web like filling all space included triangle on the left side.
Do you think is there any possibility to realize that without preparing showed images as transparent PNGs in proper polygon format? Only by CSS3 transform or use canvas or SVG?
One method could be to split the image into two containers which are 50% the size of the parent, transform each of them separately and position the backgrounds to look like they are one single image. The transform could either be a skew (used in the answer) or a perspective based rotation.
Note that since we are transforming the container, we have to apply the reverse effect to the actual image for it to look normal.
.image {
position: relative;
height: 150px;
width: 450px;
overflow: hidden;
}
.top-container,
.bottom-container {
position: absolute;
left: 0px;
height: 50%;
width: 100%;
overflow: hidden;
backface-visibility: hidden;
}
.top-container {
top: 0px;
transform-origin: right bottom;
transform: skew(-20deg);
}
.bottom-container {
bottom: 0px;
transform-origin: right top;
transform: skew(20deg);
background-position: 0% 100%;
}
.top-container:after,
.bottom-container:after {
position: absolute;
content: '';
height: 100%;
width: 100%;
left: -14px; /* tan(20) * (height/2) / 2 */
background: url(http://lorempixel.com/450/150);
background-size: 100% 200%;
}
.top-container:after {
top: 0px;
transform: skew(20deg);
}
.bottom-container:after {
bottom: 0px;
transform: skew(-20deg);
background-position: 0% 100%;
}
/* Just for demo */
body {
background: linear-gradient(90deg, crimson, indianred, purple);
}
.image2 {
margin-top: 10px;
height: 150px;
width: 450px;
background: url(http://lorempixel.com/450/150);
}
<div class="image">
<div class='top-container'></div>
<div class='bottom-container'></div>
</div>
<!-- this is the actual image for comparison -->
<h3>Original Image</h3>
<div class='image2'></div>
I was about to suggest usage of SVG and clipPath but since Persijn has already posted that sample, I have added below a different version with polygon.
.vector {
position: relative;
height: 150px;
width: 450px;
}
svg {
position: absolute;
top: 0px;
left: 0px;
height: 100%;
width: 100%;
}
polygon {
fill: url(#image);
}
/* Just for demo */
body {
background: linear-gradient(90deg, crimson, indianred, purple);
}
<div class='vector'>
<svg viewBox='0 0 450 150' preserveAspectRatio='none'>
<defs>
<pattern id='image' height='150' width='450' patternUnits='userSpaceOnUse'>
<image xlink:href='http://lorempixel.com/450/150' height='150' width='450' />
</pattern>
</defs>
<polygon points='15,0 450,0 450,150 15,150 0,75' />
</svg>
</div>
SVG
Fiddle example
Solution found by Jbutler438
using a clip-path and image tag in svg you can easily cut out an arrow shape at the front.
<?xml version="1.0" ?>
<svg width="300px" height="300px" viewBox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg">
<defs>
<clipPath id="myClip">
<path d="M30 0, 100 0, 100 100, 30 100 0,50Z" />
</clipPath>
</defs>
<image xlink:href="http://lorempixel.com/300/300" x="0" y="0" width="100%" height="100%" clip-path="url(#myClip)" />
</svg>