clipPath cut off by container - html

So I am pretty close to my desired effect, the issue though is that the clipPath I am using while rotating gets cut off by the container. Is there a way to remedy this? I tried messing with the viewBox and other properties but to no avail. I am not super well versed in using clipPath. Would using CSS clip-path be a better call and just rotate a pseudo element the opposite way?
.red {
background-image: url('https://cdn.mos.cms.futurecdn.net/u8wSHMmMMXzZuAFBCmcsCK-650-80.jpg');
background-size: 90%;
height: 100vh;
width: 700px;
clip-path: url(#clipPolygon);
position: relative;
z-index: 2;
margin-top: 120px;
margin-left: 250px;
}
.bg {
position: absolute;
top: 0;
left: 0;
z-index: 1;
}
svg {
}
defs {
transition: all 5s;
transform: rotate(360deg);
}
<div class="red">
<svg>
<defs>
<clipPath id="clipPolygon">
<polygon points="200 250,400 100,300 50,0 0">
<animateTransform attributeName="transform" begin="0s" dur="2.5s" type="rotate" from="360 160 160" to="0 160 160" repeatCount="indefinite"/>
</polygon>
</clipPath>
</defs>
</svg>
</div>
<div class="bg">
<img src="https://www.mcgilvraydesign.com/img/bgdemo3.jpg" alt="">
</div>

You can use your polygon as a CSS mask then you can easily handle the rotation using two elements rotating in opposite direction
.red {
background:url(https://www.mcgilvraydesign.com/img/bgdemo3.jpg) center/contain no-repeat;
min-height:350px;
height: 100vh;
overflow:hidden;
}
.red > div {
/* control the mask here */
-webkit-mask:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 0 0 400 300"><polygon points="200 250,400 100,300 50,0 0"/></svg>')
center/ /* position */
300px 200px /* size */
no-repeat;
mask:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 0 0 400 300"><polygon points="200 250,400 100,300 50,0 0"/></svg>')
center/
300px 200px
no-repeat;
height:100%;
position:relative;
animation:rotate 2s linear infinite;
}
.red > div::before {
content:"";
position:absolute;
/*big values here to avoid the cut effet*/
top:-100%;
left:-100%;
right:-100%;
bottom:-100%;
/* */
/* Control the skull here */
background: url('https://cdn.mos.cms.futurecdn.net/u8wSHMmMMXzZuAFBCmcsCK-650-80.jpg')
50% 45%/ /* position */
22% auto /* size*/
no-repeat,
#fff;
animation:inherit;
animation-direction:reverse;
}
#keyframes rotate {
to {
transform:rotate(-360deg);
}
}
body {
margin:0;
}
<div class="red">
<div></div>
</div>

Related

Scale border on svg without viewbox

I have 2 svgs one has viewbox and the other doesn't. Both are 100% width of the parent. The first one scales with the viewbox and the second scales with the height of the parent, because I have a hover height transition.
The problem is that I want both to have the same stroke-width. I want the stroke to scale like it scales with the svg that has viewbox, but the stroke of the second rect always stays 2px.
How can I keep the functionality of scaling the height of the rect with it's parent, but also to have the same border width as the first svg?
body > div{
width: 100px;
height: 400px;
}
svg{
width: 100%;
stroke-width: 2px;
stroke: black;
}
.svg-with-viewbox rect{
fill: red;
}
div > div{
height: 50px;
width: 100%;
transition: 1.5s all;
}
div > div:hover{
height: 200px;
}
.scale-height{
fill: yellow;
height: 100%;
}
<div>
<svg class="svg-with-viewbox" viewbox="0 0 20 20">
<rect height="20" width="20"/>
</svg>
<div>
<svg class="scale-height">
<rect width="100%" height="100%">
</rect>
</svg>
</div>
</div>
You could use a drop-shadow() filter , so no matter if the svg part is rescaled, it will remain the same size around the transparent edges.
example
body>div {
width: 100px;
height: 400px;
}
svg {
width: 100%;
filter: /* on on each sides */
drop-shadow( 2px 0 black)
drop-shadow(-2px 0 black)
drop-shadow( 0 2px black)
drop-shadow( 0 -2px black);
margin: 2px;/* increase margin or padding to include the drop-shadow */
}
.svg-with-viewbox rect {
fill: red;
}
div>div {
height: 50px;
width: 100%;
transition: 1.5s all;
}
div>div:hover {
height: 200px;
}
.scale-height {
fill: yellow;
height: 100%;
}
<div>
<svg class="svg-with-viewbox" viewbox="0 0 20 20">
<rect height="20" width="20"/>
</svg>
<div>
<svg class="scale-height">
<rect width="100%" height="100%">
</rect>
</svg>
</div>
</div>

How to show an svg element with an fade in?

I have an svg element. How can i show it gradually (like an animation) from left to right?
You can use CSS #keyframes.
#keyframes stretchInFromLeft {
0% {
width: 100%;
}
100% {
width: 0;
}
}
img {
max-width: 100%;
width: 100%;
}
.wrapper {
position: relative;
}
.overlay {
animation: 1s ease-out 0s 1 stretchInFromLeft;
position: absolute;
top: 0;
right: 0;
background: #fff;
width: 0;
height: 100%;
}
<div class="wrapper">
<img src="https://i.stack.imgur.com/dta2g.jpg" />
<div class="overlay"></div>
</div>
Fiddle: https://jsfiddle.net/r034wcgp/1/
Source: css3 transition animation on load?
You could animate a SVG clipPath with jQuery animate() like this:
$("#cut-off-bottom rect").animate({width: "100%", duration:4000})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1440 320">
<clipPath id="cut-off-bottom">
<rect x="0" y="0" width="0" height="320" />
</clipPath>
<path fill="#0099ff" fill-opacity="1" clip-path="url(#cut-off-bottom)" d="M0,32L48,32C96,32,192,32,288,58.7C384,85,480,139,576,154.7C672,171,768,149,864,165.3C960,181,1056,235,1152,240C1248,245,1344,203,1392,181.3L1440,160L1440,320L1392,320C1344,320,1248,320,1152,320C1056,320,960,320,864,320C768,320,672,320,576,320C480,320,384,320,288,320C192,320,96,320,48,320L0,320Z"></path>
</svg>

Cut out shape of another shape in CSS - cross-browser compatibility

I have white and red, full circles, absolutely positioned divs. Is there a way that I can cut out all white circles to be transparent with CSS and to be cross-browser compatible? Looking for the most "primitive" way.
You can use border-radius for that.
Check this example:
.container {
background: black;
width: 490px;
height: 490px;
position: relative;
background: black url(http://www.planwallpaper.com/static/images/recycled_texture_background_by_sandeep_m-d6aeau9_PZ9chud.jpg) no-repeat -500px -500px;
}
.r1 {
width: 400px;
height: 400px;
border-radius: 400px;
border: 30px solid red;
position: absolute;
top: 10px;
left: 10px;
}
.r2 {
width: 300px;
height: 300px;
border-radius: 300px;
border: 30px solid red;
position: absolute;
top: 60px;
left: 60px;
}
.r3 {
width: 200px;
height: 200px;
border-radius: 200px;
border: 30px solid red;
position: absolute;
top: 110px;
left: 110px;
}
<div class="container">
<div class="r1"></div>
<div class="r2"></div>
<div class="r3"></div>
</div>
you may take a look at radial gradient:
html {
min-height: 100%;
background-image: radial-gradient(
circle /* a circle*/
closest-side at 50% 50% /* set as closed as possible to center*/,
transparent 0 /* from center */,
/* to */transparent 50px,
/* from */red 50px,
/* to */red 60px,
/*from */transparent 60px,
/* to */transparent 70px,
/* from */red 70px,
/* to */red 80px,
/* from */transparent 80px,
/* to */ transparent 100px,
/* from */ red 100px,
/* to */ red 120px,
/* from */ transparent 120px
/* and so or till end */),
/* bg image to show transparency */ url(http://lorempixel.com/150/150);
}
keep repeating the pattern as much as needed. you can also use calc() example to mix percentage and pixel values.
You can use SVG as well.
body {
height: 100vh;
margin: 0;
display: flex;
}
svg {
flex: 1;
background: url(http://fillmurray.com/638/220) no-repeat center center / cover;
}
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<circle cx="50%" cy="50%" r="40" stroke="#F44336" stroke-width="8" fill="none" />
<circle cx="50%" cy="50%" r="60" stroke="#F44336" stroke-width="6" fill="none" />
<circle cx="50%" cy="50%" r="80" stroke="#F44336" stroke-width="10" fill="none" />
</svg>

How to segment a circle with different colors using CSS

I want to be able to draw a circle with a segment of it another colour, I would like the amount of a segment covered to be able to be increased in increments of 10% from 0% to 100%.
Any examples on Google are all sectors not segments.
So far this is the best I have been able to come up with:
div.outerClass {
position: absolute;
left: 10px;
top: 10px;
height: 2.5px;
overflow: hidden;
-ms-transform: rotate(270deg); /* IE 9 */
-webkit-transform: rotate(270deg); /* Chrome, Safari, Opera */
transform: rotate(270deg);
}
div.innerClass {
width: 10px;
height: 10px;
border: 5px solid green;
border-radius: 36px;
}
<div class="outerClass">
<div class="innerClass"></div>
</div>
0%, 50% and 100% I can all do.
You can do it using linear-gradient
.circle{
position:absolute;
width:80px;
height:80px;
border-radius:50%;
background: linear-gradient(
to right,
yellow 0%, yellow 10%,
orange 10%, orange 20%,
yellow 20%, yellow 30%,
orange 30%, orange 40%,
yellow 40%, yellow 50%,
orange 50%, orange 60%,
yellow 60%, yellow 70%,
orange 70%, orange 80%,
yellow 80%, yellow 90%,
orange 90%, orange 100%
);
}
<div class="circle"></div>
otherwise you can put 10 child elements inside your overflow:hidden circle parent:
.circle{
position:absolute;
width:80px;
height:80px;
border-radius:50%;
overflow:hidden;
}
.circle > span{
width:10%;
height:100%;
float:left;
}
.circle > span:nth-child(1){ background: yellow;}
.circle > span:nth-child(2){ background: orange;}
.circle > span:nth-child(3){ background: blue;}
.circle > span:nth-child(4){ background: green;}
.circle > span:nth-child(5){ background: fuchsia;}
.circle > span:nth-child(6){ background: orange;}
.circle > span:nth-child(7){ background: gold;}
.circle > span:nth-child(8){ background: tan;}
.circle > span:nth-child(9){ background: navy;}
.circle > span:nth-child(10){background: brown;}
<div class="circle">
<span></span><span></span><span></span><span></span><span></span>
<span></span><span></span><span></span><span></span><span></span>
</div>
The cross-browser solution:
JSFiddle
.circle {
border-radius: 50%;
background: gray;
width: 300px;
height: 300px;
overflow: hidden;
}
.segment {
float: left;
width: 10%;
height: 100%;
}
.segment_1 {
background: red;
}
.segment_2 {
background: green;
}
.segment_3 {
background: yellow;
}
.segment_4 {
background: blue;
}
<div class="circle">
<div class="segment segment_1"></div>
<div class="segment segment_2"></div>
<div class="segment segment_3"></div>
<div class="segment segment_4"></div>
</div>
BOX SHADOW
Another approach could be using one element and box-shadows.
The main element is a circle (border-radius: 50%;) and has an aspect ratio of 1:1.
The pseudoelement is positioned left: -100%;, or just left of the main element.
10 box shadows are applied to the pseudoelement, with different colour and different abscissae. I have put abscissae as 30px, as 30px is 10% of 300px ...
10% of width was chosen because 10 stripes are needed.
div {
height: 300px;
width: 300px;
border: 1px solid black;
position: relative;
border-radius: 50%;
overflow: hidden;
}
div:before {
position: absolute;
content: '';
height: inherit;
width: inherit;
left: -100%;
background: red;
box-shadow:
30px 0 0 chocolate,
60px 0 0 hotpink,
90px 0 0 indigo,
120px 0 0 orangered,
150px 0 0 gold,
180px 0 0 deepskyblue,
210px 0 0 springgreen,
240px 0 0 darkslategray,
270px 0 0 gold,
300px 0 0 navy;
}
<div></div>
Another approach would be to use SVG. The segments are made with <rect /> elements and they are clipped to a circle using the <clipPath/> element :
svg{width:40%;display:block;margin:0 auto;}
use:hover{fill:#000;}
<svg viewBox="0 0 10 10">
<defs>
<clipPath id="circle">
<circle cx="5" cy="5" r="5" />
</clipPath>
<rect id="seg" y="0" width="1" height="10" />
</defs>
<g clip-path="url(#circle)">
<use xlink:href="#seg" x="0" fill="pink"/>
<use xlink:href="#seg" x="1" fill="green" />
<use xlink:href="#seg" x="2" fill="orange" />
<use xlink:href="#seg" x="3" fill="teal" />
<use xlink:href="#seg" x="4" fill="tomato"/>
<use xlink:href="#seg" x="5" fill="gold"/>
<use xlink:href="#seg" x="6" fill="darkorange" />
<use xlink:href="#seg" x="7" fill="pink" />
<use xlink:href="#seg" x="8" fill="red" />
<use xlink:href="#seg" x="9" fill="yellow" />
</g>
</svg>

Internet Explorer and clip-path

As far as I'm aware clip-path should work in IE, as demonstrated in many articles and this tutorial CSS Masking
However I can't get the below to run properly on IE, but it works fine on Chrome.
.container {
position: relative;
width: 240px;
height: 500px;
left: 50%;
top: 50%;
}
.pentagon {
-webkit-clip-path: polygon(0px 0px, 100px 0px, 112px 13px, 240px 13px, 240px 250px, -250px 250px);
-o-clip-path: polygon(0px 0px, 100px 0px, 112px 13px, 240px 13px, 240px 250px, -250px 250px);
-ms-clip-path: polygon(0px 0px, 100px 0px, 112px 13px, 240px 13px, 240px 250px, -250px 250px);
float: left;
}
.avatar {
margin-top: 50px;
}
html {
text-align: center;
min-height: 100%;
background: linear-gradient(white, #ddd);
}
h1,
p {
color: rgba(0, 0, 0, .3);
}
<div class="container">
<div class="avatar">
<img class="pentagon" src="http://25.media.tumblr.com/tumblr_m5nre6cxkQ1qbs7p5o1_r1_500.jpg" alt="" />
</div>
</div>
<svg>
<defs>
<clipPath id="pentagon" clipPathUnits="objectBoundingBox">
<polygon points=".5,0 1,.30 .2,1 .2,1 0,.30" />
</clipPath>
</defs>
</svg>
After more in depth research, when working with the image directly, IE supports clip as in rectangular shapes only but not clipPath complicated shapes.
My solution was to add the image to an SVG as below, and this time it works in both Chrome and IE9+.
Demo JsFiddle
body {
background-color: #e0e0e0;
}
#image-wrapper {
position: relative;
}
.svg-background,
.svg-image {
clip-path: url(#clip-triangle);
}
.svg-image {
-webkit-transition: all 0.5s ease 0.2s;
-moz-transition: all 0.5s ease 0.2s;
opacity: 1;
transition: all 0.5s ease 0.2s;
}
svg.clip-svg {
height: 250px;
position: absolute;
width: 250px;
}
#svg-1 {
left: 0px;
top: 0px;
}
<div id="image-wrapper">
<svg id="svg-1" class="clip-svg">
<rect class='svg-background' width="300" height="300" fill="#ffffff" />
<image id="img-1" class='svg-image' width="300" height="300" xlink:href="http://25.media.tumblr.com/tumblr_m5nre6cxkQ1qbs7p5o1_r1_500.jpg" />
</svg>
</div>
<svg id="svg-defs">
<defs>
<clipPath id="clip-triangle">
<polygon points="0 0, 100 0, 112 13, 240 13, 240 250, -250 250"/>
</clipPath>
</defs>
</svg>
Look at this Demo JsFiddle it supports responsive image and well documented
.member-picture {
width: 200px; /*Final image width*/
}
.member-picture image{
width:100%; /*for responsive image behaviour*/
clip-path: url('#small-clip');
}
<svg class="member-picture">
<image xlink:href="https://via.placeholder.com/350x200"></image>
</svg>
<svg viewBox="0 0 250.35696 212.65134"> <!--viewBox = "X1 Y1 X2 Y2"-->
<defs>
<clipPath id="small-clip" clipPathUnits="objectBoundingBox"
transform="scale(.0039 .0047)">
<!--Use clipPathUnits="objectBoundingBox" and transform="scale(1/(viewBox.X2-viewBox.X1) 1/(viewBox.Y2-viewBox.Y1)" -->
<path d="M231.76,2.10959c5.989,1.0033,11.34394,3.5405,14.95847,9.74636,5.229,8.97779,3.54658,20.83845,2.65967,30.67514-4.2102,46.31217-8.047,92.66163-12.03267,138.993A28.82369,28.82369,0,0,1,235.49314,189.8c-2.913,7.28451-8.96608,11.54254-17.95131,14.28814-10.36022,3.16575-21.42435,3.0895-32.14721,3.458L40.64126,212.52043c-7.4331.25543-15.17585,0.4528-21.94517-2.62817C9.79852,205.84265,4.11114,196.65751,1.7732,187.16541S-0.05058,167.74594.329,157.97752c1.53266-39.43778.62959-78.92331,0.4924-118.39062C0.7836,28.70009,1.2929,16.57391,9.01875,8.9034,20.99475-2.98675,42.47458.45166,57.6212,0.4913q29.26963,0.07661,58.5389.24813,48.42851,0.2838,96.855.82742C219.161,1.63584,225.777,1.1073,231.76,2.10959Z"
fill="#4d4d4d">
</path>
</clipPath>
</defs>
</svg>