Pure CSS UI: Buttons, Loaders, and Animations Without JavaScript
June 4, 2026 · 3 min read
JavaScript is often the first tool developers reach for when they want interactivity or animation. But buttons, loading spinners, and keyframe animations can all be built with CSS alone — no JavaScript, no external libraries, no images. This guide walks through each one, explains why it works, and points to free generators so you can copy-paste the code without writing it by hand.
CSS buttons
A good button is mostly padding, a clear background color, a readable text color, and a hover state. CSS handles all of that natively:
.button {
background: #6366f1;
color: #ffffff;
padding: 11px 22px;
border: none;
border-radius: 8px;
font-size: 15px;
font-weight: 600;
cursor: pointer;
transition: background 0.2s ease;
}
.button:hover {
background: #4f46e5;
}
The transition property is key — it smoothly interpolates the background change on hover instead of snapping instantly. No JavaScript needed; the browser handles the hover state via the :hover pseudo-class.
Use the CSS Button Generator to tune the colors, padding, radius, and border visually and copy the finished CSS.
CSS loading spinners
The classic spinner is built entirely from one <div>:
.loader {
width: 48px;
height: 48px;
border: 5px solid #e5e7eb;
border-top-color: #6366f1;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
How it works: three sides of the border are the light "track" color; the top is the accent color. When the element rotates continuously, the accent arc appears to move around the track. No images, no inline SVG, no JavaScript — just a border-radius: 50% div and a rotate keyframe.
Customize size, thickness, colors, and speed with the CSS Loader Generator.
CSS keyframe animations
@keyframes lets you define a named animation that any element can use:
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
.card {
animation: fadeIn 0.4s ease-out;
}
You can animate almost any CSS property — opacity, transform, color, background. More complex animations use percentage stops instead of from/to:
@keyframes bounce {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-30px); }
}
The animation shorthand takes: name, duration, timing function, delay, and iteration count (infinite to loop). The CSS Animation Generator covers fades, slides, scales, rotates, bounces, pulses, and shakes — pick a preset, tune the timing, and copy the CSS.
CSS transitions
Transitions are simpler than keyframes — they animate between two states (usually the default and a :hover, :focus, or :active state) without defining explicit frames:
.box {
transform: scale(1);
transition: transform 0.2s ease-out;
}
.box:hover {
transform: scale(1.05);
}
If you just need a smooth hover or focus effect rather than a full looping animation, transition is the right tool. The CSS Transition Generator lets you configure any property, duration, and easing curve.
Why go JavaScript-free?
- No runtime dependency — CSS animations run on the compositor thread and are not blocked by JavaScript execution.
- Less code to ship — a pure-CSS spinner is under 10 lines; a JS equivalent requires a library or more boilerplate.
- Better performance —
opacityandtransformanimations run off the main thread and don't cause layout reflows. - Works before JS loads — pure CSS UI is visible and functional even if your JavaScript bundle is slow to parse.
None of this means JavaScript is never the right tool — interactive state, complex sequencing, and dynamic data still belong in JS. But visual polish like hover states, entry animations, and loading indicators almost never needs it.
Try the generators
All three generators run locally in your browser and produce clean, copy-paste CSS:
- CSS Button Generator — colors, padding, radius, border, hover state
- CSS Loader Generator — size, thickness, color, speed
- CSS Animation Generator — 8 presets, duration, easing, delay, iteration
- CSS Transition Generator — property, duration, easing