Make border clip other elements and show background content - html

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>

Related

How to fill a SVG with the opposite background-color?

I have a div where there is an SVG with the following code:
HTML
<div>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<path d="M10.97 4.97a.75.75 0 0 1 1.07 1.05l-3.99 4.99a.75.75 0 0 1-1.08.02L4.324 8.384a.75.75 0 1 1 1.06-1.06l2.094 2.093 3.473-4.425a.267.267 0 0 1 .02-.022z"/>
</svg>
</div>
CSS
div {
background: linear-gradient(
to bottom right,
var(--norm-col) 0%,
var(--norm-col) 50%,
var(--bg-color) 50%,
var(--bg-color) 100%);
}
div svg {
width: 30px;
height: 30px;
mix-blend-mode: difference;
}
I want to fill the SVG white when it's on the black side, and black when it's on the white side.
mix-blend-mode works fine. Post your code please - something else must be going wrong.
div {
background: linear-gradient(
to bottom right,
black 0%,
black 50%,
white 50%,
white 100%);
}
#test {
position: absolute;
top: 30px;
left: 30px;
width: 400px;
height: 400px;
}
#testSVG {
mix-blend-mode: difference;
}
body {
background: blue;
}
<div id="test">
<svg id="testSVG" width="300px" height="300px">
<circle r="100" cx="150" cy="150" fill="white"/>
</svg>
</div>

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>

Hover event on hidden part of the div

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>

How to give border radius to make an element look like this image?

I am trying to make .main-div like this image
.main-div {
width: 100px;
height: 100px;
background-color: Red;
border-radius: 30px/20px;
}
<div class="main-div"></div>
My JSFiddle is here.
You can do a trick using a pseudo element and achieve that shape
body {
background: lightgray;
}
.main-div {
position: relative;
display: inline-block;
width: 110px;
height: 100px;
background-color: red;
border-radius: 30%/50%;
background: url(https://i.stack.imgur.com/CWoXa.png) center center no-repeat;
background-size: 110px 110px;
}
.main-div::after {
content: '';
position: absolute;
left: 5px;
top: -5px;
width: 100px;
height: 110px;
background: inherit;
background-size: inherit;
border-radius: 50%/30%;
}
.main-div+.main-div {
background: gray;
}
<div class="main-div"></div>
<div class="main-div"></div>
As Justinas remarked in their answer, the border of your example image does not look like it can be recreated with border-radius alone. This is because the outline is not an ellipse.
It is possible to do this, with good browser support, using SVG as follows.
/* set size of and center SVG */
svg {
display: block;
width: 200px;
height: 200px;
margin: 0 auto;
}
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<clipPath id="outline">
<!-- use Bezier curves to define outline -->
<path d="M 0 100
C 0 0, 40 0, 100 0
C 160 0, 200 0, 200 100
C 200 200, 160 200, 100 200
C 40 200, 0 200, 0 100
Z" />
</clipPath>
</defs>
<image x="0" y="0" width="200" height="200"
xlink:href="https://placehold.it/200"
clip-path="url(#outline)" />
</svg>
This uses clipping in SVG with the clipPath element. You can define any path to use for the clipping. I have used four Bezier curves here. You can tweak where the control points are, or change this to use something entirely different if you wish.
An extra bonus of this approach is that it is now easy to apply other (advanced) filters, for example blurring the image or applying a drop shadow.
/* set size of and center SVG */
svg {
display: block;
width: 204px;
height: 204px;
margin: 0 auto;
}
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<clipPath id="outline">
<!-- use Bezier curves to define outline -->
<path d="M 0 100
C 0 0, 40 0, 100 0
C 160 0, 200 0, 200 100
C 200 200, 160 200, 100 200
C 40 200, 0 200, 0 100
Z" />
</clipPath>
<filter id="dropshadow" x="-30%" y="-30%"
width="160%" height="160%"
color-interpolation-filters="sRGB">
<!-- define color of shadow here -->
<feComponentTransfer in="SourceAlpha">
<feFuncR type="linear" slope="0"
intercept="0.518"></feFuncR>
<feFuncG type="linear" slope="0"
intercept="0.698"></feFuncG>
<feFuncB type="linear" slope="0"
intercept="0.867"></feFuncB>
</feComponentTransfer>
<!-- define blur of shadow here -->
<feGaussianBlur stdDeviation="2" />
<!-- we can offset the shadow -->
<feOffset result="shadow" dx="1" dy="1" />
<!-- put shadow below original content -->
<feBlend in="SourceGraphic"
in2="shadow" mode="normal" />
</filter>
</defs>
<g transform="translate(2, 2)"
filter="url(#dropshadow)">
<image x="0" y="0" width="200" height="200"
xlink:href="https://placehold.it/200"
clip-path="url(#outline)" />
</g>
</svg>
Your image radius does not look like standard CSS border radius. If yes, than you need to use image preprocessing (in back-end side, e.g. GD or stand-alone tool like Photoshop) or use Clipping Mask with limited support. Using border radius you can have similar effect.
.main-div {
width: 100px;
height: 100px;
background-color: red;
border-radius: 40%;
overflow: hidden;
position: relative;
}
.main-div img {
width: 100%;
position: absolute;
left: -50px;
top: -50px;
margin-top: 50%;
margin-left: 50%;
}
<div class="main-div">
<img src="http://lorempixel.com/200/200/"/>
</div>
Add this style. You can change border-radius as per your requirements:
div {
border: 2px solid #a1a1a1;
padding: 10px 15px; `enter code here`
background: #dddddd;
width: 100px;
border-radius: 55px;
}
.element {
border-radius: 50px;
overflow: hidden;
}
<img src="https://image.ibb.co/irvmO5/html5.png" alt="html5" border="0" class="element"><br /><a target='_blank' href='https://imgbb.com/'>Rounded rectangle clip mask</a>