Orbit Ring Loader オービットリングローダー
Satellite dots smoothly orbiting around a central core using pure CSS transforms. CSSトランスフォームを用いた中央コア周囲の衛星ドット周回ローダー。
ライブデモ Live Demo
読み込み中... Loading...
概要・用途・特徴Overview, Usage & Features
何ができるかWhat it does
A sleek loading animation featuring satellite dots orbiting a static glowing core with smooth CSS 3D-feel transforms.
中央のコアの周囲を複数のサテライトドットが周回する、スムーズなCSS回転アニメーションローダー。
どこで使うかWhere to use
Used inside loading screens, cards, modals, or centered async wrappers.
ローディング画面、カードコンポーネント、モーダル、または非同期データ待機エリアで使用します。
特徴Key features
Pure CSS keyframes, scoped custom properties, accessibility support with role="status", prefers-reduced-motion fallbacks, and pause/resume states.
CSSアニメーションのみで構成、スコープ付きカスタムプロパティ、role="status"によるアクセシビリティ対応、prefers-reduced-motion時の静的表示、一時停止対応。
調整可能パラメータ Adjustable Parameters
| Parameter | Default | Description |
|---|---|---|
duration | 1.4s | Animation cycle duration |
size | 64px | Width and height of the loader container |
color | #818cf8 | Primary accent color of the loader |
実装コード Implementation Code
<div class="s011-loader" role="status" aria-label="Loading">
<span class="s011-sr-only">Loading</span>
<div class="s011-core" aria-hidden="true"></div>
<div class="s011-orbit" aria-hidden="true">
<div class="s011-satellite"></div>
<div class="s011-satellite"></div>
<div class="s011-satellite"></div>
</div>
</div>
.s011-loader {
--s011-size: 64px;
--s011-duration: 1.4s;
--s011-color: #818cf8;
--s011-accent: #06b6d4;
position: relative;
width: var(--s011-size);
height: var(--s011-size);
display: inline-flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
}
.s011-sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
.s011-core {
width: calc(var(--s011-size) * 0.22);
height: calc(var(--s011-size) * 0.22);
border-radius: 50%;
background: radial-gradient(circle, #ffffff 10%, var(--s011-color) 70%, transparent 100%);
box-shadow: 0 0 14px var(--s011-color);
z-index: 1;
}
.s011-orbit {
position: absolute;
inset: 0;
border-radius: 50%;
border: 1.5px dashed rgba(129, 140, 248, 0.25);
animation: s011-spin var(--s011-duration) cubic-bezier(0.45, 0.05, 0.55, 0.95) infinite;
}
.s011-satellite {
position: absolute;
top: 50%;
left: 50%;
width: calc(var(--s011-size) * 0.16);
height: calc(var(--s011-size) * 0.16);
margin: calc(var(--s011-size) * -0.08);
border-radius: 50%;
background: var(--s011-accent);
box-shadow: 0 0 8px var(--s011-accent);
}
.s011-satellite:nth-child(1) {
transform: rotate(0deg) translate(calc(var(--s011-size) * 0.44));
}
.s011-satellite:nth-child(2) {
transform: rotate(120deg) translate(calc(var(--s011-size) * 0.44));
background: var(--s011-color);
box-shadow: 0 0 8px var(--s011-color);
}
.s011-satellite:nth-child(3) {
transform: rotate(240deg) translate(calc(var(--s011-size) * 0.44));
background: #a855f7;
box-shadow: 0 0 8px #a855f7;
}
@keyframes s011-spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.s011-loader.paused,
.s011-loader[data-paused="true"],
.s011-loader.paused *,
.s011-loader[data-paused="true"] * {
animation-play-state: paused !important;
}
@media screen and (prefers-reduced-motion: reduce) {
.s011-orbit {
animation: none !important;
border-style: solid;
border-color: rgba(129, 140, 248, 0.4);
}
}
import React from 'react';
import './S-011.css';
export default function S011OrbitRingLoader({
size = 64,
duration = 1.4,
color = '#818cf8',
label = 'Loading',
paused = false,
className = ''
}) {
const rootStyle = {
'--s011-size': typeof size === 'number' ? `${size}px` : size,
'--s011-duration': typeof duration === 'number' ? `${duration}s` : duration,
'--s011-color': color
};
const classNames = [
's011-loader',
paused ? 'paused' : '',
className
].filter(Boolean).join(' ');
return (
<div
className={classNames}
style={rootStyle}
role="status"
aria-label={label}
data-paused={paused ? 'true' : undefined}
>
<span className="s011-sr-only">{label}</span>
<div className="s011-core" aria-hidden="true" />
<div className="s011-orbit" aria-hidden="true">
<div className="s011-satellite" />
<div className="s011-satellite" />
<div className="s011-satellite" />
</div>
</div>
);
}
.s011-loader {
--s011-size: 64px;
--s011-duration: 1.4s;
--s011-color: #818cf8;
--s011-accent: #06b6d4;
position: relative;
width: var(--s011-size);
height: var(--s011-size);
display: inline-flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
}
.s011-sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
.s011-core {
width: calc(var(--s011-size) * 0.22);
height: calc(var(--s011-size) * 0.22);
border-radius: 50%;
background: radial-gradient(circle, #ffffff 10%, var(--s011-color) 70%, transparent 100%);
box-shadow: 0 0 14px var(--s011-color);
z-index: 1;
}
.s011-orbit {
position: absolute;
inset: 0;
border-radius: 50%;
border: 1.5px dashed rgba(129, 140, 248, 0.25);
animation: s011-spin var(--s011-duration) cubic-bezier(0.45, 0.05, 0.55, 0.95) infinite;
}
.s011-satellite {
position: absolute;
top: 50%;
left: 50%;
width: calc(var(--s011-size) * 0.16);
height: calc(var(--s011-size) * 0.16);
margin: calc(var(--s011-size) * -0.08);
border-radius: 50%;
background: var(--s011-accent);
box-shadow: 0 0 8px var(--s011-accent);
}
.s011-satellite:nth-child(1) {
transform: rotate(0deg) translate(calc(var(--s011-size) * 0.44));
}
.s011-satellite:nth-child(2) {
transform: rotate(120deg) translate(calc(var(--s011-size) * 0.44));
background: var(--s011-color);
box-shadow: 0 0 8px var(--s011-color);
}
.s011-satellite:nth-child(3) {
transform: rotate(240deg) translate(calc(var(--s011-size) * 0.44));
background: #a855f7;
box-shadow: 0 0 8px #a855f7;
}
@keyframes s011-spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.s011-loader.paused,
.s011-loader[data-paused="true"],
.s011-loader.paused *,
.s011-loader[data-paused="true"] * {
animation-play-state: paused !important;
}
@media screen and (prefers-reduced-motion: reduce) {
.s011-orbit {
animation: none !important;
border-style: solid;
border-color: rgba(129, 140, 248, 0.4);
}
}
仕組みとカスタマイズHow It Works & Customization
仕組みHow it works
Combines CSS custom properties and keyframe transforms to animate visual geometry smoothly while keeping assistive technologies informed.
CSSカスタムプロパティとキーフレームを組み合わせ、支援技術に配慮しながら滑らかなアニメーションを実行します。
カスタマイズ方法Customization
Adjust duration, size, and accent colors via scoped CSS variables or React component props.
CSSカスタムプロパティまたはReactコンポーネントのProps経由でサイズ・周期・色を自在に変更可能です。
注意点Caveats
Always ensure meaningful label text for screen reader users and preserve reduced-motion overrides.
スクリーンリーダー向けのラベルテキストを適切に指定し、prefers-reduced-motion設定を上書きしないようご注意ください。
よくある質問 Frequently Asked Questions
How can I change the animation speed of Orbit Ring Loader? オービットリングローダーのアニメーション速度を変更するにはどうすればよいですか?
Override the --s011-duration CSS variable or pass the duration prop to the React component.
CSS変数 --s011-duration を指定するか、Reactコンポーネントの duration プロパティを設定してください。
Does this snippet support prefers-reduced-motion? prefers-reduced-motion(視覚効果の抑制設定)に対応していますか?
Yes, it provides explicit media query overrides that freeze or stabilize animations without disappearing.
はい。メディアクエリによりアニメーションを停止し、要素が非表示にならない安定した静止形状を表示します。
AIへの指示テンプレート AI Prompt Template
以下をAIに貼り付けると実装を依頼できます。 Paste the following into your AI assistant to request implementation.