Sie können überlegen border-radius
. Hier ist ein grundlegendes Beispiel, das Sie verbessern können
.box {
height:100px;
margin-top:50px;
border:10px solid transparent;
border-bottom:10px solid red;
width:100px;
animation:
loop 5s infinite alternate linear,
radius 5s infinite alternate linear;
}
@keyframes loop{
0% {
transform:translateX(0);
}
40% {
transform:translateX(100px) rotate(0deg);
}
60% {
transform:translateX(100px) rotate(-360deg);
}
100% {
transform:translateX(200px) rotate(-360deg);
}
}
@keyframes radius{
0%,28% {
border-radius:0%
}
35%,38% {
border-bottom-right-radius:50%;
border-bottom-left-radius:0%;
}
45%,55% {
border-radius:50%
}
62%,65% {
border-bottom-right-radius:0%;
border-bottom-left-radius:50%;
}
70%,100% {
border-radius:0%
}
}
<div class="box"></div>
Eine weitere verrückte Idee, bei der Sie eine rechteckige Form hinter einem transparenten, gekrümmten Pfad animieren können:
.box {
height: 165px;
width: 315px;
position: relative;
border-radius: 0 100px 100px 0;
animation: hide 3s infinite linear alternate;
overflow:hidden;
}
.box:after {
content: "";
display:block;
height: 100%;
background: white padding-box;
border-radius: inherit;
border: 15px solid transparent;
border-left:0;
box-sizing: border-box;
}
.alt {
margin-top: -165px;
transform: scaleX(-1);
transform-origin: 170px 0;
animation-direction: alternate-reverse;
}
.box:before {
content: "";
position: absolute;
z-index: -1;
width: 90px;
height: 90px;
background: blue;
bottom: -40px;
animation: loop 3s infinite linear alternate;
transform-origin: 50% -20px;
}
.alt:before {
animation-direction: alternate-reverse;
}
@keyframes loop {
15% {
transform: translateX(180px) rotate(0deg);
}
40% {
transform: translateX(180px) rotate(-180deg);
}
50%,100% {
transform: translateX(125px) rotate(-180deg);
}
}
@keyframes hide {
0%,50% {
visibility: visible;
}
50.2%,100% {
visibility: hidden;
}
}
<div class="box"></div>
<div class="box alt"></div>
Eine optimierte Version mit weniger Code und Transparenz (wird dies berücksichtigen mask
)
.box {
height: 165px;
width: 315px;
position: relative;
border-radius: 0 100px 100px 0;
animation: hide 3s infinite linear alternate;
overflow:hidden;
-webkit-mask:
linear-gradient(#fff,#fff) top left /235px 15px,
linear-gradient(#fff,#fff) bottom left/235px 15px,
radial-gradient(farthest-side at left,transparent calc(100% - 15px),#fff 0) right/100px 100%;
-webkit-mask-repeat:no-repeat;
mask:
linear-gradient(#fff,#fff) top left/235px 15px,
linear-gradient(#fff,#fff) bottom left/235px 15px,
radial-gradient(farthest-side at left,transparent calc(100% - 15px),#fff 0) right/100px 100%;
mask-repeat:no-repeat;
}
.alt {
margin-top: -165px;
transform: scaleX(-1);
transform-origin: 170px 0;
animation-direction: alternate-reverse;
}
.box:before {
content: "";
position: absolute;
width: 90px;
height: 90px;
background: blue;
bottom: -40px;
animation: loop 3s infinite linear alternate;
transform-origin: 50% -20px;
}
.alt:before {
animation-direction: alternate-reverse;
}
@keyframes loop {
15% {
transform: translateX(180px) rotate(0deg);
}
40% {
transform: translateX(180px) rotate(-180deg);
}
50%,100% {
transform: translateX(125px) rotate(-180deg);
}
}
@keyframes hide {
0%,50% {
visibility: visible;
}
50.2%,100% {
visibility: hidden;
}
}
body {
background:linear-gradient(to right,yellow,gray);
}
<div class="box"></div>
<div class="box alt"></div>
Eine andere Version mit weniger Pixelwerten und CSS-Variablen, in der Sie einfach alles anpassen können.
Führen Sie das Snippet auf einer ganzen Seite aus und haben Sie Spaß mit allen Untersetzern!
.box {
--w:400px; /* Total width of the coaster */
--h:180px; /* Height of the coaster */
--b:90px; /* width of the small bar */
--t:15px; /* height of the small bar */
--c:blue; /* Color of the small bar */
width:var(--w);
height:var(--h);
}
.box > div {
height: 100%;
position:relative;
width: calc(50% + var(--h)/2 + var(--b)/2);
border-radius: 0 1000px 1000px 0;
animation: hide 3s infinite linear alternate;
-webkit-mask:
linear-gradient(#fff,#fff) top left /calc(100% - var(--h)/2) var(--t),
linear-gradient(#fff,#fff) bottom left/calc(100% - var(--h)/2) var(--t),
radial-gradient(farthest-side at left,transparent calc(100% - var(--t)),#fff 0) right/calc(var(--h)/2) 100%;
-webkit-mask-repeat:no-repeat;
mask:
linear-gradient(#fff,#fff) top left /calc(100% - var(--h)/2) var(--t),
linear-gradient(#fff,#fff) bottom left/calc(100% - var(--h)/2) var(--t),
radial-gradient(farthest-side at left,transparent calc(100% - var(--t)),#fff 0) right/calc(var(--h)/2) 100%;
mask-repeat:no-repeat;
}
.box > div:last-child {
margin-top:calc(-1*var(--h));
margin-left:auto;
transform: scaleX(-1);
animation-direction: alternate-reverse;
}
.box > div:before {
content: "";
position: absolute;
width: var(--b);
height: 50%;
background: var(--c);
bottom: -25%;
animation: loop 3s infinite linear alternate;
transform-origin: 50% -50%;
}
.box > div:last-child:before {
animation-direction: alternate-reverse;
}
@keyframes loop {
15% {
transform: translateX(calc(var(--w)/2)) rotate(0deg);
}
40% {
transform: translateX(calc(var(--w)/2)) rotate(-180deg);
}
50%,100% {
transform: translateX(calc(var(--w)/2 - var(--b)/2)) rotate(-180deg);
}
}
@keyframes hide {
50% {
visibility: visible;
}
50.1%,100% {
visibility: hidden;
}
}
body {
background:linear-gradient(to right,yellow,gray);
}
<div class="box">
<div></div><div></div>
</div>
<div class="box" style="--w:500px;--h:80px;--b:50px;--c:red;--t:5px">
<div></div><div></div>
</div>
<div class="box" style="--w:90vw;--h:200px;--b:100px;--c:purple;--t:20px">
<div></div><div></div>
</div>
Um den Trick zu verstehen, entfernen wir die Maske, ersetzen sie durch einen einfachen Farbverlauf und entfernen die ausgeblendete Animation:
.box {
--w:400px; /* Total width of the coaster */
--h:180px; /* Height of the coaster */
--b:90px; /* width of the small bar */
--t:15px; /* height of the small bar */
--c:blue; /* Color of the small bar */
width:var(--w);
height:var(--h);
}
.box > div {
height: 100%;
position:relative;
width: calc(50% + var(--h)/2 + var(--b)/2);
border-radius: 0 1000px 1000px 0;
/*animation: hide 3s infinite linear alternate;*/
background:
linear-gradient(red,red) top left /calc(100% - var(--h)/2) var(--t),
linear-gradient(green,green) bottom left/calc(100% - var(--h)/2) var(--t),
radial-gradient(farthest-side at left,transparent calc(100% - var(--t)),black 0) right/calc(var(--h)/2) 100%;
background-repeat:no-repeat;
}
.box > div:last-child {
margin-top:calc(-1*var(--h));
margin-left:auto;
transform: scaleX(-1);
animation-direction: alternate-reverse;
}
.box > div:before {
content: "";
position: absolute;
width: var(--b);
height: 50%;
background: var(--c);
bottom: -25%;
animation: loop 3s infinite linear alternate;
transform-origin: 50% -50%;
}
.box > div:last-child:before {
animation-direction: alternate-reverse;
background:purple;
}
@keyframes loop {
15% {
transform: translateX(calc(var(--w)/2)) rotate(0deg);
}
40% {
transform: translateX(calc(var(--w)/2)) rotate(-180deg);
}
50%,100% {
transform: translateX(calc(var(--w)/2 - var(--b)/2)) rotate(-180deg);
}
}
@keyframes hide {
0%,50% {
visibility: visible;
}
50.2%,100% {
visibility: hidden;
}
}
body {
background:linear-gradient(to right,yellow,gray);
}
<div class="box">
<div></div><div></div>
</div>
Der durch den Farbverlauf erzeugte Pfad ist unsere Maske und wir werden nur diesen Teil sehen. Dann machen wir unser Rechteck so, dass es dem Pfad folgt, und der Trick besteht darin, zwei symmetrische Elemente zu haben, um den Schleifeneffekt zu erzeugen. Die Haut Animation ermöglicht es uns , nur einer von ihnen zu sehen und die perfekte Überlappung wird eine kontinuierliche Animation erstellen.
Hier ist eine Version für den Fall, dass Sie einen Kreis für den Untersetzer möchten
.box {
--w:400px; /* Total width of the coaster */
--h:180px; /* Height of the coaster */
--b:90px; /* width of the small bar */
--t:15px; /* height of the small bar */
--c:blue; /* Color of the small bar */
width:var(--w);
height:var(--h);
}
.box > div {
height: 100%;
position:relative;
width: calc(50% + var(--h)/2);
border-radius: 0 1000px 1000px 0;
animation: hide 3s infinite linear alternate;
-webkit-mask:
radial-gradient(farthest-side at bottom right,transparent calc(100% - var(--t)),#fff 0 100%,transparent 100%) top 0 right calc(var(--h)/2)/calc(var(--h)/2) 50%,
linear-gradient(#fff,#fff) bottom left/calc(100% - var(--h)/2) var(--t),
radial-gradient(farthest-side at left,transparent calc(100% - var(--t)),#fff 0) right/calc(var(--h)/2) 100%;
-webkit-mask-repeat:no-repeat;
mask:
radial-gradient(farthest-side at bottom right,transparent calc(100% - var(--t)),#fff 0 100%,transparent 100%) top 0 right calc(var(--h)/2)/calc(var(--h)/2) 50%,
linear-gradient(#fff,#fff) bottom left/calc(100% - var(--h)/2) var(--t),
radial-gradient(farthest-side at left,transparent calc(100% - var(--t)),#fff 0) right/calc(var(--h)/2) 100%;
mask-repeat:no-repeat;
}
.box > div:last-child {
margin-top:calc(-1*var(--h));
margin-left:auto;
transform: scaleX(-1);
animation-direction: alternate-reverse;
}
.box > div:before {
content: "";
position: absolute;
width: var(--b);
height: 50%;
background: var(--c);
bottom: -25%;
animation: loop 3s infinite linear alternate;
transform-origin: 50% -50%;
}
.box > div:last-child:before {
animation-direction: alternate-reverse;
}
@keyframes loop {
15% {
transform: translateX(calc(var(--w)/2 - var(--b)/2)) rotate(0deg);
}
50%,100% {
transform: translateX(calc(var(--w)/2 - var(--b)/2)) rotate(-180deg);
}
}
@keyframes hide {
50% {
visibility: visible;
}
50.1%,100% {
visibility: hidden;
}
}
body {
background:linear-gradient(to right,yellow,gray);
}
<div class="box">
<div></div><div></div>
</div>
<div class="box" style="--w:500px;--h:80px;--b:50px;--c:red;--t:5px">
<div></div><div></div>
</div>
<div class="box" style="--w:90vw;--h:200px;--b:100px;--c:purple;--t:20px">
<div></div><div></div>
</div>