Geometric Shapes
Animated background of pure CSS geometric shapes — triangles, hexagons, diamond squares and circles float and rotate slowly, randomly distributed by JS.
You'll get access to the interactive demo with a free account.
This effect is part of Effect.Labs — 811 vanilla effects, some free, some premium. Backgrounds has 50 effects, including 6 free. Explore the category →
3 usage examples



How it works
On load, a JS IIFE creates 15 <div> elements and injects them into the #geometricBg container. It picks from an array of 4 types: geo-triangle, geo-hexagon, geo-square, geo-circle. Each div receives random inline styles: position (left 0–90%, top 0–80%), animation-delay 0–15 s, animation-duration 10–20 s, and transform: scale() between 0.5 and 1.5. These inline values override the class CSS values, producing the variety of rhythms visible on screen. After init, JS stops — no RAF loop, zero ongoing CPU cost.
Animation is entirely driven by @keyframes geoFloat in pure CSS. The 4-step sequence combines translateY (0 → −30 px → −15 px → −40 px), cumulative rotation (0° → 90° → 180° → 270°), and a slight opacity breath (0.6 → 0.8 → 0.5 → 0.7). Because each shape has its own inline animation-duration, they naturally drift out of phase — none is synchronized with its neighbors.
All 4 shapes are 100% CSS, no SVG or canvas. The triangle uses the transparent-border trick: zero width and height, border-left/right: 25px solid transparent, border-bottom: 43px solid #6366f1. The hexagon is a 40 × 23 px rectangle with two half-hexagon caps via ::before / ::after (20 px side borders + 11 px end caps). The square is a 30 × 30 px div pre-rotated 45° in its CSS rule to form a diamond — the keyframe rotation then spins it further. The circle is a 35 × 35 px div with border-radius: 50%, transparent fill, and a colored border only.
Accessibility
- prefers-reduced-motion absent: the code contains no
@media (prefers-reduced-motion)query or JS check — shapes animate in all conditions. Recommended CSS addition:@media (prefers-reduced-motion: reduce) { .geo-shape { animation: none; } }. - No
aria-*attributes in the base HTML. If this background accompanies content, wrap it in adivwitharia-hidden="true"to hide it from screen readers. - Shapes are purely decorative — no text is associated with them, so no WCAG contrast requirement applies directly to their color.
- Zero mouse or keyboard interaction: no focus, no events, no tab trap. The effect does not interfere with the host page's keyboard navigation.
- The
.bg-label'Geometric' present in the demo HTML is decorative; remove it or mark itaria-hidden="true"in production.
Browser compatibility
Requires CSS animations and transform — universally supported since 2015. The init JS is ES5-compatible.
Without JS, the <code>#geometricBg</code> container stays empty but throws no errors — the dark background displays, overlay content remains readable. Without CSS animations, shapes appear frozen at their initial position.
The code
HTML structure to paste into your page (CSS + JS available with a premium account):
<div class="bg-geometric" id="geometricBg">
<!-- .geo-shape elements are injected by the script -->
<!-- Optional: overlay content -->
<div class="geo-overlay">
<h2>Your message</h2>
</div>
</div>
Full HTML + CSS + JS, copy-paste ready — with hundreds of premium effects.
Customize
Options passed to the API or data-* attributes:
| Option / property | Default | Effect |
|---|---|---|
| i < 15 (JS) | 15 | Number of injected shapes. Reduce to 6–8 for a minimal background, increase to 25–30 for maximum density. |
| .geo-shape { opacity } (CSS) | 0.6 | Global opacity for all shapes. 0.3 = very subtle, 0.85 = prominently visible. |
| .geo-triangle border-bottom (CSS) | #6366f1 | Triangle color (indigo). Change the value in border-bottom: 43px solid #6366f1. |
| .geo-hexagon background (CSS) | #d946ef | Hexagon color (fuchsia). Replace #d946ef in 3 places: main rule, ::before, and ::after. |
| .geo-square background (CSS) | #06b6d4 | Square/diamond color (cyan). One line to change. |
| .geo-circle border (CSS) | #8b5cf6 | Circle border color (violet). Circles have a transparent fill — only the border is colored. |
| @keyframes geoFloat translateY (CSS) | −30 px / −15 px / −40 px | Vertical float amplitude. Increase (e.g., −60 px) for more movement, decrease (e.g., −10 px) for a subtle effect. |
| (10 + Math.random() * 10) (JS) | 10–20 s | Animation duration range. E.g., (6 + Math.random() * 6) for 6–12 s (livelier animation). |
FAQ
Math.random() for position, delay, duration, and scale — the layout changes on every load. This is intentional: no fixed pattern, the animation feels organic. For a reproducible result, hardcode the inline styles on the shapes as in the demo HTML.id="geometricBg". For multiple instances, extract the logic into an initGeoShapes(containerId, count) function and call it with distinct ids for each container. CSS classes (prefix geo-) apply to all instances without conflict.transform and opacity are GPU-accelerated through the browser's compositing layer — they trigger no layout or paint. With 15 lightweight CSS divs (no images, no canvas), the performance impact is negligible even on low-end mobile devices.