Sliders are one of those UI components that look simple until you actually need to build one properly.
At first, it feels like just moving a few cards from left to right. Then you start dealing with touch gestures, drag behavior, loop boundaries, responsive layouts, slide sizes, progress indicators, accessibility, hydration, CDN usage, and the small visual glitches that only appear when real HTML and real CSS get involved.
That was the motivation behind BrickSlider.
I wanted a carousel engine that stays close to the DOM, gives developers control over the markup, and does not assume a specific framework or styling system.
The main idea
BrickSlider is built around a simple principle:
The library should control behavior, not own your design.
The slider expects a small set of structural classes, but the actual visual style belongs to the project using it.
That means you can use plain CSS, Tailwind utilities, scoped styles, CSS modules, or any styling approach you already have.
The markup remains readable:
<div id="slider">
<button class="bs-arrow bs-prev" type="button">Previous</button>
<button class="bs-arrow bs-next" type="button">Next</button>
<div class="bs-track">
<div class="bs-container">
<article class="bs-slide">Slide 01</article>
<article class="bs-slide">Slide 02</article>
<article class="bs-slide">Slide 03</article>
</div>
</div>
<ul class="bs-dots">
<li class="bs-dot"></li>
</ul>
</div>
And the JavaScript stays focused:
import { BrickSlider } from "@sixsrc/brick-slider"
import "@sixsrc/brick-slider-tailwind/brick-slider.css"
const slider = new BrickSlider("#slider", {
slidesPerView: 1,
slidesPerPage: 1,
gap: 16,
useLoop: false
})
slider.init()
For Tailwind projects, the recommended setup is to install the core package together with the Tailwind package:
npm install @sixsrc/brick-slider @sixsrc/brick-slider-tailwind tailwindcss
Then use the Tailwind package CSS as the structural layer:
import "@sixsrc/brick-slider-tailwind/brick-slider.css"
The core CSS is still available for non-Tailwind projects, but the main authoring experience is designed around Tailwind-friendly markup.
Framework-agnostic by default
I did not want BrickSlider to be tied to React, Vue, Svelte, or any specific rendering model.
A slider should work in static HTML, server-rendered pages, islands architecture, React/Vue/Astro apps, custom frameworks, and simple CDN-based pages.
The library only needs the DOM.
That makes the integration surface smaller and easier to reason about. If the markup exists, the slider can mount.
Tailwind-friendly, but not Tailwind-only
A big part of the design is making the markup comfortable for Tailwind users without making Tailwind a requirement.
For example, dots can be styled directly with utilities:
<ul class="bs-dots flex gap-2">
<li class="bs-dot h-2 w-8 rounded-full bg-slate-300"></li>
</ul>
Then the active state can be customized with CSS:
.bs-dot--active {
background: #6d28d9;
}
Or with Tailwind:
.bs-dot--active {
@apply bg-violet-700;
}
This keeps the library flexible: it provides the behavior and state classes, while the project defines the visual language.
Web Animations API instead of inline style hacks
Another important decision was using the Web Animations API for movement.
Instead of constantly mutating inline styles for every transition, BrickSlider uses WAAPI to control the animation layer more explicitly.
That makes the movement logic easier to isolate, cancel, restart, and coordinate with loop boundaries, touch gestures, and responsive recalculations.
The goal is not to hide everything behind CSS tricks, but to let the browser animation engine handle the motion while BrickSlider focuses on state, measurements, and navigation rules.
Modular features
One thing I wanted to avoid was shipping every possible feature as one big default experience.
BrickSlider is split into focused packages:
- core slider engine
- accessibility helpers
- story-style plugin
- Tailwind-oriented CSS/utilities
The core package handles the carousel behavior. Extra features can be added only when needed.
That keeps the mental model cleaner: if a project does not need story flows, it does not need to think about story flows.
Accessibility as a separate concern
Accessibility is important, but it also needs to be explicit.
The accessibility plugin adds helpers for keyboard navigation, focus behavior, and screen-reader-friendly interactions.
I like this separation because it makes the feature visible. You install it intentionally, configure it intentionally, and understand that it is part of the slider experience rather than hidden magic.
Story-style flows
The Stories plugin was one of the more interesting parts to build.
It adds an Instagram-like flow on top of the core slider, with progress indicators, media awareness, triggers, and full-screen behavior.
This is a different interaction model from a traditional carousel, so it made sense as a separate plugin instead of forcing those concepts into the core.
Stories are not just “slides with autoplay”. They have their own rules, timing, controls, and expectations.
The hard parts
The hardest parts were not the obvious ones.
The tricky bugs came from edge cases like loop boundaries, cloned slides, fast navigation, touch gestures near the first or last slide, responsive layouts with different slide widths, hydration timing, CDN builds, and CSS assumptions from user markup.
Those are the parts that make a slider feel either solid or fragile.
A lot of the work went into making the library behave consistently when real-world markup is not perfectly clean.
Developer experience
The DX goal is simple:
- readable markup
- predictable class names
- small setup
- real examples
- CDN support
- TypeScript types
- optional plugins
- styling that stays in your hands
I also wanted the docs to include examples that can be copied, inspected, and downloaded instead of only showing isolated snippets.
When I use a UI library, I usually want to see a working example first, then understand how it is built.
So the docs follow that direction.
Current status
BrickSlider is still evolving, but the foundation is already usable:
- core slider
- touch and drag
- arrows
- dots
- pages
- progress
- loop
- auto height
- responsive options
- custom slide sizes
- accessibility plugin
- stories plugin
- CDN examples
- downloadable examples
There is still plenty to improve, but it already reflects the direction I wanted: a slider engine that gives control back to the developer instead of hiding everything behind an opaque abstraction.
Links
If you want to take a look:
- Website: https://sixsrc.github.io/brickslider/
- Docs and demos: https://sixsrc.github.io/brickslider/docs/
- GitHub: https://github.com/sixsrc/brickslider
If the project looks useful, a GitHub star helps a lot.
Top comments (0)