Bars Loader
A simple animated loader made with vertical bars that rise and fall in sequence. It uses only HTML and CSS with no JavaScript required.
<div class="bars-loader" aria-label="Loading">
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
</div>
.bars-loader{
display:flex;
align-items:center;
gap:6px;
height:50px;
}
.bars-loader span{
width:7px;
height:18px;
border-radius:4px;
background:#22d3ee;
animation:barsWave 1s ease-in-out infinite;
}
.bars-loader span:nth-child(2){
animation-delay:.1s;
}
.bars-loader span:nth-child(3){
animation-delay:.2s;
}
.bars-loader span:nth-child(4){
animation-delay:.3s;
}
.bars-loader span:nth-child(5){
animation-delay:.4s;
}
@keyframes barsWave{
0%,100%{
height:18px;
opacity:.45;
}
50%{
height:46px;
opacity:1;
}
}
How This Bars Loader Works
The Bars Loader is a CSS-only loading indicator made from one parent <div> and five empty <span> elements. Each span becomes a vertical bar, and the bars animate at slightly different times to create a repeating wave effect. There is no JavaScript in this component, so the loader runs entirely through CSS.
The .bars-loader container uses display: flex, which places all five bars in a horizontal row. The bars are vertically centered with align-items: center, so their height changes expand equally around the middle of the 50px-high container instead of appearing anchored only to the top or bottom.
A gap of 6px creates consistent spacing between the bars. This keeps the animation easy to read while maintaining a compact overall loader size.
Each .bars-loader span is 7px wide and starts at 18px high. A border-radius of 4px rounds the ends slightly, giving each bar a softer shape rather than a sharp rectangular appearance. The bars use cyan #22d3ee as their background color.
The animation is defined with the barsWave keyframes. It lasts 1s, uses an ease-in-out timing function, and repeats infinitely. The timing function makes the bars accelerate and decelerate as their height changes instead of moving at a constant rate.
At both 0% and 100%, every bar is 18px high with an opacity of .45. At the midpoint, or 50%, the bar grows to 46px high and becomes fully opaque with opacity: 1.
Because the parent uses centered flex alignment, the height increase happens around the vertical center. This gives the impression that each bar stretches upward and downward as it reaches its maximum size.
The wave effect comes from the staggered animation delays applied through :nth-child(). The first bar starts without an additional delay. The second begins after .1s, the third after .2s, the fourth after .3s, and the fifth after .4s.
These small timing differences mean the bars do not all reach their 46px maximum height at the same moment. Instead, the active state passes across the row from the first bar to the fifth, producing the visual wave.
The loader combines both height and opacity changes in the same keyframe animation. When a bar is short, it is also partially faded. When it reaches maximum height, it becomes fully visible. This makes the currently active part of the wave stand out more clearly.
For more information about staggering animations with delays, see the MDN animation-delay documentation.
The parent element also includes aria-label="Loading". This gives the visual loader a short accessible description even though there is no visible loading text.
Customizing the Bars Loader
The component can be adjusted easily because its appearance and movement are controlled by a small set of CSS values.
- Change the
6pxgap to increase or reduce the spacing between the five bars. - Adjust the
7pxwidth to make each bar thinner or thicker. - Change the starting height from
18pxto alter the loader’s resting appearance. - Modify the maximum
46pxheight in the keyframes to make the wave more or less pronounced. - Replace
#22d3eewith another color that matches your interface. - Adjust the
4pxborder radius to make the bars more rectangular or more rounded. - Change the
1sanimation duration to make the wave move faster or slower. - Edit the
.1sdelay increments to change how quickly the animated state travels between bars.
Where to Use the Bars Loader
This loader works well for interfaces that need a compact indication of ongoing activity without showing an exact progress percentage.
- Form submission states while a request is being processed.
- Dashboard cards waiting for data to load.
- Audio or media interfaces where a bar-based animation fits the visual style.
- Modal windows displaying asynchronous content.
- Small loading areas inside cards, panels, or widgets.
- Full-page loaders that need a simple centered activity indicator.
If you prefer a loader based on horizontal movement instead of vertical bars, the Progress Bar Loader is another related CodeRipple component to consider. The Bars Loader is particularly useful when you want an indefinite loading state with minimal markup and no JavaScript.
Frequently Asked Questions
Does the Bars Loader use JavaScript?
No. The component contains no JavaScript. Its complete wave effect is created with CSS keyframes, flexbox, opacity changes, and staggered animation delays.
How does the wave effect move from one bar to the next?
Each bar uses the same animation, but the second through fifth bars have progressively larger delays from .1s to .4s. This causes them to reach their maximum height at different times.
Why is the loader container 50px high?
The bars grow to a maximum height of 46px. A 50px container provides enough vertical space for that animation while keeping the bars centered.
Can I add more than five bars?
Yes, but the existing CSS only defines staggered delays for five spans. Additional bars would need their own delay rules if you want the same evenly spaced wave sequence.
The Bars Loader uses five simple elements, one shared keyframe animation, and staggered delays to create a lightweight wave-style loading indicator with no scripting required.
