# Colored smoke

> Soft clouds of color swirl and swell slowly, like ink spreading in water or smoke on a stage.

- Category: [Backgrounds](https://library.aimran.es/components/patterns)
- Built with: HTML + CSS
- Live editor: https://library.aimran.es/blocks/pt-smoke
- Library: AIMRAN Library (https://library.aimran.es), free, no sign-up, by Aimran Oukham

## Where to use it

Colored smoke has a moody, atmospheric feel that works for the hero of a perfume brand, a cocktail bar’s website or the teaser page of a new album. Seven blurred clouds rotate and swell at different speeds, so the mix of colors never repeats in an obvious way. An animated smoke background in pure CSS.

It shines on a dark background with two or three saturated colors; on white it loses most of its glow. If text goes on top, a slightly lower opacity keeps the clouds from swallowing thin letters.

## Code

### HTML

```html
<div class="pt-smoke"><i style="--cc:var(--c1);--x:-20.0%;--y:34.5%;--ox:89.6%;--oy:41.7%;--t:20.6s"></i><i style="--cc:var(--c2);--x:16.1%;--y:-11.6%;--ox:84.4%;--oy:86.7%;--t:29.0s"></i><i style="--cc:var(--c3);--x:4.9%;--y:2.5%;--ox:87.5%;--oy:42.5%;--t:26.5s"></i><i style="--cc:var(--c1);--x:56.8%;--y:3.7%;--ox:60.6%;--oy:44.4%;--t:24.6s"></i><i style="--cc:var(--c2);--x:24.3%;--y:6.2%;--ox:89.8%;--oy:52.7%;--t:31.6s"></i><i style="--cc:var(--c3);--x:42.2%;--y:-14.4%;--ox:32.7%;--oy:56.5%;--t:22.5s"></i><i style="--cc:var(--c1);--x:-13.5%;--y:4.4%;--ox:45.8%;--oy:30.6%;--t:27.3s"></i></div>
```

### CSS

```css
.pt-smoke {
  --c1: #0071e3;
  --c2: #8b5cf6;
  --c3: #14b8a6;
  --k: 1;
  /* velocidad */
  --d: 1;
  /* densidad / escala */
  --o: 1;
  /* opacidad */
  --bg: #05060a;
  --fg: #ffffff;
  --blend: screen;
  min-height: 100vh;
}

.pt-smoke {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
  background-color: var(--bg);
  container-type: size;
  isolation: isolate;
}

.pt-smoke>* {
  opacity: var(--o);
}

.pt-smoke i {
  position: absolute;
  left: var(--x);
  top: var(--y);
  width: calc(70% * var(--d));
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(circle,color-mix(in srgb,var(--cc) 75%,transparent),transparent 65%);
  filter: blur(50px);
  mix-blend-mode: var(--blend,screen);
  transform-origin: var(--ox) var(--oy);
  will-change: transform;
  animation: pt-smoke-r calc(var(--t) / var(--k)) linear infinite;
}

.pt-smoke i:nth-child(even) {
  animation-direction: reverse;
}

@keyframes pt-smoke-r {
  0% {
    transform: rotate(0) scale(1);
  }
  50% {
    transform: rotate(180deg) scale(1.35);
  }
  100% {
    transform: rotate(360deg) scale(1);
  }
}
```

### React

```tsx
// @ts-nocheck
import { useEffect, useRef } from "react";

const css = `
.pt-smoke {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
  background-color: var(--bg);
  container-type: size;
  isolation: isolate;
}

.pt-smoke>* {
  opacity: var(--o);
}

.pt-smoke i {
  position: absolute;
  left: var(--x);
  top: var(--y);
  width: calc(70% * var(--d));
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(circle,color-mix(in srgb,var(--cc) 75%,transparent),transparent 65%);
  filter: blur(50px);
  mix-blend-mode: var(--blend,screen);
  transform-origin: var(--ox) var(--oy);
  will-change: transform;
  animation: pt-smoke-r calc(var(--t) / var(--k)) linear infinite;
}

.pt-smoke i:nth-child(even) {
  animation-direction: reverse;
}

@keyframes pt-smoke-r {
  0% {
    transform: rotate(0) scale(1);
  }
  50% {
    transform: rotate(180deg) scale(1.35);
  }
  100% {
    transform: rotate(360deg) scale(1);
  }
}

`;

export default function PatternSmoke() {
  const ref = useRef(null);
  return (
    <>
      <style>{css}</style>
      <div
        ref={ref}
        className="pt-smoke"
        style={{
          "--c1": "#0071e3",
          "--c2": "#8b5cf6",
          "--c3": "#14b8a6",
          "--k": 1,
          "--d": 1,
          "--o": 1,
          "--bg": "#05060a",
          "--fg": "#ffffff",
          "--blend": "screen",
          minHeight: "100vh",
        }}
      >
        <i style={{ "--cc": "var(--c1)", "--x": "-20.0%", "--y": "34.5%", "--ox": "89.6%", "--oy": "41.7%", "--t": "20.6s" } as CSSProperties}></i><i style={{ "--cc": "var(--c2)", "--x": "16.1%", "--y": "-11.6%", "--ox": "84.4%", "--oy": "86.7%", "--t": "29.0s" } as CSSProperties}></i><i style={{ "--cc": "var(--c3)", "--x": "4.9%", "--y": "2.5%", "--ox": "87.5%", "--oy": "42.5%", "--t": "26.5s" } as CSSProperties}></i><i style={{ "--cc": "var(--c1)", "--x": "56.8%", "--y": "3.7%", "--ox": "60.6%", "--oy": "44.4%", "--t": "24.6s" } as CSSProperties}></i><i style={{ "--cc": "var(--c2)", "--x": "24.3%", "--y": "6.2%", "--ox": "89.8%", "--oy": "52.7%", "--t": "31.6s" } as CSSProperties}></i><i style={{ "--cc": "var(--c3)", "--x": "42.2%", "--y": "-14.4%", "--ox": "32.7%", "--oy": "56.5%", "--t": "22.5s" } as CSSProperties}></i><i style={{ "--cc": "var(--c1)", "--x": "-13.5%", "--y": "4.4%", "--ox": "45.8%", "--oy": "30.6%", "--t": "27.3s" } as CSSProperties}></i>
      </div>
    </>
  );
}
```

## Prompt for AI assistants

Paste this into ChatGPT, Claude, Cursor, v0 or Lovable to adapt the block to your stack (Tailwind, Vue, Svelte…):

````text
I want to add the “Colored smoke” block (Backgrounds) from AIMRAN Library to my project.

## What it is
Soft clouds of color swirl and swell slowly, like ink spreading in water or smoke on a stage.

## Chosen settings
- Color 1: #0071e3
- Color 2: #8b5cf6
- Color 3: #14b8a6
- Speed: 1x (from 0.2 to 3x)
- Density / scale: 1x (from 0.5 to 2x)
- Opacity: 1 (from 0.2 to 1)

## What I need
1. Add it to my project with the same look and animation as the reference code: same sizes, colours, radii, shadows, timings and easing.
2. It is built with plain HTML and CSS (the reference wraps it in a React component with its CSS). If my project uses something else (Vue, Svelte, Astro, plain HTML…), translate it without losing any behaviour. If I use Tailwind, turn the styles into classes; if not, keep the CSS in its own file.
3. Expose the settings above as props (or CSS variables) with those values as defaults.
4. Make it work well on phones: nothing that depends only on hover, touch targets of at least 44 px and no overflow on 320 px screens.
5. Make it look right in light and dark mode.
6. Keep it accessible: semantic HTML, roles and aria-* where needed, visible focus and keyboard support.
7. Respect prefers-reduced-motion: with reduced motion, no big animations but the same end result.

## Reference code
```tsx
// @ts-nocheck
import { useEffect, useRef } from "react";

const css = `
.pt-smoke {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
  background-color: var(--bg);
  container-type: size;
  isolation: isolate;
}

.pt-smoke>* {
  opacity: var(--o);
}

.pt-smoke i {
  position: absolute;
  left: var(--x);
  top: var(--y);
  width: calc(70% * var(--d));
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(circle,color-mix(in srgb,var(--cc) 75%,transparent),transparent 65%);
  filter: blur(50px);
  mix-blend-mode: var(--blend,screen);
  transform-origin: var(--ox) var(--oy);
  will-change: transform;
  animation: pt-smoke-r calc(var(--t) / var(--k)) linear infinite;
}

.pt-smoke i:nth-child(even) {
  animation-direction: reverse;
}

@keyframes pt-smoke-r {
  0% {
    transform: rotate(0) scale(1);
  }
  50% {
    transform: rotate(180deg) scale(1.35);
  }
  100% {
    transform: rotate(360deg) scale(1);
  }
}

`;

export default function PatternSmoke() {
  const ref = useRef(null);
  return (
    <>
      <style>{css}</style>
      <div
        ref={ref}
        className="pt-smoke"
        style={{
          "--c1": "#0071e3",
          "--c2": "#8b5cf6",
          "--c3": "#14b8a6",
          "--k": 1,
          "--d": 1,
          "--o": 1,
          "--bg": "#05060a",
          "--fg": "#ffffff",
          "--blend": "screen",
          minHeight: "100vh",
        }}
      >
        <i style={{ "--cc": "var(--c1)", "--x": "-20.0%", "--y": "34.5%", "--ox": "89.6%", "--oy": "41.7%", "--t": "20.6s" } as CSSProperties}></i><i style={{ "--cc": "var(--c2)", "--x": "16.1%", "--y": "-11.6%", "--ox": "84.4%", "--oy": "86.7%", "--t": "29.0s" } as CSSProperties}></i><i style={{ "--cc": "var(--c3)", "--x": "4.9%", "--y": "2.5%", "--ox": "87.5%", "--oy": "42.5%", "--t": "26.5s" } as CSSProperties}></i><i style={{ "--cc": "var(--c1)", "--x": "56.8%", "--y": "3.7%", "--ox": "60.6%", "--oy": "44.4%", "--t": "24.6s" } as CSSProperties}></i><i style={{ "--cc": "var(--c2)", "--x": "24.3%", "--y": "6.2%", "--ox": "89.8%", "--oy": "52.7%", "--t": "31.6s" } as CSSProperties}></i><i style={{ "--cc": "var(--c3)", "--x": "42.2%", "--y": "-14.4%", "--ox": "32.7%", "--oy": "56.5%", "--t": "22.5s" } as CSSProperties}></i><i style={{ "--cc": "var(--c1)", "--x": "-13.5%", "--y": "4.4%", "--ox": "45.8%", "--oy": "30.6%", "--t": "27.3s" } as CSSProperties}></i>
      </div>
    </>
  );
}
```

Give me the complete final code, ready to paste, and tell me in one line where to put it in my project.
````
