Nine-slice scaling component for Solid.js using CSS border-image
npm install @nine-slice-frame/solid

Nine-slice scaling component for Solid.js using CSS border-image.
Nine-slice scaling divides an image into 9 sections, allowing it to scale to any size while preserving corner details and preventing distortion. Perfect for UI frames, borders, panels, and buttons that need to scale dynamically.
```
āāāāāāāāāāā¬āāāāāāāāāāāā¬āāāāāāāāāā
ā Corner ā Top Edge ā Corner ā
ā (Fixed) ā (Scale H) ā (Fixed) ā
āāāāāāāāāāā¼āāāāāāāāāāāā¼āāāāāāāāāā¤
ā Left ā Center ā Right ā
ā Edge ā (Scale ā Edge ā
ā(Scale V)ā Both) ā(Scale V)ā
āāāāāāāāāāā¼āāāāāāāāāāāā¼āāāāāāāāāā¤
ā Corner ā Bottom ā Corner ā
ā (Fixed) ā Edge ā (Fixed) ā
āāāāāāāāāāā“āāāāāāāāāāāā“āāāāāāāāāā
The Problem: Traditional image scaling stretches the entire image uniformly, distorting corners, borders, and decorative elements. This makes UI elements look unprofessional and breaks visual consistency.
The Solution: Nine-slice scaling keeps corners and edges crisp while only stretching the middle sections. This means:
- Single image, infinite sizes - One asset works for buttons, dialogs, and panels of any dimension
- Pixel-perfect corners - Ornate borders and rounded corners stay sharp at any scale
- Smaller file sizes - No need for multiple image variants for different sizes
- Ideal for pixel art - Preserves the crisp aesthetic of retro-style UIs
- CSS-native performance - Uses browser-native border-image, no canvas or WebGL overhead
Common Use Cases:
- Game UI frames and dialog boxes
- Decorative borders and panels
- Scalable buttons with ornate edges
- Retro/pixel art interfaces
- Dynamic content containers
Zero Dependencies - No runtime dependencies beyond Solid.js. This package only requires Solid.js as a peer dependency.
Incredibly Small - Minimal bundle impact: 3.09KB / 1.28KB gzipped
Native Performance - Uses browser-native CSS border-image property, not canvas rendering or heavy image manipulation libraries. Fast, efficient, and hardware-accelerated.
Framework-Agnostic API - Same simple, consistent API across all frameworks:
- @nine-slice-frame/react
- @nine-slice-frame/vue
- @nine-slice-frame/svelte
- @nine-slice-frame/solid (you are here)
`bash`
npm install @nine-slice-frame/solidor
pnpm add @nine-slice-frame/solidor
yarn add @nine-slice-frame/solid
`tsx
import { NineSliceFrame } from '@nine-slice-frame/solid';
function App() {
return (
slice={7}
borderWidth={5}
repeat="stretch"
fill={true}
pixelated={true}
>
Your content here
Props
| Prop | Type | Default | Description |
| ------------- | --------------------------------------------- | ----------- | --------------------------------------------------------------------------------- |
|
imagePath | string | required | Path to the image (relative to public folder) |
| slice | number \| object | 8 | Slice values - number for uniform, or { top, right, bottom, left } for per-edge |
| borderWidth | number | 5 | Visual border width in pixels |
| repeat | 'stretch' \| 'repeat' \| 'round' \| 'space' | 'stretch' | Border repeat mode |
| fill | boolean | true | Use 'fill' to show center of image as background |
| pixelated | boolean | true | Use pixelated rendering for pixel art |
| class | string | '' | Additional CSS class names |
| style | JSX.CSSProperties | {} | Additional inline styles |Advanced Usage
$3
`tsx
imagePath="/ui/fancy-frame.png"
slice={{ top: 10, right: 8, bottom: 10, left: 8 }}
borderWidth={6}
>
Content with asymmetric border
`$3
`tsx
imagePath="/ui/frame.png"
slice={8}
borderWidth={10}
class="my-custom-frame"
style={{ padding: '20px', 'min-height': '200px' }}
>
Styled content
``This package includes TypeScript definitions out of the box.
- solid-js >= 1.8.0
MIT Ā© Callum Gander