Neon Glow Ring Loader ネオングローリングローダー
Dual counter-rotating neon glow rings with pulsating energy core. 二重同心リングの逆回転とネオングローによるフューチャリスティックなローディング演出。
ライブデモ Live Demo
システム初期化中... System Initializing...
概要・用途・特徴Overview, Usage & Features
何ができるかWhat it does
A dual-ring loading spinner featuring two concentric borders rotating in opposite directions with intense drop-shadow neon glows.
外側と内側で逆回転する二重のネオンリングと、中央で脈動する白色コアからなるサイバーパンク調のローダーです。
どこで使うかWhere to use
Designed for gaming experiences, dark-themed developer tools, crypto webapps, and AI computing terminals.
ダークテーマのUI、ゲーミングプラットフォーム、開発者ツール、暗号資産アプリ、AIターミナルなどに最適です。
特徴Key features
Pure CSS drop-shadow glow, differential counter-rotation, pulsating center core, role="status" support, reduced-motion fallback.
CSS drop-shadowによる高品位グロー、二重リングの逆回転アニメーション、中心コアの明滅、role="status"対応、prefers-reduced-motion考慮。
調整可能パラメータ Adjustable Parameters
| Parameter | Default | Description |
|---|---|---|
size | 64px | Outer ring diameter |
speed | 1.8s | Outer ring rotation duration |
outer-color | #06b6d4 | Cyan outer neon glow color |
inner-color | #ec4899 | Magenta inner neon glow color |
実装コード Implementation Code
<div class="s019-loader" role="status" aria-label="Loading">
<span class="s019-sr-only">Loading</span>
<div class="s019-ring-outer" aria-hidden="true"></div>
<div class="s019-ring-inner" aria-hidden="true"></div>
<div class="s019-core-dot" aria-hidden="true"></div>
</div>
.s019-loader {
--s019-size: 64px;
--s019-speed: 1.8s;
--s019-outer-color: #06b6d4;
--s019-inner-color: #ec4899;
position: relative;
width: var(--s019-size);
height: var(--s019-size);
display: inline-flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
}
.s019-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;
}
.s019-ring-outer {
position: absolute;
inset: 0;
border-radius: 50%;
border: 3px solid transparent;
border-top-color: var(--s019-outer-color);
border-right-color: var(--s019-outer-color);
filter: drop-shadow(0 0 8px var(--s019-outer-color));
animation: s019-spin-cw var(--s019-speed) cubic-bezier(0.5, 0, 0.5, 1) infinite;
}
.s019-ring-inner {
position: absolute;
inset: calc(var(--s019-size) * 0.18);
border-radius: 50%;
border: 2.5px solid transparent;
border-bottom-color: var(--s019-inner-color);
border-left-color: var(--s019-inner-color);
filter: drop-shadow(0 0 6px var(--s019-inner-color));
animation: s019-spin-ccw calc(var(--s019-speed) * 0.75) cubic-bezier(0.5, 0, 0.5, 1) infinite;
}
.s019-core-dot {
width: calc(var(--s019-size) * 0.12);
height: calc(var(--s019-size) * 0.12);
border-radius: 50%;
background: #ffffff;
box-shadow: 0 0 10px #ffffff, 0 0 16px var(--s019-outer-color);
animation: s019-pulse calc(var(--s019-speed) * 0.5) ease-in-out infinite alternate;
}
@keyframes s019-spin-cw {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
@keyframes s019-spin-ccw {
from { transform: rotate(360deg); }
to { transform: rotate(0deg); }
}
@keyframes s019-pulse {
from { transform: scale(0.7); opacity: 0.6; }
to { transform: scale(1.15); opacity: 1; }
}
.s019-loader.paused,
.s019-loader[data-paused="true"],
.s019-loader.paused *,
.s019-loader[data-paused="true"] * {
animation-play-state: paused !important;
}
@media screen and (prefers-reduced-motion: reduce) {
.s019-ring-outer,
.s019-ring-inner,
.s019-core-dot {
animation: none !important;
opacity: 0.8;
}
}
import React from 'react';
import './S-019.css';
export default function NeonGlowRingLoader({
size = 64,
speed = 1.8,
outerColor = '#06b6d4',
innerColor = '#ec4899',
paused = false
}) {
const style = {
'--s019-size': `${size}px`,
'--s019-speed': `${speed}s`,
'--s019-outer-color': outerColor,
'--s019-inner-color': innerColor,
};
return (
<div
className={`s019-loader ${paused ? 'paused' : ''}`}
style={style}
role="status"
aria-label="Loading"
>
<span className="s019-sr-only">Loading</span>
<div className="s019-ring-outer" aria-hidden="true" />
<div className="s019-ring-inner" aria-hidden="true" />
<div className="s019-core-dot" aria-hidden="true" />
</div>
);
}
.s019-loader {
width: var(--s019-size, 64px);
height: var(--s019-size, 64px);
position: relative;
display: inline-flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
}
.s019-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;
}
.s019-ring-outer {
position: absolute;
inset: 0;
border-radius: 50%;
border: 3px solid transparent;
border-top-color: var(--s019-outer-color, #06b6d4);
border-right-color: var(--s019-outer-color, #06b6d4);
filter: drop-shadow(0 0 8px var(--s019-outer-color, #06b6d4));
animation: s019-spin-cw var(--s019-speed, 1.8s) cubic-bezier(0.5, 0, 0.5, 1) infinite;
}
.s019-ring-inner {
position: absolute;
inset: calc(var(--s019-size, 64px) * 0.18);
border-radius: 50%;
border: 2.5px solid transparent;
border-bottom-color: var(--s019-inner-color, #ec4899);
border-left-color: var(--s019-inner-color, #ec4899);
filter: drop-shadow(0 0 6px var(--s019-inner-color, #ec4899));
animation: s019-spin-ccw calc(var(--s019-speed, 1.8s) * 0.75) cubic-bezier(0.5, 0, 0.5, 1) infinite;
}
.s019-core-dot {
width: calc(var(--s019-size, 64px) * 0.12);
height: calc(var(--s019-size, 64px) * 0.12);
border-radius: 50%;
background: #ffffff;
box-shadow: 0 0 10px #ffffff, 0 0 16px var(--s019-outer-color, #06b6d4);
animation: s019-pulse calc(var(--s019-speed, 1.8s) * 0.5) ease-in-out infinite alternate;
}
@keyframes s019-spin-cw {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
@keyframes s019-spin-ccw {
from { transform: rotate(360deg); }
to { transform: rotate(0deg); }
}
@keyframes s019-pulse {
from { transform: scale(0.7); opacity: 0.6; }
to { transform: scale(1.15); opacity: 1; }
}
.s019-loader.paused,
.s019-loader[data-paused="true"],
.s019-loader.paused *,
.s019-loader[data-paused="true"] * {
animation-play-state: paused !important;
}
@media screen and (prefers-reduced-motion: reduce) {
.s019-ring-outer,
.s019-ring-inner,
.s019-core-dot {
animation: none !important;
opacity: 0.8;
}
}
仕組みとカスタマイズHow It Works & Customization
仕組みHow it works
Transparent borders reveal localized colored arcs on each circle. Separate keyframe rotations apply opposite angular speeds.
透明ボーダーの一部にのみ色を付与した円形要素を重ね、それぞれ時計回り・反時計回りの異なる速度で回転させています。
カスタマイズ方法Customization
Adjust outer and inner ring colors, duration, and diameter via custom properties or React props.
CSSカスタムプロパティ(--s019-size, --s019-speed, --s019-outer-color, --s019-inner-color)またはReact propsで色や速度を調整可能です。
注意点Caveats
Best suited for dark UI surfaces. Provide appropriate contrast if rendered on light backgrounds.
ダークテーマの背景に最も映えるデザインです。ライトテーマで使用する場合は、濃色のアクセントカラーを選択してください。
よくある質問 Frequently Asked Questions
Can I configure separate rotation times for each ring? 各リングの回転時間を個別に設定できますか?
Yes, customize the outer speed via --s019-speed and the inner ring duration in the CSS animation property.
はい、--s019-speed 変数に加え、CSSルール内の内輪アニメーション速度(デフォルト75%)を自由に調整できます。
Does it cause browser repaints during rotation? 回転中にブラウザの再描画(リペイント)負荷はかかりますか?
No, rotation is handled purely on the compositor thread via transform: rotate.
いいえ、transform: rotate によるコンポジタスレッドでのGPU処理のため、メインスレッドへの再描画負荷は最小限です。
AIへの指示テンプレート AI Prompt Template
以下をAIに貼り付けると実装を依頼できます。 Paste the following into your AI assistant to request implementation.