Cutship
Sign inGet started
← All edits
cutship.ai

Component · Text/Hooks · 9:16

Chrome Logo Spin

by CutshipVerified

Your logo as a solid chrome badge turning slowly in 3D: real thickness from stacked layers, a polished sky-and-horizon reflection, a sheen that sweeps the face and a soft floor shadow. Loops seamlessly. Drop in a transparent PNG, or type a name.

0 taken · 3 views

Included with Pro

Sign up free to Make this

Sign up free to unlock the spec, agent prompt and Make this.

components/remotion/chrome-logo-spin/component.tsx

import React from "react";
import { AbsoluteFill, Img, staticFile, useCurrentFrame, useVideoConfig } from "remotion";
import { loadFont } from "@remotion/google-fonts/Unbounded";
import type { ChromeLogoSpinProps } from "./schema";

const { fontFamily } = loadFont("normal", { weights: ["800"], subsets: ["latin"] });

const resolve = (src: string) => (/^(https?:|data:|\/)/.test(src) ? src : staticFile(src));

const FINISH: Record<ChromeLogoSpinProps["finish"], { face: string; side: (i: number) => string }> = {
  chrome: {
    face: "linear-gradient(180deg, #93a9c6 0%, #cfdcee 16%, #f6f9fd 32%, #b9c4d3 45%, #1b2028 49.5%, #3a2f27 53%, #8b7865 61%, #dacdbb 73%, #fcf7ef 85%, #a3937f 100%)",
    side: (i) => `hsl(220 9% ${44 - i * 1.3}%)`,
  },
  gold: {
    face: "linear-gradient(180deg, #fff3c4 0%, #f7d77a 18%, #fff8e1 32%, #d9a441 45%, #4a2e0b 49.5%, #6b4512 53%, #b98532 62%, #f3d27f 74%, #fff6d6 86%, #b88a3a 100%)",
    side: (i) => `hsl(38 55% ${36 - i * 1.1}%)`,
  },
  "black chrome": {
    face: "linear-gradient(180deg, #5d6470 0%, #9aa3b1 16%, #d7dde6 30%, #59606b 44%, #050608 49.5%, #121418 54%, #3c424b 64%, #8c95a3 76%, #c4ccd7 86%, #3a3f47 100%)",
    side: (i) => `hsl(220 8% ${20 - i * 0.5}%)`,
  },
};

export const ChromeLogoSpin: React.FC<ChromeLogoSpinProps> = ({
  logo,
  text,
  tagline,
  background,
  spotlight,
  finish,
  depth,
  turns,
  tilt,
  size,
  brandKit,
}) => {
  const frame = useCurrentFrame();
  const { durationInFrames, width } = useVideoConfig();
  const image = brandKit?.logo || logo;
  const bg = brandKit?.colors?.[1] ?? background;
  const metal = FINISH[finish];
  const angle = (frame / durationInFrames) * 360 * turns;
  // The sheen crosses the face once per turn, while it faces the camera.
  const facing = ((angle % 360) + 360) % 360;
  const sheenPos = facing < 70 ? 130 - (facing / 70) * 160 : facing > 300 ? 130 : -30;
  // The shadow narrows when the badge is edge-on.
  const edgeOn = Math.abs(Math.cos((angle * Math.PI) / 180));
  const w = width * size;
  const layerStep = (w / 500) * 1.6;

  const shape: React.CSSProperties = image
    ? {
        position: "absolute",
        inset: 0,
        WebkitMaskImage: `url("${resolve(image)}")`,
        maskImage: `url("${resolve(image)}")`,
        WebkitMaskSize: "contain",
        maskSize: "contain",
        WebkitMaskRepeat: "no-repeat",
        maskRepeat: "no-repeat",
        WebkitMaskPosition: "center",
        maskPosition: "center",
      }
    : { position: "absolute", inset: 0, display: "grid", placeItems: "center" };

  // A plain function (not a component), so layers update in place each frame instead of remounting.
  const layer = ({ key, fill, z, rotate = 0, sheen = false, solid = false }: { key: string; fill: string; z: number; rotate?: number; sheen?: boolean; solid?: boolean }) =>
    image ? (
      <div key={key} style={{ ...shape, backfaceVisibility: solid ? "visible" : "hidden", background: fill, transform: `translateZ(${z}px) rotateY(${rotate}deg)`, backgroundSize: sheen ? "300% 100%" : undefined, backgroundPosition: sheen ? `${sheenPos}% 0` : undefined }} />
    ) : (
      <div key={key} style={{ ...shape, backfaceVisibility: solid ? "visible" : "hidden", transform: `translateZ(${z}px) rotateY(${rotate}deg)` }}>
        <span
          style={{
            fontFamily: brandKit?.fonts?.[0] ?? fontFamily,
            fontWeight: 800,
            fontSize: w / Math.max(3.4, text.length * 0.82),
            lineHeight: 1,
            whiteSpace: "nowrap",
            background: fill,
            backgroundSize: sheen ? "300% 100%" : undefined,
            backgroundPosition: sheen ? `${sheenPos}% 0` : undefined,
            WebkitBackgroundClip: "text",
            backgroundClip: "text",
            color: "transparent",
          }}
        >
          {text}
        </span>
      </div>
    );

  return (
    <AbsoluteFill style={{ background: bg, alignItems: "center", justifyContent: "center" }}>
      <AbsoluteFill style={{ background: `radial-gradient(ellipse 60% 38% at 50% 48%, rgba(255,255,255,${0.16 * spotlight}), transparent 70%)` }} />
      {/* Loads the logo before the first frame renders (the mask itself doesn't wait). */}
      {image ? <Img src={resolve(image)} style={{ position: "absolute", width: 1, height: 1, opacity: 0 }} /> : null}
      <div style={{ perspective: w * 3.2 }}>
        <div style={{ position: "relative", width: w, height: image ? w * 0.55 : w * 0.4, transformStyle: "preserve-3d", transform: `rotateX(${tilt}deg) rotateY(${angle}deg)` }}>
          {Array.from({ length: depth }, (_, i) => (
            layer({ key: `side-${i}`, fill: metal.side(i), z: -(i + 1) * layerStep, solid: true })
          ))}
          {layer({ key: "face", fill: metal.face, z: 0.5 })}
          {layer({ key: "sheen", fill: "linear-gradient(100deg, transparent 35%, rgba(255,255,255,0.85) 46%, rgba(200,222,255,0.55) 50%, transparent 62%)", z: 1, sheen: true })}
          {layer({ key: "back", fill: metal.face, z: -(depth + 1) * layerStep, rotate: 180 })}
        </div>
      </div>
      <div
        style={{
          position: "absolute",
          top: `calc(50% + ${w * 0.36}px)`,
          width: w * 0.85 * (0.4 + 0.6 * edgeOn),
          height: w * 0.05,
          borderRadius: "50%",
          background: "radial-gradient(closest-side, rgba(0,0,0,0.55), transparent)",
          filter: `blur(${w * 0.012}px)`,
        }}
      />
      {tagline ? (
        <div
          style={{
            position: "absolute",
            top: `calc(50% + ${w * 0.48}px)`,
            fontFamily: brandKit?.fonts?.[1] ?? fontFamily,
            fontSize: w * 0.045,
            letterSpacing: "0.22em",
            textTransform: "uppercase",
            color: "rgba(255,255,255,0.7)",
          }}
        >
          {tagline}
        </div>
      ) : null}
    </AbsoluteFill>
  );
};

Remotion code you can paste anywhere, or install it: npx cutship add chrome-logo-spin

MIT License: use it in any video, personal or commercial. License

More from Cutship

Creator page →