---
title: SC Gradient Border
description: A customizable gradient border from CSS masks, with no extra DOM.
url: https://secretocho.design/lab/sc-gradient-border/
type: SoftwareSourceCode
status: working
published: 2025-09-01
updated: 2025-09-01
---

# SC Gradient Border

> A customizable gradient border from CSS masks, with no extra DOM.

component 07 / 28 · WORKING

- **type**: Code Component
- **platform**: Framer
- **last update**: 2025-09-01
- **license**: SecretoCho Design

![A still of the SC Gradient Border demo, as its module draws it with reduced motion.](https://secretocho.design/_astro/still.CzKOpcgS_2aKUFi.webp)

*fig 00 · live demo, ported from **SC\_GradientBorder.tsx***

Draw a performant, customizable gradient border using CSS masks—no extra DOM, SVG, or images.

A pure-CSS gradient border wrapper for Framer. Uses layered masks to “punch out” the center, leaving a crisp, GPU-friendly gradient ring around your content area. Fully configurable via color stops, angle, width, and radius.

- UI
- Decoration
- Effects

## Main

### Overview

- **Built With**: React, CSS (gradients + masks), Framer Code Component API
- **Layout Support**: Fully Responsive (fills parent)
- **Orientation**: N/A
- **Ideal Use Case**: Cards, avatars, badges, containers needing premium gradient accents

### Tags

- gradient
- border
- mask
- css
- ui

### Code comment

```tsx
/**
 * SC Gradient Border
 * © SecretoCho Design 2025 (https://secretocho.design)
 * Renders a configurable gradient border using CSS masks (no images/SVG).
 * Uses padding=borderWidth to create the ring; inner area stays clean for content.
 * @framerDisableUnlink
 * @framerIntrinsicWidth 200
 * @framerIntrinsicHeight 200
 */
```

### Dependencies

- **Technologies**: None (pure CSS + React)
- **Notes**: No external libs; relies on -webkit-mask-composite: xor + mask-composite: exclude layering.

### Complexity

- **Logic Level**: Low (map gradient stops → CSS string)
- **Runtime Cost**: Very Low (static styles; no loops/RAF)
- **Component Size**: ~1–2 KB TSX
- **Notes**: GPU-accelerated by browsers; no layout thrash when props change.

## Guide

### Instructions

1. Add to your Framer project and place on the canvas.
2. Set **Colors** (array of { color, position% }) to define the gradient.
3. Adjust **Angle** (0–360°), **Border Width** (px), and **Radius** (px).
4. Place content **inside** the component frame (the inner white panel).
5. For dark themes, change the inner panel color in code if needed.

### Examples / Presets

- Preset A (Subtle Duo)
  
  - **stops**: [{#ff00cc,0},{#3333ff,100}]
  - **angle**: 45
  - **width**: 4
  - **radius**: 12
  
- Preset B (Rainbow Ring)
  
  - **stops**: [red,orange,yellow,green,blue,indigo,violet @ spaced 0–100]
  - **angle**: 90
  - **width**: 6
  - **radius**: 20
  
- Preset C (Mono Glow)
  
  - **stops**: [{#0ea5e9,0},{#22d3ee,100}]
  - **angle**: 135
  - **width**: 2
  - **radius**: 8
  

## Mechanics

### How it Works

- **Gradient string** from stops\[\] → linear-gradient(angle, color position, …).
- Outer wrapper gets padding = borderWidth and the gradient **background**.
- Two **mask layers** (content-box + full box) with xor/exclude create a **hollow center**, so only the border area shows the gradient.
- Inner child fills remaining space as the actual **content surface**.

### Performance & Tuning

- Prefer **2–4** color stops for minimal paint; more is fine for hero elements.
- Gradients are cheap; large radii and wide borders are safe.
- Avoid animating borderRadius or borderWidth every frame; prefer discrete transitions.

### Compatibility & Limits

- Modern Chromium/WebKit support -webkit-mask-composite: xor; mask-composite: exclude used as a standard fallback.
- Firefox support for the exact composite semantics may vary; if you target older/strict Firefox environments, consider an SVG fallback.
- Inner panel is hardcoded to white; change to a tokenized var if theming is required.

## Quality

### Accessibility

- Decorative effect; set aria-hidden="true" on the wrapper if used purely as chrome.
- Ensure inner content maintains sufficient **contrast** against the inner panel color.

### Security & Privacy

- No network calls; no storage.
- No dangerouslySetInnerHTML / eval.
- No device permissions.
- Cleans up by default (no timers/listeners created).

## Reference

### Props

| name | type | default | description |
| --- | --- | --- | --- |
| stops | Array<{ color:string; position:number(0–100) }> | [{ "#ff00cc",0 }, { "#3333ff",100 }] | Gradient color stops with percentage positions. |
| angle | number(0–360) | 45 | Gradient angle in degrees. |
| borderWidth | number(px) | 4 | Thickness of the gradient ring (via wrapper padding). |
| borderRadius | number(px) | 12 | Corner rounding applied to outer and inner panels. |

### Notes & Tips

- position is in **%** (0–100); keep the first at 0 and last at 100 for clean edges.
- Use **small widths (2–6px)** for subtle UI; go larger for hero cards.
- For dark UIs, replace the inner panel background:"white" with your surface token.

### Troubleshooting / FAQ

Gradient doesn’t show

Ensure stops has ≥1 item and values are valid hex/rgb.

Border clips content

The inner panel should be your content area; don’t add extra padding unless needed.

Firefox looks different

Provide an SVG or outline fallback for strict Firefox targets.

## Source

### Header comment

*SC\_GradientBorder.tsx · lines 15–23 · header comment*

```tsx
/**
 * SC Gradient Border
 * © SecretoCho Design 2025 (https://secretocho.design)
 * Renders a configurable gradient border using CSS masks (no images/SVG).
 * Uses padding=borderWidth to create the ring; inner area stays clean for content.
 * @framerDisableUnlink
 * @framerIntrinsicWidth 200
 * @framerIntrinsicHeight 200
 */
```

[props \[REF\]](#reference)

### Key excerpt

The whole effect: padding as wide as the border, a gradient background, and two masks composited with exclude, so only the ring shows.

*SC\_GradientBorder.tsx · lines 30–62 · tsx*

```tsx
    const gradientStops = stops
        .map((stop) => `${stop.color} ${stop.position}%`)
        .join(", ")

    const gradient = `linear-gradient(${angle}deg, ${gradientStops})`

    return (
        <div
            style={{
                position: "relative",
                width: "100%",
                height: "100%",
                padding: borderWidth,
                borderRadius,
                background: gradient,
                WebkitMask:
                    "linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0)",
                WebkitMaskComposite: "xor",
                maskComposite: "exclude",
                boxSizing: "border-box",
            }}
        >
            <div
                style={{
                    width: "100%",
                    height: "100%",
                    background: "white",
                    borderRadius,
                    boxSizing: "border-box",
                }}
            ></div>
        </div>
    )
```

## Credits

### Credits

- Effect pattern inspired by CSS mask-composite techniques.
- Implementation & Framer adaptation by SecretoCho Design.

- **license**: SecretoCho Design

SecretoCho Design 2025

### Disclaimer

Provided “as is” for visual/UX purposes. Validate cross-browser behavior, accessibility, and performance for your project.

## Proves

- [Creative coding](https://secretocho.design/about/#capabilities)

## Hiring a design engineer?

I’m open to senior design engineer roles: remote from Belgrade, or relocation with visa sponsorship. Write to me, or read the CV first. Client work stays selective, one project at a time.

[sc@secretocho.design](mailto:sc@secretocho.design)

[read the CV](https://secretocho.design/cv/) · [LinkedIn](https://www.linkedin.com/in/secretocho/)
