Internet Explorer and clip-path - html

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>

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>

clipPath cut off by container

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>

How to get svg clipPath sized correctly

I have a problem with scaling my inline SVG which is used for clip-path only. The element which is clipped has a width of 150px and a height of 150px. It's the 2nd day I'm trying to fix this, but I feel like running in circles.
In Chrome (latest) the SVG has the correct width of 150px.
In Opera (latest) the SVG has the correct width of 150px
In Firefox (54.0.1) the SVG doesn't have the correct width.
body {
background: #333;
}
.image {
background-size: cover;
background-repeat: no-repeat;
background-position: center center;
clip-path: url(#clipPath);
height: 150px;
left: 0;
position: absolute;
top: 0;
width: 150px;
}
#clipPath {
transform: scale(2.63, 2.63);
}
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 1 1">
<defs>
<clipPath id="clipPath" clipPathUnits="objectBoundingBox">
<!-- <path d="M28.487,10.847C21.13-6.364,0.18-2.348,0.08,17.628C0,33.538,27.699,46.784,28.531,49.636C29.285,46.675,57,33.785,56.92,17.509C56.823-2.517,35.506-5.678,28.487,10.847z">-->
<path d="M0.189913333333,0.0723133333333C0.140866666667-0.0424266666667,0.0012-0.0156533333333,0.000533333333333,0.11752C0,0.223586666667,0.18466,0.311893333333,0.190206666667,0.330906666667C0.195233333333,0.311166666667,0.38,0.225233333333,0.379466666667,0.116726666667C0.37882-0.01678,0.236706666667-0.0378533333333,0.189913333333,0.0723133333333z">
</clipPath>
</defs>
</svg>
<div class="image" style="background-image: url('https://images.unsplash.com/photo-1468793195345-d9d67818016d?dpr=1&auto=format&fit=crop&w=1500&h=994&q=80&cs=tinysrgb&crop=');"></div>
Apply transform using attribute, not via CSS to fix this in Firefox.
body {
background: #333;
}
.image {
background-size: cover;
background-repeat: no-repeat;
background-position: center center;
clip-path: url(#clipPath);
height: 150px;
left: 0;
position: absolute;
top: 0;
width: 150px;
}
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 1 1">
<defs>
<clipPath id="clipPath" clipPathUnits="objectBoundingBox" transform="scale(2.63, 2.63)">
<path d="M0.189913333333,0.0723133333333C0.140866666667-0.0424266666667,0.0012-0.0156533333333,0.000533333333333,0.11752C0,0.223586666667,0.18466,0.311893333333,0.190206666667,0.330906666667C0.195233333333,0.311166666667,0.38,0.225233333333,0.379466666667,0.116726666667C0.37882-0.01678,0.236706666667-0.0378533333333,0.189913333333,0.0723133333333z">
</path>
</clipPath>
</defs>
</svg>
<div class="image" style="background-image: url('https://images.unsplash.com/photo-1468793195345-d9d67818016d?dpr=1&auto=format&fit=crop&w=1500&h=994&q=80&cs=tinysrgb&crop=');"></div>

CSS one side cut circle image with border

How I can make following shape with a colored border:
My first try was pure CSS but the attached code makes more an egg shape than a circle:
img {
border: 2px #ff00ff solid;
border-top-left-radius: 60% 50%;
border-bottom-left-radius: 60% 50%;
border-top-right-radius: 50% 20%;
border-bottom-right-radius:50% 20%;
}
<img src="https://d1wn0q81ehzw6k.cloudfront.net/additional/thul/media/4e34feee0acdc38a?w=400&h=400" style="width:100%">
Second try, working with SVG isn't supported in Opera and IE and I have no idea how to make borders. The "cut" doesn't work every time.
img {
clip-path: url(#myClip);
}
<svg width="120" height="120"
viewBox="0 0 120 120"
xmlns="http://www.w3.org/2000/svg">
<defs>
<clipPath id="myClip">
<circle cx="260" cy="256" r="256" style="fill:none;stroke:#00df0b;stroke-width:6"/>
</clipPath>
</defs>
</svg>
<img src="https://d1ra4hr810e003.cloudfront.net/media/27FB7F0C-9885-42A6-9E0C19C35242B5AC/0/D968A2D0-35B8-41C6-A94A0C5C5FCA0725/F0E9E3EC-8F99-4ED8-A40DADEAF7A011A5/dbe669e9-40be-51c9-a9a0-001b0e022be7/thul-IMG_2100.jpg" style="width:100%">
The simplest solution is probably just to make an SVG.
<svg width="400px" height="400px" viewBox="0 0 1 1"
overflow="visible">
<defs>
<mask id="myMask" x="0" y="0" width="1" height="1"
maskContentUnits="objectBoundingBox" fill="white">
<path id="myPath" d="M 0.8 0.9 L 0.8 0.1 A 0.5 0.5 0 1 0 0.8 0.9 Z"/>
</mask>
</defs>
<image xlink:href="https://d1ra4hr810e003.cloudfront.net/media/27FB7F0C-9885-42A6-9E0C19C35242B5AC/0/D968A2D0-35B8-41C6-A94A0C5C5FCA0725/F0E9E3EC-8F99-4ED8-A40DADEAF7A011A5/dbe669e9-40be-51c9-a9a0-001b0e022be7/thul-IMG_2100.jpg"
x="0" y="0" width="1" height="1" mask="url(#myMask)"/>
<use xlink:href="#myPath" fill="none" stroke="#f0f" stroke-width="0.01"/>
</svg>
You could use a pseudo element to create something like this:
div {
height: 300px;
width: 300px;
position: relative;
overflow: hidden;
cursor: pointer;
transition: all 0.4s;
}
div:hover {
height: 500px;
width: 500px;
}
div:before {
content: "";
box-sizing: border-box;
position: absolute;
top: 0;
left: 15%;
height: 100%;
width: 100%;
background: url(http://lorempixel.com/300/300);
background-size: 100% 100%;
border-radius: 50%;
border: 10px solid tomato;
}
div:after {
content: "";
position: absolute;
right: 0;
top: 15%;
height: 70%;
background: tomato;
width: 10px;
}
<div></div>

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>