This question already has answers here:
Animate dashed SVG line
(3 answers)
Closed 5 years ago.
How can I make a dot line from starting begin to the end path (for example the 3 shape, with the dot line drawing from top to bottom)?
.box {
overflow: hidden;
outline: none;
width: 200px;
height: 200px;
position: relative;
}
.mask {
position: absolute;
top: 0;
left: 0;
width: 200px;
height: 200px;
z-index: 10;
background-color: white;
background-repeat: no-repeat;
animation: showDiag 2s linear forwards;
}
#keyframes showDiag {
from {
left: 0;
top: 0;
}
to {
left: 200px;
top: 200px;
}
}
<div class="box">
<svg class height="200" width="200">
<line fill="none" stroke="black" x1="0" y1="0" x2="200" y2="200" stroke-dasharray="5, 5" />
</svg>
<div class="mask"></div>
</div>
I have no idea how to do the fade out from top to bottom.
With a solid (not dotted) line it is quite easy. Here is a very good tutorial:
Animated line drawing in SVG
I bet all of you have seen that little trick where an SVG path is
animated to look like it's drawing itself. It's super cool. Jake
Archibald pioneered the technique and has a super good interactive
blog post on how it works. Brian Suda wrote about it on 24 Ways.
Polygon used it to great effect on a custom designed article and wrote
about it. Codrops has some neat examples.
I have very little to add, except my brain just kinda figured it out,
so I thought I would explain it one more time the way it clicked for
me.
here is something that i read and looks useful - https://css-tricks.com/svg-line-animation-works/
Related
I'm attempting an HTML page that has a diagonal border down the right-hand side. Well, in fact it has a semi-transparent border next to a solid border (to echo some design elements on other pages). The way I've created this line is by having two slightly rotated rectangles, one in the :before and one in the :after pseudo elements.
#header_block_unlimited:before {
content: '';
position: absolute;
width: 50%;
height: 130%;
right: -38.5%;
top: -10%;
bottom: -10%;
background-color: rgb(255, 255, 255); /* fallback */
background-color: rgba(255, 255, 255, 0.4);
-webkit-transition: all 1s;
-moz-transition: all 1s;
transition: all 1s;
-webkit-transform: rotate(5deg);
-moz-transform: rotate(5deg);
transform: rotate(5deg);
}
#header_block_unlimited:after {
content: '';
position: absolute;
width: 50%;
height: 130%;
right: -40%;
top: -10%;
bottom: -10%;
background-color: #F95E62;
-webkit-transform: rotate(5deg);
-moz-transform: rotate(5deg);
transform: rotate(5deg);
}
I suppose I could use an SVG shape, but I'm thinking this will take too long to fine-tune, especially since the page length needs to be dynamic (should be able to range between 400 pixels and about 1500 pixels).
I have attempted to use overflow-y:hidden but this produces a scroll bar on the x-axis, partly because the design also needs to use full-browser-width bars (see https://css-tricks.com/full-browser-width-bars/)
Clip-path to the rescue! Well, unfortunately not quite. Clip-path crops off the bits at the bottom of the rectangle I don't need, but unfortunately still counts those bits to the length of the page, meaning there is a gap beneath my footer.
Here's the clip-path code that's assigned to the parent container...
clip-path: inset( -100vw -100vw 0 -100vw);
Here's a codepen of the problem.
Any help with this would be much appreciated. An ideal solution would be some way of cropping the excess of the rotated rectangles so that it doesn't add to the page length. Alternatively, some other way of achieving the diagonal RHS border.
Instead of clip-path and complex transformation I would a simple linear-gradient to create this:
body {
margin:0;
height:100vh;
background:linear-gradient(100deg, transparent 70%,#F95E62 70.5%);
}
While I liked the simplicity of Temani Afif's answer, I was unable to get it working without the diagonal line either being blurry or pixelated.
After some fiddling, I was able to solve the problem using an SVG file, created from the original Adobe Illustrator artwork.
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
height="1700px" width="300px" viewBox="0 14 300 1715">
/* Note that the SVG needs to have an implicit height and width
to avoid problems in Firefox */
<defs>
<style>
.cls-1{opacity:0.36;}
.cls-2{fill:#fff;}
.cls-3{fill:#f95e62;}
</style>
</defs>
<title>Asset 3</title>
<g class="cls-1">
<polyline class="cls-2" points="167.05 13.28 8.5 1721 334 1721 334 1721 334 13"/>
</g>
<polyline class="cls-3" points="334 1721 334 13 197 13 40.25 1720.99"/>
</svg>
I then added it in a div just inside my main container div.
<div id="header_triangle">
<img src="[path to the svg]" />
</div>
For which the styling is as follows...
#header_triangle {
position: absolute;
top: 0;
bottom: 0;
right: 0;
z-index: 100; /* needs to sit on top */
}
#header_triangle img {
height: 102%;
float: right; /* to Fix an issue in FF */
}
Here's the working CodePen.
I just want to animate my image through curved path. Like this way. ( I'm using position absolute for positioning. ) Did some research and found that css transform can do the job. It can be easily done by straight line. But curved path?
I tried to combine with css transform-origin + transform:rotate but I didn't get exact that I want. Clearly I want to move around 80% to the left curved and need to come to original position. I tried so many times adjusting my code but still no luck.
Fiddle
P.S
What is transform-origin really do here? Is it necessary?
Can someone explain me about how transform:rotate works here?
Here is my code
.sun{
width: 5.7%;
position: absolute;
top: -5%;
left: 57%;
animation: circle 10s linear infinite;
transform-origin: 0px 700px;
animation-fill-mode: forwards;
animation-direction: alternate;
}
#keyframes circle {
from {
transform:rotate(-60deg);
}
to {
transform:rotate(40deg);
}
}
<div class="sun">
<img src="sun.png" alt="">
</div>
Maybe make parent element move by rotate and children (in my case pseudoelement, whatever) make position absolute to the parent. And just use animation. Look at my solution. Maybe you will have to create some wrapper and use overflow: hidden, because it is square which is rotating. You can watch square's behavior by adding background-color.
#keyframes move-sun {
from {
transform: rotate(0deg);
}
to {
transform: rotate(90deg);
}
}
.sun {
position: relative;
width: 400px;
height: 400px;
margin: 200px;
transform: rotate(90deg);
animation: move-sun 10s;
}
.sun::before {
content: "";
position: absolute;
top: -25px;
left: -25px;
width: 50px;
height: 50px;
background-color: #ff0;
border-radius: 50%;
}
<div class="sun">
</div>
I realize this is an old question, but I just wanted to add another option. You could use 2 separate animations, one for the x-motion and one for the y-motion:
body {
background: #8DBECC;
}
.container {
position: relative;
height: 100%;
width: 100%;
}
.sun {
position: absolute;
width: 30px;
height: 200px;
animation: x-motion 3s ease-in-out 0s infinite alternate;
}
.sun:before {
content: '';
width: 30px;
height: 30px;
position: absolute;
top: 100%;
background: #F18C3E;
animation: y-motion 3s ease-in-out 0s infinite alternate;
border-radius: 15px;
}
#keyframes x-motion {
0% {
left: 0;
}
100% {
left: calc(100% - 30px);
}
}
#keyframes y-motion {
0%, 100% {
top: 100%;
}
50% {
top: 0%;
}
}
<html>
<body>
<div class="container">
<div class="sun">
</div>
</div>
</body>
</html>
https://jsfiddle.net/561pbt0r/27/
It might not be easy with CSS, but you can easily do this with SVG animation.
I modified a sample from this tutorial for your case:
<svg width="500" height="350" viewBox="0 0 350 350">
<path id="motionPath" fill="none" stroke="#000000" stroke-miterlimit="10" d="M100,100Q250,-50,400,100"/>
<g id="sun" transform="translate(-100, -300)">
<circle cx="100" cy="300" r="25" fill="yellow"/>
</g>
<animateMotion
xlink:href="#sun"
dur="3s"
begin="0s"
fill="freeze"
repeatCount="indefinite"
>
<mpath xlink:href="#motionPath" />
</animateMotion>
</svg>
When you want to apply some transform operation to an element, that transformation has a reference point from where it will be applied. That is the origin point and by default it is at the center of every element (i.e.: transform-origin(50% 50%)).
With this statement you can modify that origin whenever you need the transformation to apply from a different origin.
Here you can see an example when the rotation is done from the top left corner. Without the origin modification, it would rotate around its center.
Note: You can set the transform-origin even outside the element
I need to draw two curves, using CSS.
I have tried to assemble some divs, using CSS border-radius to draw the curved panel. But the result is bad. Any better arithmetic?
As I had mentioned in comments earlier, please do not use CSS for achieving complex curves and shapes. While it is still possible to use CSS to achieve them (using transform + pseudo-elements like shown in this thread or using box-shadows in this thread), the process is very complex and you can't get much control over the shape, its curvature etc also. SVG on the other hand is designed for such graphics and it can also be scaled without any issues.
Below is a sample snippet on how to create the shape using a couple of cubic bezier curve (c) commands. The cubic bezier curve command takes 3 sets of parameters in total where the first two sets represent the coordinates of the control points for the initial and end points of the curve and the last set represents the coordinates of the actual end point of the curve.
You can control the curvature by modifying the control points.
.container {
position: relative;
width: 300px;
}
.container > div {
display: inline-block;
box-sizing: border-box;
}
.items {
width: 100%;
height: 250px;
border-radius: 10px;
border: 1px solid #BBB;
overflow: hidden;
}
.shape {
position: absolute;
top: 50%;
right: 0%;
height: 100px;
width: 40px;
transform: translateX(100%) translateY(-50%);
}
path {
stroke: #AAA;
fill: #DDD;
}
line {
stroke: #444;
}
<div class="container">
<div class="items">
</div>
<div class="shape">
<svg viewBox='0 0 50 100' preserveAspectRatio='none'>
<path d='M0,0
c10,15 40,15 48,35
v30
c-8,20 -38,20 -48,35'></path>
<line x1='15' y1='45' x2='30' y2='45' />
<line x1='15' y1='50' x2='30' y2='50' />
<line x1='15' y1='55' x2='30' y2='55' />
</svg>
</div>
</div>
Is it possible to create the shape produced by this Fiddle. But then with no JavaScript but CSS3 (with <div>) ?
Basically this:
for(var i = 0; i < coords.length; i += 1) {
if(coords[(i + 1)] != undefined) {
ctx.beginPath();
ctx.moveTo(coords[i].x, coords[i].y);
ctx.lineTo(coords[(i + 1)].x, coords[(i + 1)].y);
ctx.stroke();
} else {
ctx.beginPath();
ctx.moveTo(coords[i].x, coords[i].y);
ctx.lineTo(coords[0].x, coords[0].y);
ctx.stroke();
}
}
So you have points that needs to connect to each other?
Use svg, if you don't want to use canvas.
<svg width="100" height="100">
<path d="M0 0 l100 10 l-40 90z" fill="none" stroke="black" stroke-width="2" />
</svg>
Path command for 8,8,10,10,30,30,49,10 would be M8 8 L10 10 L30 40 L49 10z.
<svg width="49" height="40" viewBox="0 0 50 41">
<path d="M8 8 L10 10 L30 40 L49 10z" fill="none" stroke="black" stroke-width="2" />
</svg>
To apply a click event to the shape, you could use pointer-events: all on #test.
#test {
pointer-events: all;
}
<svg width="49" height="40" viewBox="0 0 50 41">
<path id="test" d="M8 8 L10 10 L30 40 L49 10z" fill="none" onclick="alert('Works')" stroke="black" stroke-width="2" />
</svg>
Note: Posting this answer just because you asked with CSS3, but the complexity and possible calculation overhead involved in this approach is proof enough why CSS shouldn't be used for this. Please do not use this approach.
A bit of explanation on how this was achieved:
A div is created with top and right border (1px black) and the other two borders are set to none.
This div is then skewed a bit to make it appear as though the edge on the right side is a bit slanted.
Inside the shape, a pseudo-element with only a right border is created and it is also skewed to produce the diagonal line from the right-bottom to the left-top. Transform origin is set as right-bottom to avoid positioning overhead.
An anchor tag is added within the parent div and the overflow is set to hidden so that only the portion within the shape is clickable.
The user select on the anchor tag are disabled to prevent a double click from selecting a blank space within the div.
Finally the whole container div is rotated a bit to make it look as though the triangle is not parallel to x-axis.
document.getElementById("clickme").onclick = function() {
alert('Hi! I work alright.');
}
div {
position: relative;
height: 50px;
width: 45px;
border: 1px solid black;
border-left: none;
border-bottom: none;
-webkit-transform: skew(-10deg) rotate(5deg);
-moz-transform: skew(-10deg) rotate(5deg);
transform: skew(-10deg) rotate(5deg);
overflow: hidden;
}
a {
display: block;
content: '';
margin-left: 0px;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
height: 100%;
width: 100%;
}
div:after {
position: absolute;
top: 0px;
left: 0px;
content: '';
height: 50px;
width: 45px;
-webkit-transform: skew(42deg);
-webkit-transform-origin: left bottom;
-moz-transform: skew(42deg);
-moz-transform-origin: left bottom;
transform: skew(42deg);
transform-origin: left bottom;
border-right: 1px solid black;
}
<div>
</div>
Another option to create a skewed triangle shape would be to use clip-path like in below snippet. The shape is created by applying the same clip-path on the main container element and a pseudo-element which is smaller than the container.
document.getElementById("clickme").onclick = function() {
alert('Hi! I work alright.');
}
div {
position: relative;
height: 150px;
width: 150px;
background: black;
-webkit-clip-path: polygon(0% 0%, 100% 20%, 70% 100%);
}
div:after{
position: absolute;
content: '';
height: calc(100% - 5px);
width: calc(100% - 5px);
top: 2px;
left: 3px;
background: white;
-webkit-clip-path: polygon(0% 0%, 100% 20%, 70% 100%);
}
/* Just for demo */
div{
transition: all 1s;
}
div:hover{
height: 250px;
width: 250px;
}
<div id="clickme"></div>
You can do it by embeding SVG as CSS. Quote from:
http://css-tricks.com/using-svg/
"Another way to use SVG's is to convert them into Data URI's. Data URI's might not save you actual file size, but can be more efficient because the data is right there. It doesn't require an additional HTTPRequest.
Mobilefish.com has an online conversion tool for that (http://www.mobilefish.com/services/base64/base64.php). Simply paste in the contents of your SVG file and fill out the form and it will display the results in a textarea for you to copy. Remember to remove line breaks in the data it gives you back.
...
You can use that anywhere we've talked about so far (except inline because that just doesn't make sense) Just put the gibberish where it says [data] in these examples.
As CSS
.logo {
background: url(data:image/svg+xml;base64,[data]);
}
"
The end goal of this
use svg line to underscore border of div that contains it
webkit animation effects dash forwards to imitate border effects
If possible, the line to "be" the top border of the div
The problem is the extra padding below the top of the containing div. I do not know the source of the padding. Any tries at top: 0; or margin: 0; are unsuccessful.
Actual Results
The line is affected by unknown padding and pushed down a bit
I have an svg line with a div that contains it. This all happens in the ...
HTML
<div style = "display: inline;" id="divDisplay">
<svg height="1" width="1500">
<line id="top" x1="0" y1="0" x2="1500" y2="0" />
</svg>
</div>
CSS
#divDisplay {
background:linear-gradient(to bottom, #8dd2d9 , #58c0c7);
border: 2px solid #dadada;
position: fixed;
bottom: 0;
left: 0;
right: 0;
background-color: #111;
height: 100px;
}
#top {
top: 0;
position: fixed;
margin:0;
stroke: rgb(112,111,111);
stroke-width: 5;
stroke-dasharray:1300;
stroke-dashoffset:1300;
-webkit-animation: dash-top 3.00s forwards;
}
#-webkit-keyframes dash-top {
to { stroke-dashoffset: 0; }
}
This is because the <svg> element is inline by default, so vertical-align applies and defaults to baseline.
A quick fix is to change the vertical-align value: updated fiddle
svg {
vertical-align: top;
}
Not sure about the root cause, but adding the following css solved it.
#divDisplay svg
{
position:absolute;
top:1;
}
http://jsfiddle.net/wmeLa8tc/