SVG clip-path animation bug in Chrome/Chromium - html

I'm new at animating SVGs with CSS and I'm trying to create a "blinking eye" effect. This is what I've managed to do:
https://codepen.io/pablo-m/pen/jOGeMpJ.
(Edit 3: Code added)
SVG
<svg id="composicion" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 571.8 761.82">
<g id="Ojito">
<rect x="190.37" y="288.55" width="192.7" height="91.76" fill="#606060" />
<ellipse id="outer-eye" cx="292.3" cy="335.43" rx="44.72" ry="30.01" fill="#3caa56" />
<circle id="inner-eye" cx="291.69" cy="334.82" r="18.38" fill="#efefef" />
</g>
</svg>
SCSS
#composicion {
#Ojito {
#keyframes inner-eye-blink {
0%,
82%,
95%,
100% {
clip-path: ellipse(75% 55%);
}
90% {
clip-path: ellipse(75% 0);
}
}
#keyframes outer-eye-blink {
0%,
80%,
100% {
ry: 30.01px;
}
90% {
ry: 1px;
}
}
& #outer-eye {
animation: outer-eye-blink 8s ease infinite;
}
& #inner-eye {
animation: inner-eye-blink 8s infinite;
}
}
}
The animation works great on Firefox v95.0.2 and Safari v15.1. However, on Chrome/Chromium v97.0.4692.71 (as of today, the latest version) it does not. It looks like, whenever I apply a clip-path with css the white circle dissapears. I also noticed that this behaviour does not happen on Chrome/Chromium v96.0.4664.93. Am I doing something wrong or did something change in the latest version of Chrome/Chromium? Edit: If I did everything correctly, does anyone know a workaround?
This is my first question in SO, so please let me know if I missed any detail.
Thanks!
Edit: I have looked at Chromium's bug tracker but I've not found any relevant issues there.
Edit 2: Chromium bug reported

In a situation like this it is a good idea to use either a clip-path or a mask because you have more elements that need to be animated/masked off. In this example I chose CSS clip-path because you started off with the animation in CSS.
My example works fine in Chrome 97 as I see it.
Another option would be to use SVG animation with SMIL. I would expect it to work in Chrome as well. In some cases it is more flexible then mask or clip-path in CSS.
I used SvgPathEditor for constructing the path.
#keyframes eye-blink {
0%,
100% {
clip-path: path('M 3 5 C 6 6 9 7 13 5 C 9 2 6 3 3 5');
}
50% {
clip-path: path('M 3 5 C 6 5 9 5 13 5 C 9 5 6 5 3 5');
}
}
#Ojito g {
clip-path: path('M 3 5 C 6 6 9 7 13 5 C 9 2 6 3 3 5');
animation: eye-blink 4s ease infinite;
}
<svg id="composicion" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 10" width="400">
<g id="Ojito">
<rect width="16" height="10" fill="#606060" />
<g>
<rect width="16" height="10" fill="white" />
<circle id="inner-eye" cx="8" cy="4.8" r="2" fill="#333" />
<circle id="inner-eye" cx="8" cy="4.8" r="1.2" fill="black" />
</g>
</g>
</svg>

It looks like it's a Chrome bug indeed. However, I managed to find a workaround which solves the issue: https://codepen.io/pablo-m/pen/WNZYeoB
SCSS
#composicion {
#Ojito {
#keyframes inner-eye-move {
0%,
5%,
20%,
25%,
40%,
45%,
50%,
60%,
65%,
80%,
85%,
100% {
cx: 291.69px;
cy: 334.82px;
}
10%,
15% {
cx: 273.69px;
cy: 328.82px;
}
30%,
35% {
cx: 291.69px;
cy: 342.82px;
}
70%,
75% {
cx: 310.69px;
cy: 328.82px;
}
90%,
95% {
cx: 307.69px;
cy: 338.82px;
}
}
#keyframes outer-eye-blink {
0%,
80%,
100% {
ry: 30.01px;
}
90% {
ry: 1px;
}
}
& .outer-eye {
animation: outer-eye-blink 8s ease infinite;
}
& #inner-eye {
clip-path: url(#eyeClip);
animation: inner-eye-move 50s ease infinite;
}
}
}
SVG
<svg id="composicion" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 571.8 761.82">
<g id="Ojito">
<rect x="190.37" y="288.55" width="192.7" height="91.76" fill="#606060" />
<clipPath id="eyeClip">
<ellipse class="outer-eye" cx="292.3" cy="335.43" rx="44.72" ry="30.01" />
</clipPath>
<ellipse class="outer-eye" cx="292.3" cy="335.43" rx="44.72" ry="30.01" fill="#3caa56" />
<circle id="inner-eye" cx="291.69" cy="334.82" r="18.38" fill="#efefef" />
</g>
</svg>
I'll edit my question and answer when I post the bug on the Chrome bug tracker.
Edit: Chromium bug reported
Edit 2: For another great workaround, please look at #chrwahl's answer

Related

Drop shadow with fade in animation is cut off on iOS

I have a website where I fade in a set of SVG icons which have the filter: drop-shadow rule applied. This works fine on desktop, however on iOS the shadow gets cut off once the animation finishes.
For example, this is the html:
<div class="fade-in">
<svg class="shadow" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<circle cx="50" cy="50" r="50" fill="white"/>
</svg>
</div>
The css:
#keyframes fade-in {
from {
opacity: 0.0;
}
to {
opacity: 1.0;
}
}
.fade-in {
animation: fade-in 2s;
}
.shadow {
filter: drop-shadow(0 0.1rem 0.7rem black);
}
JS Bin:
https://jsbin.com/yonifusomo/edit?html,css,output
Result on iOS after the animation finishes:
Safari has multiple bugs related to shadows and various animations. Luckily, looks like this one is not the worst. Adding a -webkit-transform: translateZ(0); property to your .fade-in class did the trick for me.
For more info: this post is pretty similar to yours, and it contains almost same advice.

How do I make the edges of the hexagon image round? [duplicate]

This question already has answers here:
How to make a curved edge hexagon by using CSS
(6 answers)
Closed last year.
This post was edited and submitted for review last year and failed to reopen the post:
Original close reason(s) were not resolved
I'm working on a small project by myself. I want to make the edges of that hexagonal pfp round.
The code:
.hex img {
width: 50px;
height: 50px;
-webkit-clip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);
clip-path: polygon(0% 50%, 25% 100%, 75% 100%, 100% 50%, 75% 0%, 25% 0%);
object-fit: cover;
}
I've tried using border-radius, but little did I know that it would only make the sides of that hexagon round.
I'm trying to get something like this.
How do I make it like that?
Curved Path
I suggest that you use an SVG path with rounded corner:
https://developer.mozilla.org/en-US/docs/Web/CSS/clip-path
It should look like this (this is a heart shape as an example):
.hex img {
clip-path: path('M0.5,1 C0.5,1,0,0.7,0,0.3 A0.25,0.25,1,1,1,0.5,0.3 A0.25,0.25,1,1,1,1,0.3 C1,0.7,0.5,1,0.5,1 Z');
}
Here's the documentation concerning paths:
https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths
You can also create the path with a vector editing software like Illustrator, or directly only with tools like this: https://yqnn.github.io/svg-path-editor/
SVG filter
Another solution would be to use SVG filters. Although it may look "simpler" I strongly suggest that you use curved paths (the solution I mentioned earlier) for performance and readability.
You can declare a filter that will smooth corners like that:
<svg style="visibility: hidden; position: absolute;" width="0" height="0" xmlns="http://www.w3.org/2000/svg" version="1.1">
<defs>
<filter id="round">
<feGaussianBlur in="SourceGraphic" stdDeviation="5" result="blur" />
<feColorMatrix in="blur" mode="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 19 -9" result="goo" />
<feComposite in="SourceGraphic" in2="goo" operator="atop"/>
</filter>
</defs>
</svg>
Then, you just need to use the filter CSS property
.hex::before {
content:"";
display:block;
padding-top:86.6%;
background:red;
clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%);
}
.hex {
width: 100px;
height: 100px;
filter: url(#round)
}
source: https://dev.to/afif/css-shapes-with-rounded-corners-56h

How to animate the fill color of SVG with CSS?

CSS allows to change the color of SVG like this
.clr {fill: green;}
But when I apply animation with the same fill attributes nothing seems to work. What should I do?
<svg width="800" height="600" style="background-color:lightblue">
<circle class="clr" cx="610" cy="240" r="4" fill="gold" />
<style>
.clr {animation: col 3s linear infinite;}
#keyframes col {
0%,71% {fill:none}
72% {fill:black}
75%,100% {fill:none}
}
</style>
</svg>
Its working as expected, I just increased the circle radius and changed its position to show it on 50x and 50y,
.color {animation: col 3s linear infinite;}
#keyframes col {
0%,71% {fill:none}
72% {fill:black}
75%,100% {fill:none}
}
<svg width="800" height="600" style="background-color:lightblue">
<circle class="color" cx="50" cy="50" r="30" fill="gold" />
</svg>
You Just add fill:black in #keyframes section. change it to green like this:
.color {animation: col 3s linear infinite;}
#keyframes col {
0%,71% {fill:none}
72% {fill:green}
75%,100% {fill:none}
}
<svg width="800" height="600" style="background-color:lightblue">
<circle class="color" cx="610" cy="240" r="4" fill="gold" />
</svg>
and don't want to use .color {fill: green;}.
You cannot animate from none (nothing) to green (something) for a smooth transition. Instead do:
#keyframes col {
0%, 71% { fill: none; } /* change attribute value to `inherit` */
72% { fill: black; }
75%, 100% { fill: none; } /* or change value to `currentcolor` */
}
Resulting in the following:
#keyframes col {
0%, 71% { fill: inherit; }
72% { fill: black; }
75%, 100% { fill: currentcolor; }
}
Then play around with the animation attribute or element.animate to achieve desired effect.
Following is the example from #Muhammad (because it is easier to see than the OP's example of a small dot in the lower right) of an svg with an inline style section. As I read the specification, it should work as is. However, browser support still seems to be lacking 3 years later, now in 2020.
SVG 2 Requirement: Add HTML5 ‘style’ element attributes to SVG's ‘style’ element.
Resolution: SVG 2 ‘style’ element shall be aligned with the HTML5 ‘style’ element.
Purpose: To not surprise authors with different behavior for the ‘style’ element in HTML and SVG content.
I have used VS Code with a plugin called jock.svg and the animation works as expected in the live preview pane. Just copy and save the svg code "as is" with a file extension of "svg".
It is hard to know what animation the OP was going for without a description because the code snippet is said to be not working.
For clarity I will describe what this example does: It displays a briefly (3% of the time) flashing black circle on a light blue background in the top left corner. Note that the original "gold" fill is ignored when the animation is working. Today in Safari (Mac, iPad), Chrome (iPad) and Edge (iPad), all I see is the "gold" circle. No animation is applied. Please comment if (when) your browser works. I suspect this hole in browser support will be filled in the future.
[Edit]
It works in Chrome 81.0.4044.92 (Mac)
<svg width="800" height="600" style="background-color:lightblue">
<circle class="color" cx="50" cy="50" r="30" fill="gold" />
<style>
.color {animation: col 3s linear infinite;}
#keyframes col {
0%,71% {fill:none}
72% {fill:black}
75%,100% {fill:none}
}
</style>
</svg>

clip-path is not working in firefox even after using inline SVG as source

I have created a right pointing content box using css clip-path polygon, It works well inside chrome, For firefox I have added Inline SVG, but still it is not working.
Here is work in progress link
Link
Here is the markup and code I used for creating the right pointing content box
HTML :
<svg width="0" height="0">
<defs>
<clipPath id="clip-shape" clipPathUnits="objectBoundingBox">
<polygon points="0 0, 0.95 0, 1 0.5, 0.95 1, 0 1" />
</clipPath>
</defs>
</svg>
<div class="application-content">
<h3>clip-path is not working in firefox</h3>
<p>Hi, I have created a right pointing content box using css clip-path polygon, It works well inside chrome, For firefox I have added Inline SVG, but still it is not working.</p>
</div>
CSS:
.application-content{
width:35%;
-webkit-clip-path: polygon(0% 0%, 95% 0, 100% 50%, 95% 100%, 0% 100%);
clip-path: polygon(0% 0%, 95% 0, 100% 50%, 95% 100%, 0% 100%);
clip-path: url("#clip-shape");
background-color:#f5f5f5;
padding:30px;
}
I don't know, where it is going wrong.
Interesting thing here is, The above code is working when used with jsfiddle or codepen. I am using latest version of wordpress with a custom code theme.
Here is the codepen link

Radial wipe with pure CSS; if not SVG alternative

I have found this question that's been answered and seems to achieve a radial wipe animation with an SVG.
I am looking to achieve a border: 1px solid green; effect like the following example:
What I would like to know though is if this is possible with pure CSS —that would be ideal.
If it's not achievable with CSS, how would I tackle this type of thing with SVG?
CSS is not the right tool for animations like these. While you can do it with CSS, best is to make use of SVG. For a pure CSS version you could try adapting the snippet provided in my answer here but I wouldn't really be recommending it because as you can see it is very complex.
All you have to do is use a circle element, set its stroke-dasharray equal to the circumference of the circle and then animate the stroke-dashoffset like in the below snippet.
The stroke-dasharray property creates a dotted line stroke for the cirlce (the border) where each of the stroke and the dash between them will have the length as specified for the property.
The stroke-dashoffset property specifies the offset at which the circle's stroke should start. When the offset is at 0, the green colored stroke is visible whereas when the offset is at 314 (equal to the circumference), the dash in between strokes become visible. Thus it ends up producing a wipe effect.
svg {
height: 100px;
width: 100px;
transform: rotate(-90deg);
}
circle {
stroke: green;
fill: none;
stroke-dasharray: 314; /* equal to circumference of circle 2 * 3.14 * 50 */
animation: wipe 2s linear infinite;
}
#keyframes wipe {
0% {
stroke-dashoffset: 0;
}
30%, 50% {
stroke-dashoffset: 314;
}
80%, 100% {
stroke-dashoffset: 0;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<svg viewBox='0 0 100 100'>
<circle cx='50' cy='50' r='40' />
</svg>
The above sample uses an infinite animation and so the wipe and repaint would run continuously. If it has to be toggled on/off then it would be better to use transition like in the below snippet. I have done this on :hover but you can easily adapt it to click or other events.
svg {
height: 100px;
width: 100px;
transform: rotate(-90deg);
}
circle {
stroke: green;
fill: none;
stroke-dasharray: 314; /* equal to circumference of circle 2 * 3.14 * 50 */
stroke-dashoffset: 0; /* initial setting */
transition: all 2s;
}
svg:hover circle{
stroke-dashoffset: 314;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<svg viewBox='0 0 100 100'>
<circle cx='50' cy='50' r='40' />
</svg>