# Venetian blinds toggle

> The slats of a window blind tilt one after another and let the sun into the room in bands of light.

- Category: [Toggles](https://library.aimran.es/components/toggles)
- Built with: HTML + CSS
- Live editor: https://library.aimran.es/blocks/uv-tg-blinds
- Library: AIMRAN Library (https://library.aimran.es), free, no sign-up, by Aimran Oukham

## Where to use it

This switch is a small window with venetian blinds closed over a view of sky, sun and a green hill. Turning it on tilts each slat in turn with a short delay, so the light opens from top to bottom, the tilt rod twists and a warm glow spreads around the frame. The slats use rotateX in CSS. It fits smart home lighting and daylight settings.

The main color is the sky and the second one is the sun. A pale dawn sky with an orange sun gives a morning look, and a darker blue suits evening modes. Keep the label about light or shade.

## Code

### HTML

```html
<label class="uvq03-bln"><input type="checkbox" role="switch"><span class="wn"><span class="vw"><i class="sn"></i><i class="hl"></i></span><span class="sl"><i style="--i:0"></i><i style="--i:1"></i><i style="--i:2"></i><i style="--i:3"></i><i style="--i:4"></i><i style="--i:5"></i><i style="--i:6"></i><i style="--i:7"></i></span><i class="rd"></i><i class="rs"></i></span>Natural light</label>
```

### CSS

```css
.uvq03-bln {
  --c1: #7cc4f0;
  --c2: #ffcf4a;
  --s: 16px;
  /* tamaño */
  --k: 1;
  /* velocidad */
  --fg: #1d1d1f;
  /* texto */
  --bg: #f5f5f7;
  /* fondo */
}

.uvq03-bln {
  font-family: -apple-system,BlinkMacSystemFont,"SF Pro Text","Inter",system-ui,sans-serif;
  font-size: var(--s);
  color: var(--fg);
  -webkit-tap-highlight-color: transparent;
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: .8em;
  cursor: pointer;
  user-select: none;
  font-weight: 550;
}

.uvq03-bln input {
  position: absolute;
  opacity: 0;
  width: 1px;
  height: 1px;
  margin: 0;
  pointer-events: none;
}

.uvq03-bln .wn {
  position: relative;
  display: block;
  flex: none;
  box-sizing: border-box;
  width: 4em;
  height: 4em;
  padding: .22em;
  border-radius: .3em;
  background: linear-gradient(180deg,#fbfaf7,#dedad1);
  box-shadow: inset 0 0 0 1px rgba(0,0,0,.08),0 .5em 1em -.5em rgba(0,0,0,.45);
}

.uvq03-bln .vw {
  position: relative;
  display: block;
  height: 100%;
  overflow: hidden;
  border-radius: .12em;
  background: linear-gradient(180deg,var(--c1),color-mix(in srgb,var(--c1) 35%,#fff));
}

.uvq03-bln .vw i {
  position: absolute;
  display: block;
}

.uvq03-bln .sn {
  right: .45em;
  top: .4em;
  width: .9em;
  height: .9em;
  border-radius: 50%;
  background: var(--c2);
  box-shadow: 0 0 .8em .2em color-mix(in srgb,var(--c2) 70%,transparent);
}

.uvq03-bln .hl {
  left: -20%;
  right: -20%;
  bottom: -1.1em;
  height: 2em;
  border-radius: 50%;
  background: linear-gradient(180deg,#7fc96b,#4e9a43);
}

.uvq03-bln .sl {
  position: absolute;
  inset: .22em;
  display: grid;
  grid-template-rows: repeat(8,1fr);
  perspective: 12em;
}

.uvq03-bln .sl i {
  display: block;
  margin: -.03em 0;
  border-radius: .06em;
  background: linear-gradient(180deg,#f7f4ee,#d8d2c6 70%,#c4bdaf);
  box-shadow: 0 .04em .05em rgba(0,0,0,.25);
  transition: transform calc(0.5s / var(--k)) cubic-bezier(.22,1,.36,1);
  transition-delay: calc((7 - var(--i)) * calc(0.04s / var(--k)));
}

.uvq03-bln .rd {
  position: absolute;
  left: .4em;
  top: .22em;
  width: .06em;
  height: 2.9em;
  background: #a9a293;
  transition: transform calc(0.5s / var(--k)) cubic-bezier(.25,.1,.25,1);
}

.uvq03-bln .rs {
  position: absolute;
  left: 0;
  right: 0;
  bottom: -.18em;
  height: .26em;
  border-radius: .08em;
  background: linear-gradient(180deg,#f4f1ea,#cfc9bd);
}

.uvq03-bln:hover input:not(:checked) + .wn .sl i {
  transform: rotateX(18deg);
}

.uvq03-bln:active .wn {
  scale: .97;
}

.uvq03-bln input:checked + .wn .sl i {
  transform: rotateX(78deg);
  transition-delay: calc(var(--i) * calc(0.04s / var(--k)));
}

.uvq03-bln input:checked + .wn .rd {
  transform: rotate(14deg);
}

.uvq03-bln input:checked + .wn {
  box-shadow: inset 0 0 0 1px rgba(0,0,0,.08),0 .5em 1em -.5em rgba(0,0,0,.45),0 0 1.6em -.3em color-mix(in srgb,var(--c2) 55%,transparent);
}

.uvq03-bln input:focus-visible + .wn {
  outline: 2px solid var(--c1);
  outline-offset: 3px;
}

@media (prefers-reduced-motion:reduce) {
  .uvq03-bln,.uvq03-bln *,.uvq03-bln *::before,.uvq03-bln *::after {
    animation-duration: .01ms!important;
    animation-iteration-count: 1!important;
    transition-duration: .01ms!important;
  }
}
```

### React

```tsx
import type { CSSProperties } from "react";

const css = `
.uvq03-bln {
  font-family: -apple-system,BlinkMacSystemFont,"SF Pro Text","Inter",system-ui,sans-serif;
  font-size: var(--s);
  color: var(--fg);
  -webkit-tap-highlight-color: transparent;
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: .8em;
  cursor: pointer;
  user-select: none;
  font-weight: 550;
}

.uvq03-bln input {
  position: absolute;
  opacity: 0;
  width: 1px;
  height: 1px;
  margin: 0;
  pointer-events: none;
}

.uvq03-bln .wn {
  position: relative;
  display: block;
  flex: none;
  box-sizing: border-box;
  width: 4em;
  height: 4em;
  padding: .22em;
  border-radius: .3em;
  background: linear-gradient(180deg,#fbfaf7,#dedad1);
  box-shadow: inset 0 0 0 1px rgba(0,0,0,.08),0 .5em 1em -.5em rgba(0,0,0,.45);
}

.uvq03-bln .vw {
  position: relative;
  display: block;
  height: 100%;
  overflow: hidden;
  border-radius: .12em;
  background: linear-gradient(180deg,var(--c1),color-mix(in srgb,var(--c1) 35%,#fff));
}

.uvq03-bln .vw i {
  position: absolute;
  display: block;
}

.uvq03-bln .sn {
  right: .45em;
  top: .4em;
  width: .9em;
  height: .9em;
  border-radius: 50%;
  background: var(--c2);
  box-shadow: 0 0 .8em .2em color-mix(in srgb,var(--c2) 70%,transparent);
}

.uvq03-bln .hl {
  left: -20%;
  right: -20%;
  bottom: -1.1em;
  height: 2em;
  border-radius: 50%;
  background: linear-gradient(180deg,#7fc96b,#4e9a43);
}

.uvq03-bln .sl {
  position: absolute;
  inset: .22em;
  display: grid;
  grid-template-rows: repeat(8,1fr);
  perspective: 12em;
}

.uvq03-bln .sl i {
  display: block;
  margin: -.03em 0;
  border-radius: .06em;
  background: linear-gradient(180deg,#f7f4ee,#d8d2c6 70%,#c4bdaf);
  box-shadow: 0 .04em .05em rgba(0,0,0,.25);
  transition: transform calc(0.5s / var(--k)) cubic-bezier(.22,1,.36,1);
  transition-delay: calc((7 - var(--i)) * calc(0.04s / var(--k)));
}

.uvq03-bln .rd {
  position: absolute;
  left: .4em;
  top: .22em;
  width: .06em;
  height: 2.9em;
  background: #a9a293;
  transition: transform calc(0.5s / var(--k)) cubic-bezier(.25,.1,.25,1);
}

.uvq03-bln .rs {
  position: absolute;
  left: 0;
  right: 0;
  bottom: -.18em;
  height: .26em;
  border-radius: .08em;
  background: linear-gradient(180deg,#f4f1ea,#cfc9bd);
}

.uvq03-bln:hover input:not(:checked) + .wn .sl i {
  transform: rotateX(18deg);
}

.uvq03-bln:active .wn {
  scale: .97;
}

.uvq03-bln input:checked + .wn .sl i {
  transform: rotateX(78deg);
  transition-delay: calc(var(--i) * calc(0.04s / var(--k)));
}

.uvq03-bln input:checked + .wn .rd {
  transform: rotate(14deg);
}

.uvq03-bln input:checked + .wn {
  box-shadow: inset 0 0 0 1px rgba(0,0,0,.08),0 .5em 1em -.5em rgba(0,0,0,.45),0 0 1.6em -.3em color-mix(in srgb,var(--c2) 55%,transparent);
}

.uvq03-bln input:focus-visible + .wn {
  outline: 2px solid var(--c1);
  outline-offset: 3px;
}

@media (prefers-reduced-motion:reduce) {
  .uvq03-bln,.uvq03-bln *,.uvq03-bln *::before,.uvq03-bln *::after {
    animation-duration: .01ms!important;
    animation-iteration-count: 1!important;
    transition-duration: .01ms!important;
  }
}
`;

export default function TgBlinds() {
  return (
    <>
      <style>{css}</style>
      <div
        style={{
          "--c1": "#7cc4f0",
          "--c2": "#ffcf4a",
          "--s": "16px",
          "--k": "1",
          "--fg": "#1d1d1f",
          "--bg": "#f5f5f7",
        } as CSSProperties}
      >
        <label className="uvq03-bln"><input type="checkbox" role="switch" /><span className="wn"><span className="vw"><i className="sn"></i><i className="hl"></i></span><span className="sl"><i style={{ "--i": "0" } as CSSProperties}></i><i style={{ "--i": "1" } as CSSProperties}></i><i style={{ "--i": "2" } as CSSProperties}></i><i style={{ "--i": "3" } as CSSProperties}></i><i style={{ "--i": "4" } as CSSProperties}></i><i style={{ "--i": "5" } as CSSProperties}></i><i style={{ "--i": "6" } as CSSProperties}></i><i style={{ "--i": "7" } as CSSProperties}></i></span><i className="rd"></i><i className="rs"></i></span>Natural light</label>
      </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 “Venetian blinds toggle” block (Toggles) from AIMRAN Library to my project.

## What it is
The slats of a window blind tilt one after another and let the sun into the room in bands of light.

## Chosen settings
- Main color: #7cc4f0
- Secondary color: #ffcf4a
- Size: 16px (from 12 to 24px)
- Speed: 1x (from 0.5 to 2x)
- Text: "Luz natural"

## 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
import type { CSSProperties } from "react";

const css = `
.uvq03-bln {
  font-family: -apple-system,BlinkMacSystemFont,"SF Pro Text","Inter",system-ui,sans-serif;
  font-size: var(--s);
  color: var(--fg);
  -webkit-tap-highlight-color: transparent;
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: .8em;
  cursor: pointer;
  user-select: none;
  font-weight: 550;
}

.uvq03-bln input {
  position: absolute;
  opacity: 0;
  width: 1px;
  height: 1px;
  margin: 0;
  pointer-events: none;
}

.uvq03-bln .wn {
  position: relative;
  display: block;
  flex: none;
  box-sizing: border-box;
  width: 4em;
  height: 4em;
  padding: .22em;
  border-radius: .3em;
  background: linear-gradient(180deg,#fbfaf7,#dedad1);
  box-shadow: inset 0 0 0 1px rgba(0,0,0,.08),0 .5em 1em -.5em rgba(0,0,0,.45);
}

.uvq03-bln .vw {
  position: relative;
  display: block;
  height: 100%;
  overflow: hidden;
  border-radius: .12em;
  background: linear-gradient(180deg,var(--c1),color-mix(in srgb,var(--c1) 35%,#fff));
}

.uvq03-bln .vw i {
  position: absolute;
  display: block;
}

.uvq03-bln .sn {
  right: .45em;
  top: .4em;
  width: .9em;
  height: .9em;
  border-radius: 50%;
  background: var(--c2);
  box-shadow: 0 0 .8em .2em color-mix(in srgb,var(--c2) 70%,transparent);
}

.uvq03-bln .hl {
  left: -20%;
  right: -20%;
  bottom: -1.1em;
  height: 2em;
  border-radius: 50%;
  background: linear-gradient(180deg,#7fc96b,#4e9a43);
}

.uvq03-bln .sl {
  position: absolute;
  inset: .22em;
  display: grid;
  grid-template-rows: repeat(8,1fr);
  perspective: 12em;
}

.uvq03-bln .sl i {
  display: block;
  margin: -.03em 0;
  border-radius: .06em;
  background: linear-gradient(180deg,#f7f4ee,#d8d2c6 70%,#c4bdaf);
  box-shadow: 0 .04em .05em rgba(0,0,0,.25);
  transition: transform calc(0.5s / var(--k)) cubic-bezier(.22,1,.36,1);
  transition-delay: calc((7 - var(--i)) * calc(0.04s / var(--k)));
}

.uvq03-bln .rd {
  position: absolute;
  left: .4em;
  top: .22em;
  width: .06em;
  height: 2.9em;
  background: #a9a293;
  transition: transform calc(0.5s / var(--k)) cubic-bezier(.25,.1,.25,1);
}

.uvq03-bln .rs {
  position: absolute;
  left: 0;
  right: 0;
  bottom: -.18em;
  height: .26em;
  border-radius: .08em;
  background: linear-gradient(180deg,#f4f1ea,#cfc9bd);
}

.uvq03-bln:hover input:not(:checked) + .wn .sl i {
  transform: rotateX(18deg);
}

.uvq03-bln:active .wn {
  scale: .97;
}

.uvq03-bln input:checked + .wn .sl i {
  transform: rotateX(78deg);
  transition-delay: calc(var(--i) * calc(0.04s / var(--k)));
}

.uvq03-bln input:checked + .wn .rd {
  transform: rotate(14deg);
}

.uvq03-bln input:checked + .wn {
  box-shadow: inset 0 0 0 1px rgba(0,0,0,.08),0 .5em 1em -.5em rgba(0,0,0,.45),0 0 1.6em -.3em color-mix(in srgb,var(--c2) 55%,transparent);
}

.uvq03-bln input:focus-visible + .wn {
  outline: 2px solid var(--c1);
  outline-offset: 3px;
}

@media (prefers-reduced-motion:reduce) {
  .uvq03-bln,.uvq03-bln *,.uvq03-bln *::before,.uvq03-bln *::after {
    animation-duration: .01ms!important;
    animation-iteration-count: 1!important;
    transition-duration: .01ms!important;
  }
}
`;

export default function TgBlinds() {
  return (
    <>
      <style>{css}</style>
      <div
        style={{
          "--c1": "#7cc4f0",
          "--c2": "#ffcf4a",
          "--s": "16px",
          "--k": "1",
          "--fg": "#1d1d1f",
          "--bg": "#f5f5f7",
        } as CSSProperties}
      >
        <label className="uvq03-bln"><input type="checkbox" role="switch" /><span className="wn"><span className="vw"><i className="sn"></i><i className="hl"></i></span><span className="sl"><i style={{ "--i": "0" } as CSSProperties}></i><i style={{ "--i": "1" } as CSSProperties}></i><i style={{ "--i": "2" } as CSSProperties}></i><i style={{ "--i": "3" } as CSSProperties}></i><i style={{ "--i": "4" } as CSSProperties}></i><i style={{ "--i": "5" } as CSSProperties}></i><i style={{ "--i": "6" } as CSSProperties}></i><i style={{ "--i": "7" } as CSSProperties}></i></span><i className="rd"></i><i className="rs"></i></span>Natural light</label>
      </div>
    </>
  );
}
```

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