1598618580
If you have some basic handyman skills and an old computer lying around, you can turn an old arcade machine into a MAME arcade machine, capable of playing nearly every arcade game ever made using free PC software. The project you’re going to see is a one-off, meaning I did it once for fun, and that was it. I bought the original machine for $50 USD but sold it a few years later for $2,400. If you follow these steps, you can make a similar machine. It’s fun, and it’s really not that hard. I’ve broken the entire job down into manageable steps for you, so read on!
This step isn’t very difficult. There are loads of old arcade machines out there, and any machine will do, EVEN IF IT DOESN’T WORK AT ALL. I found one on Craigslist that was an hour away from my home for only $50. Since I owned my own pickup truck, I went and got it myself. If you don’t have a pickup truck, people will often deliver for a fee. What did I manage to get for $50, you might ask? Bask in the glory of this old Capcom Bowling game!
Bowling! Yuck!
“Wow, what a horrible piece of garbage you picked up there, Erik!” you might be saying. Haha, you’re sort of right! That being said, I was actually very glad to find this specific machine, because this Capcom Bowling game (which is a terrible game, by the way) is actually a rethemed Centipede machine! You can see some long-ago previous owner swapped out the Centipede labels, put a different sticker on the controls and slapped some awful wooden stick-on paneling on the sides, and called it a day. Here’s what it might have looked like originally. My goal was to retheme it as the original Centipede game, but with the ability to play nearly every arcade game ever made.
#arcade #renovations #games #arcade-games #projects
1643186064
Please watch our home arcade built :
https://youtu.be/8ToTCFucoBc
Eran
1598618580
If you have some basic handyman skills and an old computer lying around, you can turn an old arcade machine into a MAME arcade machine, capable of playing nearly every arcade game ever made using free PC software. The project you’re going to see is a one-off, meaning I did it once for fun, and that was it. I bought the original machine for $50 USD but sold it a few years later for $2,400. If you follow these steps, you can make a similar machine. It’s fun, and it’s really not that hard. I’ve broken the entire job down into manageable steps for you, so read on!
This step isn’t very difficult. There are loads of old arcade machines out there, and any machine will do, EVEN IF IT DOESN’T WORK AT ALL. I found one on Craigslist that was an hour away from my home for only $50. Since I owned my own pickup truck, I went and got it myself. If you don’t have a pickup truck, people will often deliver for a fee. What did I manage to get for $50, you might ask? Bask in the glory of this old Capcom Bowling game!
Bowling! Yuck!
“Wow, what a horrible piece of garbage you picked up there, Erik!” you might be saying. Haha, you’re sort of right! That being said, I was actually very glad to find this specific machine, because this Capcom Bowling game (which is a terrible game, by the way) is actually a rethemed Centipede machine! You can see some long-ago previous owner swapped out the Centipede labels, put a different sticker on the controls and slapped some awful wooden stick-on paneling on the sides, and called it a day. Here’s what it might have looked like originally. My goal was to retheme it as the original Centipede game, but with the ability to play nearly every arcade game ever made.
#arcade #renovations #games #arcade-games #projects
1642923600
Webサイトがある場合は、ローダーを使用すると、ユーザーがリンクまたはボタンをクリックすると何かが起こっていることを知ることができるので便利です。
このローダーコンポーネントは多くの場所で使用でき、可能な限りシンプルにする必要があります。
<div>
この投稿では、1行と数行のCSSコードで2種類のローダーを構築する方法を説明します。これだけでなく、同じコードからさまざまなバリエーションを簡単に作成できるようにカスタマイズできるようにします。
これが私たちが構築するものです:
CSSのみのスピナーとプログレスローダー
以下は、私たちが構築しているもののデモです。
https://codepen.io/t_afif/pen/PoJyaNy
<div class="loader"></div>
<div class="loader" style="--b: 15px;--c: blue;width: 120px;--n: 8"></div>
<div class="loader" style="--b: 5px;--c: green;width: 80px;--n: 6;--g: 20deg"></div>
<div class="loader" style="--b: 20px;--c: #000;width: 80px;--n: 15;--g: 7deg"></div>
.loader {
--b: 10px; /* border thickness */
--n: 10; /* number of dashes*/
--g: 10deg; /* gap between dashes*/
--c: red; /* the color */
width: 100px; /* size */
aspect-ratio: 1;
border-radius: 50%;
padding: 1px;
background: conic-gradient(#0000,var(--c)) content-box;
-webkit-mask:
repeating-conic-gradient(#0000 0deg,
#000 1deg calc(360deg/var(--n) - var(--g) - 1deg),
#0000 calc(360deg/var(--n) - var(--g)) calc(360deg/var(--n))),
radial-gradient(farthest-side,#0000 calc(98% - var(--b)),#000 calc(100% - var(--b)));
mask:
repeating-conic-gradient(#0000 0deg,
#000 1deg calc(360deg/var(--n) - var(--g) - 1deg),
#0000 calc(360deg/var(--n) - var(--g)) calc(360deg/var(--n))),
radial-gradient(farthest-side,#0000 calc(98% - var(--b)),#000 calc(100% - var(--b)));
-webkit-mask-composite: destination-in;
mask-composite: intersect;
animation: load 1s infinite steps(var(--n));
}
@keyframes load {to{transform: rotate(1turn)}}
同じコードを使用する4つの異なるローダーがあります。いくつかの変数を変更するだけで、CSSコードに触れることなく新しいローダーを生成できます。
変数は次のように定義されます。
--b
境界線の太さを定義します。--n
ダッシュの数を定義します。--g
ダッシュ間のギャップを定義します。円形の要素を扱っているので、これは角度の値です。--c
色を定義します。これは、さまざまな変数を確認するための図です。
スピナーローダーのCSS変数
CSSコードに取り組みましょう。別の図を使用して、ローダーの段階的な構成を説明します。
スピナーローダーのステップバイステップの図
まず、次のような円を作成します。
.loader {
width: 100px; /* size */
aspect-ratio: 1;
border-radius: 50%;
}
これまでのところ複雑なことはありません。これを使用すると、サイズを制御するためにaspect-ratio
1つの値()のみを変更できることに注意してください。width
次に、透明から定義された色(変数--c
)に円錐曲線の色を追加します。
.loader {
width:100px; /* size */
aspect-ratio: 1;
border-radius: 50%;
background: conic-gradient(#0000,var(--c));
}
このステップでmask
は、円の一部を繰り返し非表示にするプロパティを紹介します。--n
これはと--d
変数に依存します。図をよく見ると、次のパターンに気付くでしょう。
visible part
invisible part
visible part
invisible part
etc
これを行うには、を使用しますrepeating-conic-gradient(#000 0 X, #0000 0 Y)
。から0
までX
は不透明な色(可視部分)があり、からX
までY
は透明な色(不可視部分)があります。
変数を紹介します。
g
ように、各可視部分の間に等しいギャップが必要です。XYX = Y - g
n
目に見える部分が必要なので、の式Y
はY = 360deg/n
です。完全な円は360deg
、単純にで割ったものです。n
これまでのコードは次のとおりです。
.loader {
width: 100px; /* size */
aspect-ratio: 1;
border-radius: 50%;
background: conic-gradient(#0000,var(--c));
mask: repeating-conic-gradient(#000 0 calc(360deg/var(--n) - var(--g)) , #0000 0 calc(360deg/var(--n))
}
この次のステップは最も難しいステップです。最終的な形状を取得するために、別のマスクを適用して一種の穴を作成する必要があるためです。これを行うにはradial-gradient()
、変数で論理的にaを使用しますb
。
radial-gradient(farthest-side,#0000 calc(100% - var(--b)),#000 0)
に等しい厚さを削除するところから完全な円b
。
これを前のマスクに追加します。
.loader {
width: 100px; /* size */
aspect-ratio: 1;
border-radius: 50%;
background: conic-gradient(#0000,var(--c));
mask:
radial-gradient(farthest-side,#0000 calc(100% - var(--b)),#000 0),
repeating-conic-gradient(#000 0 calc(360deg/var(--n) - var(--g)) , #0000 0 calc(360deg/var(--n))
}
2つのマスクレイヤーがありますが、結果は私たちが望むものではありません。次のようになります。
奇妙に見えるかもしれませんが、それは論理的です。「最終的な」可視部分は、各マスクレイヤーの各可視部分の合計に他なりません。この動作は、を使用して変更できますmask-composite
。このプロパティを説明するために記事全体が必要になるので、単純に値を示します。
intersect
私たちの場合、 (そしてdestination-out
接頭辞付きのプロパティについて)考慮する必要があります。コードは次のようになります。
.loader {
width: 100px; /* size */
aspect-ratio: 1;
border-radius: 50%;
background: conic-gradient(#0000,var(--c));
mask:
radial-gradient(farthest-side,#0000 calc(100% - var(--b)),#000 0),
repeating-conic-gradient(#000 0 calc(360deg/var(--n) - var(--g)) , #0000 0 calc(360deg/var(--n));
-webkit-mask-composite: destination-in;
mask-composite: intersect;
}
形が出来上がりました!アニメーションが欠けているだけです。後者は無限回転です。
注意すべき唯一のことは、steps
アニメーションを使用して、固定されたダッシュと動く色の錯覚を作成しているということです。
これが違いを見るためのイラストです
線形アニメーションとステップアニメーション
最初のものは形状の線形で連続的な回転であり(私たちが望むものではありません)、2番目のものは離散アニメーション(私たちが望むもの)です。
アニメーションを含む完全なコードは次のとおりです。
<div class="loader"></div>
<div class="loader" style="--b: 15px;--c: blue;width: 120px;--n: 8"></div>
<div class="loader" style="--b: 5px;--c: green;width: 80px;--n: 6;--g: 20deg"></div>
<div class="loader" style="--b: 20px;--c: #000;width: 80px;--n: 15;--g: 7deg"></div>
.loader {
--b: 10px; /* border thickness */
--n: 10; /* number of dashes*/
--g: 10deg; /* gap between dashes*/
--c: red; /* the color */
width: 100px; /* size */
aspect-ratio: 1;
border-radius: 50%;
padding: 1px;
background: conic-gradient(#0000,var(--c)) content-box;
-webkit-mask:
repeating-conic-gradient(#0000 0deg,
#000 1deg calc(360deg/var(--n) - var(--g) - 1deg),
#0000 calc(360deg/var(--n) - var(--g)) calc(360deg/var(--n))),
radial-gradient(farthest-side,#0000 calc(98% - var(--b)),#000 calc(100% - var(--b)));
mask:
repeating-conic-gradient(#0000 0deg,
#000 1deg calc(360deg/var(--n) - var(--g) - 1deg),
#0000 calc(360deg/var(--n) - var(--g)) calc(360deg/var(--n))),
radial-gradient(farthest-side,#0000 calc(98% - var(--b)),#000 calc(100% - var(--b)));
-webkit-mask-composite: destination-in;
mask-composite: intersect;
animation: load 1s infinite steps(var(--n));
}
@keyframes load {to{transform: rotate(1turn)}}
説明で使用したコードとの違いに気付くでしょう。
padding: 1px
背景を追加して設定していますcontent-box
+/1deg
の色の間にありますrepeating-conic-gradient()
radial-gradient()
これらは、視覚的な不具合を回避するためのいくつかの修正です。グラデーションは「奇妙な」結果を生成することが知られているため、それらを回避するためにいくつかの値を手動で調整する必要があります。
前のローダーと同様に、概要から始めましょう。
https://codepen.io/t_afif/pen/bGoNddg
<div class="loader"></div>
<div class="loader" style="--s:10px;--n:10;color:red"></div>
<div class="loader" style="--g:0px;color:darkblue"></div>
<div class="loader" style="--s:25px;--g:8px;border-radius:50px;color:green"></div>
.loader {
--n:5; /* control the number of stripes */
--s:30px; /* control the width of stripes */
--g:5px; /* control the gap between stripes */
width:calc(var(--n)*(var(--s) + var(--g)) - var(--g));
height:30px;
padding:var(--g);
margin:5px auto;
border:1px solid;
background:
repeating-linear-gradient(90deg,
currentColor 0 var(--s),
#0000 0 calc(var(--s) + var(--g))
) left / calc((var(--n) + 1)*(var(--s) + var(--g))) 100%
no-repeat content-box;
animation: load 1.5s steps(calc(var(--n) + 1)) infinite;
}
@keyframes load {
0% {background-size: 0% 100%}
}
以前のローダーと同じ構成になっています。ローダーを制御するCSS変数:
--n
ダッシュ/ストライプの数を定義します。--s
各ストライプの幅を定義します。--g
ストライプ間のギャップを定義します。CSS変数の図
上の図から、要素の幅が3つの変数に依存することがわかります。CSSは次のようになります。
.loader {
width: calc(var(--n)*(var(--s) + var(--g)) - var(--g));
height: 30px; /* use any value you want here */
padding: var(--g);
border: 1px solid;
}
padding
両側にギャップを設定するために使用します。その場合、幅はストライプの数に幅とギャップを掛けたものに等しくなります。N
ストライプにはギャップがあるため、1つのギャップを削除しN-1
ます。
ストライプを作成するには、以下のグラデーションを使用します。
repeating-linear-gradient(90deg,
currentColor 0 var(--s),
#0000 0 calc(var(--s) + var(--g))
)
From 0
tos
は定義された色であり、from s
tos + g
は透明色(ギャップ)です。
currentColor
プロパティの値であるwhichを使用していcolor
ます。内部に色を定義しなかったためborder
、の値にも使用されることに注意してくださいcolor
。ローダーの色を変更したい場合は、color
プロパティを設定するだけです。
これまでのコード:
.loader {
width: calc(var(--n)*(var(--s) + var(--g)) - var(--g));
height: 30px;
padding: var(--g);
border: 1px solid;
background:
repeating-linear-gradient(90deg,
currentColor 0 var(--s),
#0000 0 calc(var(--s) + var(--g))
) left / 100% 100% content-box no-repeat;
}
content-box
グラデーションがパディング領域をカバーしないようにするために使用しています。100% 100%
次に、左の位置に等しいサイズを定義します。
アニメーションの時間です。このローダーでは、background-size
from 0% 100%
toをアニメーション化します。これは、fromから toへ100% 100%
のグラデーションの幅を意味します。0%100%
steps()
以前のローダーと同様に、連続的なアニメーションではなく、個別のアニメーションを使用することに依存します。
線形アニメーションとステップアニメーション
2つ目は作成したいもので、次のコードを追加することで実現できます。
.loader {
animation: load 1.5s steps(var(--n)) infinite;
}
@keyframes load {
0% {background-size: 0% 100%}
}
最後の図をよく見ると、アニメーションが完全ではないことがわかります。を使用したとしても、最後に1つのストライプがありませんN
。これはバグではありませんが、どのように機能するsteps()
はずです。
これを克服するには、追加のステップを追加する必要があります。background-size
グラデーションを増やしてN+1
ストライプを含め、を使用しますsteps(N+1)
。これにより、最終的なコードが表示されます。
.loader {
width: calc(var(--n)*(var(--s) + var(--g)) - var(--g));
height: 30px;
padding: var(--g);
margin: 5px auto;
border: 1px solid;
background:
repeating-linear-gradient(90deg,
currentColor 0 var(--s),
#0000 0 calc(var(--s) + var(--g))
) left / calc((var(--n) + 1)*(var(--s) + var(--g))) 100%
content-box no-repeat;
animation: load 1.5s steps(calc(var(--n) + 1)) infinite;
}
@keyframes load {
0% {background-size: 0% 100%}
}
グラデーションの幅は、N+1
(ではなく100%
) 1つのストライプとギャップの幅を掛けたものに等しいことに注意してください。
このチュートリアルを楽しんでいただけたでしょうか。興味があれば、私は500以上のCSSのみのシングルdivローダーを作成しました。また、バックグラウンドプロパティのみを使用してドットローダーを作成する方法を説明する別のチュートリアルを作成しました。
以下の便利なリンクを見つけて、複雑さのために完全には説明しなかった、私が使用したいくつかのプロパティの詳細を確認してください。
mask-composite
:https ://css-tricks.com/mask-compositing-the-crash-course/steps()
:https ://developer.mozilla.org/en-US/docs/Web/CSS/easing-function#the_steps_class_of_easing_functions読んでくれてありがとう!
リンク:https ://www.freecodecamp.org/news/how-to-create-a-css-only-loader/
1643336880
If you have a website, it's helpful to have a loader so users can tell something is happening once they've clicked a link or button.
You can use this loader component in a lot of places, and it should be as simple as possible.
In this post, we will see how to build two types of loaders with only one <div>
and a few lines of CSS code. Not only this but we will make them customizable so you can easily create different variations from the same code.
Here's what we'll build:
CSS-only Spinner and Progress Loader
Below is a demo of what we are building:
https://codepen.io/t_afif/pen/PoJyaNy
<div class="loader"></div>
<div class="loader" style="--b: 15px;--c: blue;width: 120px;--n: 8"></div>
<div class="loader" style="--b: 5px;--c: green;width: 80px;--n: 6;--g: 20deg"></div>
<div class="loader" style="--b: 20px;--c: #000;width: 80px;--n: 15;--g: 7deg"></div>
.loader {
--b: 10px; /* border thickness */
--n: 10; /* number of dashes*/
--g: 10deg; /* gap between dashes*/
--c: red; /* the color */
width: 100px; /* size */
aspect-ratio: 1;
border-radius: 50%;
padding: 1px;
background: conic-gradient(#0000,var(--c)) content-box;
-webkit-mask:
repeating-conic-gradient(#0000 0deg,
#000 1deg calc(360deg/var(--n) - var(--g) - 1deg),
#0000 calc(360deg/var(--n) - var(--g)) calc(360deg/var(--n))),
radial-gradient(farthest-side,#0000 calc(98% - var(--b)),#000 calc(100% - var(--b)));
mask:
repeating-conic-gradient(#0000 0deg,
#000 1deg calc(360deg/var(--n) - var(--g) - 1deg),
#0000 calc(360deg/var(--n) - var(--g)) calc(360deg/var(--n))),
radial-gradient(farthest-side,#0000 calc(98% - var(--b)),#000 calc(100% - var(--b)));
-webkit-mask-composite: destination-in;
mask-composite: intersect;
animation: load 1s infinite steps(var(--n));
}
@keyframes load {to{transform: rotate(1turn)}}
We have 4 different loaders using the same code. By only changing a few variables, we can generate a new loader without needing to touch the CSS code.
The variables are defined like below:
--b
defines the border thickness.--n
defines the number of dashes.--g
defines the gap between dashes. Since we're dealing with a circular element, this one is an angle value.--c
defines the color.Here is an illustration to see the different variables.
CSS Variables of the Spinner loader
Let's tackle the CSS code. We will use another figure to illustrate a step-by-step construction of the loader.
Step-by-Step illustration of the Spinner Loader
We first start by creating a circle like this:
.loader {
width: 100px; /* size */
aspect-ratio: 1;
border-radius: 50%;
}
Nothing complex so far. Note the use of aspect-ratio
which allows us to only modify one value (the width
) in order to control the size.
Then we add a conic gradient coloration from transparent to the defined color (the variable --c
):
.loader {
width:100px; /* size */
aspect-ratio: 1;
border-radius: 50%;
background: conic-gradient(#0000,var(--c));
}
In this step, we introduce the mask
property to hide some parts of the circle in a repetitive manner. This will depend on the --n
and --d
variables. If you look closely at the figure, we will notice the following pattern:
visible part
invisible part
visible part
invisible part
etc
To do this, we use repeating-conic-gradient(#000 0 X, #0000 0 Y)
. From 0
to X
we have an opaque color (visible part) and from X
to Y
we have a transparent one (invisible part).
We introduce our variables:
g
between each visible part so the formula between X
and Y
will be X = Y - g
.n
visible part so the formula of Y
should be Y = 360deg/n
. A full circle is 360deg
so we simply divide it by n
Our code so far is:
.loader {
width: 100px; /* size */
aspect-ratio: 1;
border-radius: 50%;
background: conic-gradient(#0000,var(--c));
mask: repeating-conic-gradient(#000 0 calc(360deg/var(--n) - var(--g)) , #0000 0 calc(360deg/var(--n))
}
This next step is the trickiest one, because we need to apply another mask to create a kind of hole in order to get the final shape. To do this we will logically use a radial-gradient()
with our variable b
:
radial-gradient(farthest-side,#0000 calc(100% - var(--b)),#000 0)
A full circle from where we remove a thickness equal to b
.
We add this to the previous mask:
.loader {
width: 100px; /* size */
aspect-ratio: 1;
border-radius: 50%;
background: conic-gradient(#0000,var(--c));
mask:
radial-gradient(farthest-side,#0000 calc(100% - var(--b)),#000 0),
repeating-conic-gradient(#000 0 calc(360deg/var(--n) - var(--g)) , #0000 0 calc(360deg/var(--n))
}
We have two mask layers, but the result is not what we want. We get the following:
It may look strange but it's logical. The "final" visible part is nothing but the sum of each visible part of each mask layer. We can change this behavior using mask-composite
. I would need a whole article to explain this property so I will simply give the value.
In our case, we need to consider intersect
(and destination-out
for the prefixed property). Our code will become:
.loader {
width: 100px; /* size */
aspect-ratio: 1;
border-radius: 50%;
background: conic-gradient(#0000,var(--c));
mask:
radial-gradient(farthest-side,#0000 calc(100% - var(--b)),#000 0),
repeating-conic-gradient(#000 0 calc(360deg/var(--n) - var(--g)) , #0000 0 calc(360deg/var(--n));
-webkit-mask-composite: destination-in;
mask-composite: intersect;
}
We are done with the shape! We are only missing the animation. The latter is an infinite rotation.
The only thing to note is that I am using a steps
animation to create the illusion of fixed dashes and moving colors.
Here is an illustration to see the difference
A Linear Animation vs a Steps Animation
The first one is a linear and continuous rotation of the shape (not what we want) and the second one is a discrete animation (the one we want).
Here is the full code including the animation:
<div class="loader"></div>
<div class="loader" style="--b: 15px;--c: blue;width: 120px;--n: 8"></div>
<div class="loader" style="--b: 5px;--c: green;width: 80px;--n: 6;--g: 20deg"></div>
<div class="loader" style="--b: 20px;--c: #000;width: 80px;--n: 15;--g: 7deg"></div>
.loader {
--b: 10px; /* border thickness */
--n: 10; /* number of dashes*/
--g: 10deg; /* gap between dashes*/
--c: red; /* the color */
width: 100px; /* size */
aspect-ratio: 1;
border-radius: 50%;
padding: 1px;
background: conic-gradient(#0000,var(--c)) content-box;
-webkit-mask:
repeating-conic-gradient(#0000 0deg,
#000 1deg calc(360deg/var(--n) - var(--g) - 1deg),
#0000 calc(360deg/var(--n) - var(--g)) calc(360deg/var(--n))),
radial-gradient(farthest-side,#0000 calc(98% - var(--b)),#000 calc(100% - var(--b)));
mask:
repeating-conic-gradient(#0000 0deg,
#000 1deg calc(360deg/var(--n) - var(--g) - 1deg),
#0000 calc(360deg/var(--n) - var(--g)) calc(360deg/var(--n))),
radial-gradient(farthest-side,#0000 calc(98% - var(--b)),#000 calc(100% - var(--b)));
-webkit-mask-composite: destination-in;
mask-composite: intersect;
animation: load 1s infinite steps(var(--n));
}
@keyframes load {to{transform: rotate(1turn)}}
You will notice a few differences with the code I used in the explanation:
padding: 1px
and setting the background to content-box
+/1deg
between the colors of the repeating-conic-gradient()
radial-gradient()
Those are some corrections to avoid visual glitches. Gradients are known to produce "strange" results in some cases so we have to adjust some values manually to avoid them.
Like the previous one loader, let's start with an overview:
https://codepen.io/t_afif/pen/bGoNddg
<div class="loader"></div>
<div class="loader" style="--s:10px;--n:10;color:red"></div>
<div class="loader" style="--g:0px;color:darkblue"></div>
<div class="loader" style="--s:25px;--g:8px;border-radius:50px;color:green"></div>
.loader {
--n:5; /* control the number of stripes */
--s:30px; /* control the width of stripes */
--g:5px; /* control the gap between stripes */
width:calc(var(--n)*(var(--s) + var(--g)) - var(--g));
height:30px;
padding:var(--g);
margin:5px auto;
border:1px solid;
background:
repeating-linear-gradient(90deg,
currentColor 0 var(--s),
#0000 0 calc(var(--s) + var(--g))
) left / calc((var(--n) + 1)*(var(--s) + var(--g))) 100%
no-repeat content-box;
animation: load 1.5s steps(calc(var(--n) + 1)) infinite;
}
@keyframes load {
0% {background-size: 0% 100%}
}
We have the same configuration as the previous loader. CSS variables that control the loader:
--n
defines the number of dashes/stripes.--s
defines the width of each stripe.--g
defines the gap between stripes.Illustration of the CSS Variables
From the above figure we can see that the width of the element will depend on the 3 variables. The CSS will be as follows:
.loader {
width: calc(var(--n)*(var(--s) + var(--g)) - var(--g));
height: 30px; /* use any value you want here */
padding: var(--g);
border: 1px solid;
}
We use padding
to set the gap on each side. Then the width will be equal to the number of stripes multiplied by their width and the gap. We remove one gap because for N
stripes we have N-1
gaps.
To create the stripes we will use the below gradient.
repeating-linear-gradient(90deg,
currentColor 0 var(--s),
#0000 0 calc(var(--s) + var(--g))
)
From 0
to s
is the defined color and from s
to s + g
a transparent color (the gap).
I am using currentColor
which is the value of the color
property. Note that I didn't define any color inside border
so it will also use to the value of color
. If we want to change the color of the loader, we only need to set the color
property.
Our code so far:
.loader {
width: calc(var(--n)*(var(--s) + var(--g)) - var(--g));
height: 30px;
padding: var(--g);
border: 1px solid;
background:
repeating-linear-gradient(90deg,
currentColor 0 var(--s),
#0000 0 calc(var(--s) + var(--g))
) left / 100% 100% content-box no-repeat;
}
I am using content-box
to make sure the gradient doesn't cover the padding area. Then I define a size equal to 100% 100%
and a left position.
It's time for the animation. For this loader, we will animate the background-size
from 0% 100%
to 100% 100%
which means the width of our gradient from 0%
to 100%
Like the previous loader, we will rely on steps()
to have a discrete animation instead of a continuous one.
A Linear Animation vs a Steps Animation
The second one is what we want to create, and we can achieve it by adding the following code:
.loader {
animation: load 1.5s steps(var(--n)) infinite;
}
@keyframes load {
0% {background-size: 0% 100%}
}
If you look closely at the last figure, you will notice that the animation is not complete. We are missing one stripe at the end, even if we have used N
. This is not a bug but how steps()
is supposed to work.
To overcome this, we need to add an extra step. We increase the background-size
of our gradient to contain N+1
stripes and use steps(N+1)
. This will get us to the final code:
.loader {
width: calc(var(--n)*(var(--s) + var(--g)) - var(--g));
height: 30px;
padding: var(--g);
margin: 5px auto;
border: 1px solid;
background:
repeating-linear-gradient(90deg,
currentColor 0 var(--s),
#0000 0 calc(var(--s) + var(--g))
) left / calc((var(--n) + 1)*(var(--s) + var(--g))) 100%
content-box no-repeat;
animation: load 1.5s steps(calc(var(--n) + 1)) infinite;
}
@keyframes load {
0% {background-size: 0% 100%}
}
Note that the width of the gradient is equal to N+1
multiplied by the width of one stripe and a gap (instead of being 100%
)
I hope you enjoyed this tutorial. If you are interested, I have made more than 500 CSS-only single div loaders. I also wrote another tutorial to explain how to create the Dots loader using only background properties.
Find below useful links to get more detail about some properties I have used that I didn't explain thoroughly due to their complexity:
mask-composite
: https://css-tricks.com/mask-compositing-the-crash-course/steps()
: https://developer.mozilla.org/en-US/docs/Web/CSS/easing-function#the_steps_class_of_easing_functionsThank you for reading!
Link: https://www.freecodecamp.org/news/how-to-create-a-css-only-loader/
1642484580
Si tiene un sitio web, es útil tener un cargador para que los usuarios puedan saber que algo está sucediendo una vez que hayan hecho clic en un enlace o botón.
Puede usar este componente del cargador en muchos lugares y debería ser lo más simple posible.
En esta publicación, veremos cómo construir dos tipos de cargadores con solo una <div>
y unas pocas líneas de código CSS. No solo esto, sino que los haremos personalizables para que pueda crear fácilmente diferentes variaciones del mismo código.
Esto es lo que construiremos:
Spinner y Progress Loader solo para CSS
A continuación se muestra una demostración de lo que estamos construyendo:
https://codepen.io/t_afif/pen/PoJyaNy
<div class="loader"></div>
<div class="loader" style="--b: 15px;--c: blue;width: 120px;--n: 8"></div>
<div class="loader" style="--b: 5px;--c: green;width: 80px;--n: 6;--g: 20deg"></div>
<div class="loader" style="--b: 20px;--c: #000;width: 80px;--n: 15;--g: 7deg"></div>
.loader {
--b: 10px; /* border thickness */
--n: 10; /* number of dashes*/
--g: 10deg; /* gap between dashes*/
--c: red; /* the color */
width: 100px; /* size */
aspect-ratio: 1;
border-radius: 50%;
padding: 1px;
background: conic-gradient(#0000,var(--c)) content-box;
-webkit-mask:
repeating-conic-gradient(#0000 0deg,
#000 1deg calc(360deg/var(--n) - var(--g) - 1deg),
#0000 calc(360deg/var(--n) - var(--g)) calc(360deg/var(--n))),
radial-gradient(farthest-side,#0000 calc(98% - var(--b)),#000 calc(100% - var(--b)));
mask:
repeating-conic-gradient(#0000 0deg,
#000 1deg calc(360deg/var(--n) - var(--g) - 1deg),
#0000 calc(360deg/var(--n) - var(--g)) calc(360deg/var(--n))),
radial-gradient(farthest-side,#0000 calc(98% - var(--b)),#000 calc(100% - var(--b)));
-webkit-mask-composite: destination-in;
mask-composite: intersect;
animation: load 1s infinite steps(var(--n));
}
@keyframes load {to{transform: rotate(1turn)}}
Tenemos 4 cargadores diferentes usando el mismo código. Con solo cambiar algunas variables, podemos generar un nuevo cargador sin necesidad de tocar el código CSS.
Las variables se definen como sigue:
--b
define el grosor del borde.--n
define el número de guiones.--g
define el espacio entre guiones. Como estamos tratando con un elemento circular, este es un valor de ángulo.--c
define el color.Aquí hay una ilustración para ver las diferentes variables.
Variables CSS del cargador Spinner
Abordemos el código CSS. Usaremos otra figura para ilustrar una construcción paso a paso del cargador.
Ilustración paso a paso del cargador giratorio
Primero comenzamos creando un círculo como este:
.loader {
width: 100px; /* size */
aspect-ratio: 1;
border-radius: 50%;
}
Nada complejo hasta ahora. Tenga en cuenta que su uso aspect-ratio
nos permite modificar solo un valor (el width
) para controlar el tamaño.
Luego agregamos una coloración de degradado cónico de transparente al color definido (la variable --c
):
.loader {
width:100px; /* size */
aspect-ratio: 1;
border-radius: 50%;
background: conic-gradient(#0000,var(--c));
}
En este paso, introducimos la mask
propiedad para ocultar algunas partes del círculo de forma repetitiva. Esto dependerá de las variables --n
y . --d
Si observa detenidamente la figura, notaremos el siguiente patrón:
visible part
invisible part
visible part
invisible part
etc
Para hacer esto, usamos repeating-conic-gradient(#000 0 X, #0000 0 Y)
. De 0
a X
tenemos un color opaco (parte visible) y de X
a Y
tenemos uno transparente (parte invisible).
Introducimos nuestras variables:
g
entre cada parte visible por lo que la fórmula entre X
y Y
será X = Y - g
.n
la parte visible, por lo que la fórmula de Y
debería ser Y = 360deg/n
. Un círculo completo es 360deg
así que simplemente lo dividimos porn
Nuestro código hasta ahora es:
.loader {
width: 100px; /* size */
aspect-ratio: 1;
border-radius: 50%;
background: conic-gradient(#0000,var(--c));
mask: repeating-conic-gradient(#000 0 calc(360deg/var(--n) - var(--g)) , #0000 0 calc(360deg/var(--n))
}
El siguiente paso es el más complicado, porque necesitamos aplicar otra máscara para crear una especie de agujero para obtener la forma final. Para ello usaremos lógicamente a radial-gradient()
con nuestra variable b
:
radial-gradient(farthest-side,#0000 calc(100% - var(--b)),#000 0)
Un círculo completo del que quitamos un espesor igual a b
.
Añadimos esto a la máscara anterior:
.loader {
width: 100px; /* size */
aspect-ratio: 1;
border-radius: 50%;
background: conic-gradient(#0000,var(--c));
mask:
radial-gradient(farthest-side,#0000 calc(100% - var(--b)),#000 0),
repeating-conic-gradient(#000 0 calc(360deg/var(--n) - var(--g)) , #0000 0 calc(360deg/var(--n))
}
Tenemos dos capas de máscara, pero el resultado no es el que queremos. Obtenemos lo siguiente:
Puede parecer extraño pero es lógico. La parte visible "final" no es más que la suma de cada parte visible de cada capa de máscara. Podemos cambiar este comportamiento usando mask-composite
. Necesitaría un artículo completo para explicar esta propiedad, así que simplemente daré el valor.
En nuestro caso, debemos considerar intersect
(y destination-out
para la propiedad prefijada). Nuestro código se convertirá en:
.loader {
width: 100px; /* size */
aspect-ratio: 1;
border-radius: 50%;
background: conic-gradient(#0000,var(--c));
mask:
radial-gradient(farthest-side,#0000 calc(100% - var(--b)),#000 0),
repeating-conic-gradient(#000 0 calc(360deg/var(--n) - var(--g)) , #0000 0 calc(360deg/var(--n));
-webkit-mask-composite: destination-in;
mask-composite: intersect;
}
¡Hemos terminado con la forma! Solo nos falta la animación. Esta última es una rotación infinita.
Lo único a tener en cuenta es que estoy usando una steps
animación para crear la ilusión de guiones fijos y colores en movimiento.
Aquí hay una ilustración para ver la diferencia.
Una animación lineal frente a una animación de pasos
La primera es una rotación lineal y continua de la forma (no la que queremos) y la segunda es una animación discreta (la que queremos).
Aquí está el código completo, incluida la animación:
<div class="loader"></div>
<div class="loader" style="--b: 15px;--c: blue;width: 120px;--n: 8"></div>
<div class="loader" style="--b: 5px;--c: green;width: 80px;--n: 6;--g: 20deg"></div>
<div class="loader" style="--b: 20px;--c: #000;width: 80px;--n: 15;--g: 7deg"></div>
.loader {
--b: 10px; /* border thickness */
--n: 10; /* number of dashes*/
--g: 10deg; /* gap between dashes*/
--c: red; /* the color */
width: 100px; /* size */
aspect-ratio: 1;
border-radius: 50%;
padding: 1px;
background: conic-gradient(#0000,var(--c)) content-box;
-webkit-mask:
repeating-conic-gradient(#0000 0deg,
#000 1deg calc(360deg/var(--n) - var(--g) - 1deg),
#0000 calc(360deg/var(--n) - var(--g)) calc(360deg/var(--n))),
radial-gradient(farthest-side,#0000 calc(98% - var(--b)),#000 calc(100% - var(--b)));
mask:
repeating-conic-gradient(#0000 0deg,
#000 1deg calc(360deg/var(--n) - var(--g) - 1deg),
#0000 calc(360deg/var(--n) - var(--g)) calc(360deg/var(--n))),
radial-gradient(farthest-side,#0000 calc(98% - var(--b)),#000 calc(100% - var(--b)));
-webkit-mask-composite: destination-in;
mask-composite: intersect;
animation: load 1s infinite steps(var(--n));
}
@keyframes load {to{transform: rotate(1turn)}}
Notarás algunas diferencias con el código que usé en la explicación:
padding: 1px
y configurando el fondo paracontent-box
+/1deg
entre los colores de larepeating-conic-gradient()
radial-gradient()
Esas son algunas correcciones para evitar fallas visuales. Se sabe que los degradados producen resultados "extraños" en algunos casos, por lo que debemos ajustar algunos valores manualmente para evitarlos.
Al igual que el cargador anterior, comencemos con una descripción general:
https://codepen.io/t_afif/pen/bGoNddg
<div class="loader"></div>
<div class="loader" style="--s:10px;--n:10;color:red"></div>
<div class="loader" style="--g:0px;color:darkblue"></div>
<div class="loader" style="--s:25px;--g:8px;border-radius:50px;color:green"></div>
.loader {
--n:5; /* control the number of stripes */
--s:30px; /* control the width of stripes */
--g:5px; /* control the gap between stripes */
width:calc(var(--n)*(var(--s) + var(--g)) - var(--g));
height:30px;
padding:var(--g);
margin:5px auto;
border:1px solid;
background:
repeating-linear-gradient(90deg,
currentColor 0 var(--s),
#0000 0 calc(var(--s) + var(--g))
) left / calc((var(--n) + 1)*(var(--s) + var(--g))) 100%
no-repeat content-box;
animation: load 1.5s steps(calc(var(--n) + 1)) infinite;
}
@keyframes load {
0% {background-size: 0% 100%}
}
Tenemos la misma configuración que el cargador anterior. Variables CSS que controlan el cargador:
--n
define el número de guiones/rayas.--s
define el ancho de cada franja.--g
define el espacio entre las rayas.Ilustración de las variables CSS
De la figura anterior podemos ver que el ancho del elemento dependerá de las 3 variables. El CSS será el siguiente:
.loader {
width: calc(var(--n)*(var(--s) + var(--g)) - var(--g));
height: 30px; /* use any value you want here */
padding: var(--g);
border: 1px solid;
}
Usamos padding
para establecer el espacio en cada lado. Entonces el ancho será igual al número de rayas multiplicado por su ancho y el espacio. Eliminamos un espacio porque para N
las rayas tenemos N-1
espacios.
Para crear las rayas usaremos el siguiente degradado.
repeating-linear-gradient(90deg,
currentColor 0 var(--s),
#0000 0 calc(var(--s) + var(--g))
)
De 0
a s
es el color definido y de s
a s + g
un color transparente (la brecha).
Estoy usando currentColor
cuál es el valor de la color
propiedad. Tenga en cuenta que no definí ningún color dentro border
, por lo que también se usará para el valor de color
. Si queremos cambiar el color del cargador, solo necesitamos establecer la color
propiedad.
Nuestro código hasta ahora:
.loader {
width: calc(var(--n)*(var(--s) + var(--g)) - var(--g));
height: 30px;
padding: var(--g);
border: 1px solid;
background:
repeating-linear-gradient(90deg,
currentColor 0 var(--s),
#0000 0 calc(var(--s) + var(--g))
) left / 100% 100% content-box no-repeat;
}
Estoy usando content-box
para asegurarme de que el degradado no cubra el área de relleno. Luego defino un tamaño igual a 100% 100%
y una posición izquierda.
Es hora de la animación. Para este cargador, animaremos el background-size
de 0% 100%
a 100% 100%
lo que significa el ancho de nuestro degradado de 0%
a100%
Al igual que el cargador anterior, confiaremos en steps()
tener una animación discreta en lugar de una continua.
Una animación lineal frente a una animación de pasos
El segundo es el que queremos crear, y lo podemos lograr agregando el siguiente código:
.loader {
animation: load 1.5s steps(var(--n)) infinite;
}
@keyframes load {
0% {background-size: 0% 100%}
}
Si observa detenidamente la última figura, notará que la animación no está completa. Nos falta una raya al final, incluso si hemos usado N
. Esto no es un error, sino cómo steps()
se supone que funciona.
Para superar esto, necesitamos agregar un paso adicional. Aumentamos el background-size
de nuestro degradado para contener N+1
rayas y usar steps(N+1)
. Esto nos llevará al código final:
.loader {
width: calc(var(--n)*(var(--s) + var(--g)) - var(--g));
height: 30px;
padding: var(--g);
margin: 5px auto;
border: 1px solid;
background:
repeating-linear-gradient(90deg,
currentColor 0 var(--s),
#0000 0 calc(var(--s) + var(--g))
) left / calc((var(--n) + 1)*(var(--s) + var(--g))) 100%
content-box no-repeat;
animation: load 1.5s steps(calc(var(--n) + 1)) infinite;
}
@keyframes load {
0% {background-size: 0% 100%}
}
Tenga en cuenta que el ancho del degradado es igual a N+1
multiplicado por el ancho de una franja y un espacio (en lugar de ser 100%
)
Espero que disfrutes este tutorial. Si está interesado, he creado más de 500 cargadores div únicos solo para CSS . También escribí otro tutorial para explicar cómo crear el cargador de puntos usando solo propiedades de fondo .
Encuentre a continuación enlaces útiles para obtener más detalles sobre algunas propiedades que he usado y que no expliqué a fondo debido a su complejidad:
mask-composite
: https://css-tricks.com/mask-compositing-the-crash-course/steps()
: https://developer.mozilla.org/en-US/docs/Web/CSS/easing-function#the_steps_class_of_easing_functions¡Gracias por leer!
Enlace: https://www.freecodecamp.org/news/how-to-create-a-css-only-loader/
1664775764
How to create a game app is a comprehensive guide, explaining the entire process of creating and publishing games for iOS and Android. Covering all the essential information a budding game developer needs to know.
Read More - https://www.brsoftech.com/blog/how-to-create-a-game-app/