Hover event on hidden part of the div - html

I have the following sample html with css.
My probem is, when I move the mouse over the top coners of the parent html element, the hover role become active. But it should not be, because it is a hidden part of the parent.
It is working correctly in firefox, but not in chrome, opera, ie or edge.
Any suggestions?
It is a browser related bug or it is working as intended?
If I remove the position properties from the css, then it is working properly, but is not an option.
.perent{
top: 0px;
right: 0px;
width: 500px;
height: 500px;
background-color:red;
border-radius:50%;
overflow:hidden;
position:relative;
}
.child{
width: 1000px;
height: 200px;
background-color:blue;
position:absolute;
}
.child:HOVER{
background-color:black;
}
<div class="perent">
<div class="child">
</div>
</div>

For a completely round cut, use this:
Add this:
.perent {
-webkit-clip-path: circle(50.0% at 50% 50%);
clip-path: circle(50.0% at 50% 50%);
}

Although I am not sure if it is a browser bug or not, but I can suggest using svg
body {
margin: 0;
}
svg {
height: 100vh;
}
.child:hover {
fill: black;
}
<svg viewbox="0 0 100 100">
<defs>
<clipPath id="clipPath">
<circle r="50" cx="50" cy="50"/>
</clipPath>
</defs>
<rect class="child" x="0" y="0" width="100" height="40" fill= "blue" clip-path="url(#clipPath)"/>
<rect x="0" y="40" width="100" height="60" fill="red" clip-path="url(#clipPath)"/>
</svg>

Related

SVG mask not loading initially in Chrome

Working on a project which is using a SVG mask on the homepage hero component but for some reason the text in the mask only shows when I resize the window. It's not showing on the initial page load. This is happening only in Chrome (latest version).
You can view the example on the STAGING environment here: https://staging.erwconstructions.com.au/
HTML Markup is:
<section data-component="mask-hero" class="in-view mask-hero">
<picture>
<img src="https://staging.erwconstructions.com.au/wp-content/uploads/2020/07/home-hero.jpg" alt="Home">
<svg width="100%" height="100%" viewBox="0 0 100% 100%">
<defs>
<linearGradient id="gradient">
<stop offset="100%" stop-color="black" />
</linearGradient>
<mask id="mask">
<rect width="100%" height="100%" fill="#fff" />
<text x="0" y="50%">
<tspan x="5vw" dy="-.1em">Building</tspan>
<tspan x="5vw" dy="1em">Redefined</tspan>
</text>
</mask>
</defs>
<rect width="100%" height="100%" fill="url(#gradient)" fill-opacity="0.9" mask="url(#mask)" />
</svg>
</picture>
</section>
The CSS is:
[data-component="mask-hero"] {
height: 100vh;
padding: 0;
background: none;
& picture {
display: block;
height: 100vh;
& img {
height: 100%;
object-fit: cover;
object-position: center;
position: fixed;
will-change: transform;
width: 100%;
z-index: -1;
}
& svg {
display: block;
height: 100%;
}
& text {
font-family: var(--defaultFont);
font-weight: var(--bold);
font-size: 3em;
#media (--app-breakpoint-2) {
font-size: 6em;
}
#media (--app-breakpoint-4) {
font-size: 8em;
}
#media (--app-breakpoint-5) {
font-size: 14em;
}
}
}
}
For some reason there is also a console error regarding the viewBox, even though the correct attributes are set on the SVG:
Error: <svg> attribute viewBox: Expected number, "0 0 100% 100%".
Any help would be greatly appreciated.
Thanks,
Dayne
By the given error, I'd guess to problem is with the viewBox. It should be given an absolute number in px, not percent. Like <svg viewBox="0 0 100 100">
Have you tried using javascript to make it work ?
This code below adds background color to white on rect inside svg code to show the text when the page has loaded.
var svgRect = document.querySelector('svg rect');document.addEventListener("DOMContentLoaded", function(){ setTimeout(function() { svgRect.style.backgroundColor = 'white'; }, 500); });

CSS svg hover animation/transition

im using a svg clip-path as mask for an image.
Now i want an inner border inside it on hover.
So i made a second clip-path for hover but the transition doesnt affect it.
I want the border comming from the sides (reducing zoom/negative scaling).
Here you can see what i want without working animation/transition:
body {
background: #ccc;
}
.clip-svg {
position: relative;
display: block;
height: 400px;
width: 300px;
background-position: center center;
background-size: auto 100%;
clip-path: url(#Emblem);
transition: 0.4s all ease;
}
.clip-svg:hover {
clip-path: url(#Emblem2);
}
<div class="clip-svg" style="background-image: url(https://images.pexels.com/photos/864994/pexels-photo-864994.jpeg?auto=compress&cs=tinysrgb&h=750&w=1260)"></div>
<svg width="0" height="0">
<defs>
<clipPath id="Emblem">
<path d="M279,240c0,96-139.4,145-139.4,145S22,336,22,240c0-58,0-203,0-203s65-11,129-11c75,0,128,11,128,11S279,136,279,240z"/>
</clipPath>
<clipPath id="Emblem2">
<path d="M39,51.6V240c0,72.4,80.9,116.6,101.2,126.5c11-4.5,35.7-15.4,59.8-32.3c18.5-13,33.2-26.8,43.6-41.3
c12.2-17,18.4-34.8,18.4-53V51.3C240.8,48,200.9,43,151,43C106.3,43,59.9,48.7,39,51.6z"/>
<path d="M151,26C87,26,22,37,22,37s0,145,0,203c0,96,117.6,145,117.6,145S279,336,279,240c0-104,0-203,0-203S226,26,151,26z
M270,240c0,19.9-6.7,39.3-19.9,57.7c-10.9,15.1-26.2,29.7-45.5,43.1c-26.2,18.3-52.8,29.8-63.1,33.8l-1.6,0.6l-1.6-0.8
c-10.4-5-37.2-18.9-61.3-41.3c-30.5-28.4-46-59.7-46-93.2V44.7l3.4-0.5C53.5,41.4,103.1,35,151,35c53.2,0,95.3,5.6,115.6,8.9
l3.4,0.5V240z"/>
</clipPath>
</defs>
</svg>
<br/>
Image: https://www.pexels.com/...d-tablet-864994/
Thanks in advance
I would consider two layers each one using a clip-path and I would control the opacity:
body {
background: #ccc;
}
.clip-svg {
position: relative;
display: inline-block;
height: 400px;
width: 300px;
}
.clip-svg::before,
.clip-svg::after {
content: "";
position: absolute;
top: 0;
right: 0;
left: 0;
bottom: 0;
background-position: center center;
background-size: auto 100%;
background-image: var(--i);
transition: 0.8s all ease;
}
.clip-svg::before {
clip-path: url(#Emblem2);
}
.clip-svg::after {
clip-path: url(#Emblem);
}
.clip-svg:hover::after {
opacity:0;
}
<div class="clip-svg" style="--i: url(https://images.pexels.com/photos/864994/pexels-photo-864994.jpeg?auto=compress&cs=tinysrgb&h=750&w=1260)"></div>
<svg width="0" height="0">
<defs>
<clipPath id="Emblem">
<path d="M279,240c0,96-139.4,145-139.4,145S22,336,22,240c0-58,0-203,0-203s65-11,129-11c75,0,128,11,128,11S279,136,279,240z"/>
</clipPath>
<clipPath id="Emblem2">
<path d="M39,51.6V240c0,72.4,80.9,116.6,101.2,126.5c11-4.5,35.7-15.4,59.8-32.3c18.5-13,33.2-26.8,43.6-41.3
c12.2-17,18.4-34.8,18.4-53V51.3C240.8,48,200.9,43,151,43C106.3,43,59.9,48.7,39,51.6z"/>
<path d="M151,26C87,26,22,37,22,37s0,145,0,203c0,96,117.6,145,117.6,145S279,336,279,240c0-104,0-203,0-203S226,26,151,26z
M270,240c0,19.9-6.7,39.3-19.9,57.7c-10.9,15.1-26.2,29.7-45.5,43.1c-26.2,18.3-52.8,29.8-63.1,33.8l-1.6,0.6l-1.6-0.8
c-10.4-5-37.2-18.9-61.3-41.3c-30.5-28.4-46-59.7-46-93.2V44.7l3.4-0.5C53.5,41.4,103.1,35,151,35c53.2,0,95.3,5.6,115.6,8.9
l3.4,0.5V240z"/>
</clipPath>
</defs>
</svg>
I don't see a way to achieve what you want using clip paths on an HTML element. You can only replace one clip path with another in CSS. You can't interpolate between two of them.
However it is fairly easy to do, if you are okay with moving the image into an SVG. Then you can do whatever you want with the inner border.
Note however, with this solution, the inner border is not a clip path, so it doesn't make the image transparent. I don't know if that is important to you or not. It should be possible to do that if you really need it to.
body {
background: #ccc;
}
.clip-svg .emblem2-ref {
transform-origin: 150px 200px;
transform: scale(1.2, 1.2);
transition: 0.4s all ease;
}
.clip-svg:hover .emblem2-ref {
transform: scale(1, 1);
}
#Emblem2 {
fill: #ccc;
}
<!-- Clip path and inner border definitions. Can be included once and used by multiple SVGs -->
<svg width="0" height="0">
<defs>
<clipPath id="Emblem">
<path d="M279,240c0,96-139.4,145-139.4,145S22,336,22,240c0-58,0-203,0-203s65-11,129-11c75,0,128,11,128,11S279,136,279,240z"/>
</clipPath>
<path id="Emblem2"
d="M39,51.6V240c0,72.4,80.9,116.6,101.2,126.5c11-4.5,35.7-15.4,59.8-32.3c18.5-13,33.2-26.8,43.6-41.3
c12.2-17,18.4-34.8,18.4-53V51.3C240.8,48,200.9,43,151,43C106.3,43,59.9,48.7,39,51.6z
M270,240c0,19.9-6.7,39.3-19.9,57.7c-10.9,15.1-26.2,29.7-45.5,43.1c-26.2,18.3-52.8,29.8-63.1,33.8l-1.6,0.6l-1.6-0.8
c-10.4-5-37.2-18.9-61.3-41.3c-30.5-28.4-46-59.7-46-93.2V44.7l3.4-0.5C53.5,41.4,103.1,35,151,35c53.2,0,95.3,5.6,115.6,8.9
l3.4,0.5V240z"/>
</defs>
</svg>
<!-- Will need one of these SVGs for every image you want to display -->
<svg width="300" height="400" class="clip-svg">
<g clip-path="url(#Emblem)">
<image width="300" height="400" preserveAspectRatio="xMidYMid slice"
xlink:href="https://images.pexels.com/photos/864994/pexels-photo-864994.jpeg?auto=compress&cs=tinysrgb&h=750&w=1260"/>
<use class="emblem2-ref" xlink:href="#Emblem2"/>
</g>
</svg>
<br/>
Image: https://www.pexels.com/...d-tablet-864994/

I want to implement SVG clip-path for SVG element

I want to implement SVG clip-path for SVG element. I have a DIV element in which I want to put SVG element which will act as a clipping mask, and also I have the separate SVG element that has an image to which the clipping mask will be applied.
The first problem I faced with is that clipping mask moves to the left top corner of the viewport but not located inside of the parent DIV element.
The second problem is that I want to make an image on the full screen not depending on the screen size.
Incorrect Mask Circle
Correct Mask Circle (what I want to have)
Do you have suggestions how to make it?
Thanks in advance!
html, body { margin:0; padding:0; overflow:hidden }
svg { position:absolute; top:0; left:0;}
.image-clip-src {
width: 100%;
height: 100%;
}
.svg-wrapper {
width: 72px;
height: 72px;
padding: 2.5em;
border: 1px solid #4D4F51;
margin: 0 auto;
border-radius: 50%;
overflow: hidden;
position: fixed;
top: 55%;
z-index: 9;
left: 64%;
transform: translateY(-50%);
cursor: pointer;
}
.clipped-image image {
clip-path: url(#clipping);
}
<svg class="clipped-image" width="100%" height="100%" viewBox="0 0 1440 960" preserveAspectRatio="xMinYMin meet">
<image class="image-clip-src" xlink:href="https://images.unsplash.com/photo-1526327227970-4bda49fa3489?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=3c4bce33d96df6b18af53fb2dae3363e&auto=format&fit=crop&w=1650&q=80" width="100%" height="100%" overflow="visible"/>
</svg>
<div class="svg-wrapper">
<svg class="svg-defs">
<defs>
<clipPath id="clipping">
<circle r="72" stroke="black" stroke-width="3"/>
</clipPath>
</defs>
</svg>
</div>
That's not the way SVG works.
When you tell something to use a clip path, all it sees is the clip path definition itself. It doesn't know or care about where on the page you have positioned it's parent <svg>.
If you want the clip circle to be at a certain position on the water image, you need to specify its position using cx and cy.
html, body { margin:0; padding:0; overflow:hidden }
svg { position:absolute; top:0; left:0;}
.image-clip-src {
width: 100%;
height: 100%;
}
.clipped-image image {
clip-path: url(#clipping);
}
<svg class="clipped-image" width="100%" height="100%" viewBox="0 0 1440 960" preserveAspectRatio="xMinYMin meet">
<defs>
<clipPath id="clipping">
<circle cx="64%" cy="55%" r="72" stroke="black" stroke-width="3"/>
</clipPath>
</defs>
<image class="image-clip-src" xlink:href="https://images.unsplash.com/photo-1526327227970-4bda49fa3489?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=3c4bce33d96df6b18af53fb2dae3363e&auto=format&fit=crop&w=1650&q=80" width="100%" height="100%" overflow="visible"/>
<circle cx="64%" cy="55%" r="72" fill="none" stroke="#4D4F51" stroke-width="1"/>
</svg>

Make border clip other elements and show background content

I'm trying to create a spinner where two dots intersect and the foremost one should clip the other letting the background be visible on few pixels of intersection.
It would be okay to use SVG if CSS isn't capable of this, but at the moment I can't find a way to achieve the effect in neither of the technologies.
I tried with clip-path but it doesn't seem to do what am I trying to do.
Ideas?
body {
background-image: linear-gradient(to right, yellow 0%, purple 100%);
}
.a, .b {
width: 50px;
height: 50px;
border-radius: 100%;
position: absolute;
top: 5em;
left: 50vw;
border: 4px solid white;
}
.a {
background: red;
}
.b {
background-color: blue;
margin-left: 30px;
}
<div class="a"></div>
<div class="b"></div>
It's easy to do in SVG. However you'll want to use a <mask> rather than a <clipPath>.
body {
background-image: linear-gradient(to right, yellow 0%, purple 100%);
}
svg {
margin: 5em 0 0 50vw;
}
<svg width="80" height="50">
<defs>
<mask id="clipred">
<rect width="100%" height="100%" fill="white"/>
<circle cx="55" cy="25" r="29" fill="black"/>
</mask>
</defs>
<circle cx="25" cy="25" r="25" fill="red" mask="url(#clipred)"/>
<circle cx="55" cy="25" r="25" fill="blue"/>
</svg>

positioning multiple images that are masked by an svg

I've created an animation where 2 images are being masked by two different inline svg polygons. Img1 appears, then its polygon <clipPath> animates. Img2 then appears, followed by its polygon <clipPath> animating. All of this is working as it should, except that the images should be stacked on top of each other so that img2 ultimately covers up img1. Img2 instead appears below img1.
Each image is set within an <svg>, so I've tried setting each <svg> within its own <div> and setting the position to absolute. I've also looked into modifying the <svg> viewbox. Neither of these things has worked. Clearly I'm missing something or doing something wrong. Can someone help?
Here is a working jsfiddle that illustrates the problem.
This is the html:
<body>
<div id="container">
<div id="border"></div>
<!--------masked images-------->
<div id="img1Masked">
<svg width="300" height="250" viewbox="0 0 300 250">
<image xlink:href="https://static.dvidshub.net/media/thumbs/photos/1210/692947/463x486_q75.jpg" x="0" y="0" width="463" height="486" />
</svg>
</div>
<div id="img2Masked">
<svg width="300" height="250" viewbox="0 0 300 250">
<image xlink:href="http://edinspace.weebly.com/uploads/5/8/4/4/5844875/3183867_orig.jpg" x="0" y="0" width="933" height="622" />
</svg>
</div>
<!--------polygon clipPaths-------->
<svg class="svg-defs">
<defs>
<clipPath id="clippingImg1">
<polygon id="img1Shape" points="90 250,302 250,299 -3,138 -3"/>
</clipPath>
</defs>
<defs>
<clipPath id="clippingImg2">
<polygon id="img2Shape" points="105 251,301 253,301 -3,66 -3"/>
</clipPath>
</defs>
</svg>
</div>
<script src="https://s0.2mdn.net/ads/studio/cached_libs/tweenmax_1.18.0_499ba64a23378545748ff12d372e59e9_min.js"></script>
</body>
And the CSS:
#container {
position:relative;
width:300px;
height:250px;
background-color:#fff;
overflow:visible;
}
#img1Masked image{
position:absolute;
clip-path: url(#clippingImg1);
opacity:0;
top:0;
left:0;
}
#img2Masked image{
position:absolute;
clip-path: url(#clippingImg2);
opacity:0;
top:0;
left:0;
}
.svg-defs {
position: absolute;
width: 0;
height: 0;
}
#border{
position:absolute;
width:298px;
height:248px;
border:solid 1px #000;
}
You have to absolute positioning #img1Masked and #img2Masked.
#img1Masked,
#img2Masked {
position: absolute;
top: 0;
left: 0;
}