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;
}
Related
The "logo" appearing as a yellow SVG circle below can be scaled by adjusting the height ratio (line indicated by <==== (1) in the code), enabling tuning without modifying the SVG itself.
But even though .left_center_myicon is mostly duplicated in .right_center_myicon, the same tuning in <==== (2) does not affect the radio button icons.
How can I center scaled radio button icons in their DIV? I'm using here inline SVGs as even changing them to be linked (from <svg> to <img src="xyz.svg"> is itself a brittle and subtle change. If you see that difficulty, please switch to linked SVGs in your answer.
Update
I'd like the radio buttons to be vertically centered in their div, while that div is itself vertically centered and right justified in the header.
Ideally, I'd also like to be able to adjust the scale of the SVG radio button icons from the style file (although I'm starting to wonder whether doing so might be going against the grain of established custom—in other words, I'm wondering if perhaps designers end up editing the SVG files rather than manipulating the scale of the SVGs from CSS).
.header {
width: 100%;
height: 300px;
background-color: #ddd;
margin: 5px;
align-items:center;
display: block;
text-align: center;
}
.left_center_myicon {
margin: 0 auto;
background-color: #bbb;
float: left;
height: 70%; /* <==== (1) */
position: relative;
top: 50%;
left: 0;
transform: translate(0%, -50%);
}
.right_center_myicon {
background-color: #ccc;
margin: 0 auto;
float: right;
height: 70%; /* <==== (2) */
position: relative;
top: 50%;
left: 0;
transform: translate(0%, -50%);
vertical-align: middle;
}
svg { stroke:black; stroke-width:5; opacity:0.5; vertical-align: middle; }
<div class="header">
<a href="index.html">
<img class="left_center_myicon" src="svg/logo.svg"/>
</a>
<div class="right_center_myicon">
<label class="myLabel">
<input type="radio" name="radioGroup" class="myradioG" checked>
<svg width="100" height="100" viewBox="0 0 100 100">
<circle cx="50" cy="50" r="30" style="fill:blue;" />
</svg>
</label>
<label class="inline-radio">
<input type="radio" name="radioGroup" class="myradioG">
<svg width="100" height="100" viewBox="0 0 100 100">
<rect x="20" y="20" rx="15" ry="15" width="60" height="60" style="fill:red;" />
</svg>
</label>
</div>
</div>
The content of logo.svg is:
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="160" height="120"
viewBox="0 0 160 120"
version="1.1">
<g>
<circle cx="80" cy="60" r="50" fill="yellow" stroke="blue" stroke-width="10" />
</g>
</svg>
When in doubt, flexbox all the things. And add some wrappers... and a spacer.
I find CSS float maddening to work with, so I avoid it like the plague. And to answer your other question, whenever possible I include my svgs inline so the inner components can still be targeted/styled with CSS. This approach should work with either though.
I tried making a fiddle but couldn't get even the simplest code to work or display anything, so I'm not sure if that's me or them.... Works great locally in my browser though. https://imgur.com/AWrWK8Z
I made 2 additions, a middle spacer element set to flex grow so it takes up all the available space it can, pushing the other elements far to the right/left. And wrappers around the input/label pairs (and the lone left guy). I used flex on both the header container and the right and left child containers, to simplify vertical centering.
.header {
width: 100%;
height: 300px;
display: flex;
align-items: center;
background-color: #ddd;
}
.spacer {
flex: 1 0 auto;
background: rgba(200,200,200,1);
}
.left {
background-color: #bbb;
}
.right {
background-color: #ccc;
}
.wrapper {
display: flex;
height: 70%;
align-items: center;
outline: 1px solid blue;
}
.wrapper > div {
flex: 1 1 auto;
outline: 1px solid black;
}
<div class="header">
<div class="left wrapper">
<div>
<a>
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="160" height="120"
viewBox="0 0 160 120"
version="1.1">
<g>
<circle cx="80" cy="60" r="50" fill="yellow" stroke="blue" stroke-width="10" />
</g>
</svg>
</a>
</div>
</div>
<div class="spacer"></div>
<div class="right wrapper">
<div>
<label class="myLabel">
<input type="radio" name="radioGroup" class="myradioG" checked>
<svg width="100" height="100" viewBox="0 0 100 100">
<circle cx="50" cy="50" r="30" style="fill:blue;" />
</svg>
</label>
</div>
<div>
<label class="inline-radio">
<input type="radio" name="radioGroup" class="myradioG">
<svg width="100" height="100" viewBox="0 0 100 100">
<rect x="20" y="20" rx="15" ry="15" width="60" height="60" style="fill:red;" />
</svg>
</label>
</div>
</div>
</div>
I'm trying to build a page with 2 polygons, but i'm facing some problems with aspect ratio on mobile or tablet mode.
Check the codepen and resize the window, you will see that the red triangle doesn't keep correct shape as well as the icon inside.
Would be really nice if you can help me to accomplish this.
Best regards and thanks a lot
body {
overflow: hidden;
}
.wrap-layer {
position:absolute;
top:0;
height:100%;
width:100%;
min-height: 100%;
min-width: 100%;
}
.content {
position: absolute;
z-index:1;
top: 50%;
right:55%;
color: #fff;
}
svg {
width: 100%;
height: 100%;
min-height: 100%;
}
#play {
content: "\e907";
font-family: 'icomoon' !important;
fill: #fff;
font-size:5px;
}
<body>
<div class="wrap-layer">
<div class="content">
<h1>Bla bla</h1>
<p>lorem ipsum</p>
</div>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100%" height="100%" viewBox="0 0 100 100" preserveAspectRatio="none">
<polygon id="blue" points="80 0, 50 100, 0 100, 0 0" fill="#000" />
<!-- HOW TO KEEP SHAPE OF THE RED TRIANGLE IN RESPONSIVE -->
<!-- HOW ADD font icon and KEEP THE SHAPE -->
<g>
<polygon id="trigger-play" points="50 100, 56 80, 62 100" fill="red" />
<text id="play" x=53 y=95></text>
</g>
</svg>
</div>
</body>
Codepen : https://codepen.io/lulu2312/pen/oVQegd
Change the preserveAspectRatio="none" attribute to:
preserveAspectRatio="xMidYMax slice"
The xMid part means centre in the X direction. YMax means bottom align in the Y direction. The purpose of that is to ensure the red triangle will be visible. The slice means grow the SVG so that it completely fills the parent, overflowing if necessary. Basically the same as CSS's background-size: cover.
You can learn more about how preserveAspectRatio works in the SVG specification.
https://www.w3.org/TR/SVG11/single-page.html#coords-PreserveAspectRatioAttribute
If the current angles and shapes are not what you want, then you will need to redesign the SVG so it has a different aspect ratio. At the moment it is 1:1 (square).
body {
overflow: hidden;
}
.wrap-layer {
position:absolute;
top:0;
height:100%;
width:100%;
min-height: 100%;
min-width: 100%;
}
.content {
position: absolute;
z-index:1;
top: 50%;
right:55%;
color: #fff;
}
svg {
width: 100%;
height: 100%;
min-height: 100%;
}
#play {
content: "\e907";
font-family: 'icomoon' !important;
fill: #fff;
font-size:5px;
}
<div class="wrap-layer">
<div class="content">
<h1>Bla bla</h1>
<p>lorem ipsum</p>
</div>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100%" height="100%" viewBox="0 0 100 100" preserveAspectRatio="xMidYMax slice">
<polygon id="blue" points="80 0, 50 100, 0 100, 0 0" fill="#000" />
<!-- HOW TO KEEP SHAPE OF THE RED TRIANGLE IN RESPONSIVE -->
<!-- HOW ADD font icon and KEEP THE SHAPE -->
<g>
<polygon id="trigger-play" points="50 100, 56 80, 62 100" fill="red" />
<text id="play" x=53 y=95></text>
</g>
</svg>
</div>
https://codepen.io/PaulLeBeau/pen/BbGwKp
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>
I am trying to let float an underlying div to a svg. problem is: when i reduce the screenwidt, the distance between the svg and the underlying div increases.
How can i achieve that the div under the svg always floats against the svg without whitespace?
This is my code:
<div class="svg">
<svg viewBox="0 0 1439 150" style="position:fixed; top:250px; left:0;" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Sell-on-FG-Flow" transform="translate(-1.000000, -2412.000000)" fill="#1e90ff">
<g id="Customer-Section" transform="translate(1.000000, 1026.000000)">
<g id="loading" transform="translate(0.000000, 1386.807849)">
-----pathes are here ---
</g>
</g>
</g>
</g>
</svg>
</div>
<div class="under">
let the red div float against the waves
</div>
And the css:
.svg {
height: 400px;
width: 100%;
}
.under {
height: 40px;
background: red;
}
Fiddle: https://jsfiddle.net/45b3n5q8/1/
Position fixed inline style in the SVG removes the element from the document flow and it will behave like an absolute position, remove the inline style from the svg and it should be ok, there's a small margin that can be removed with a negative margin top.
.under {
background: red;
margin-top: -5px;
}
see pen
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>