Friendly avatars,
from any string.
Pass a user ID, email or name. Get the same delightful avatar every time, as clean SVG that themes with CSS variables, in every framework.
One seed in. The same face out, everywhere.
- DeterministicSame seed, same avatar: on the server, in every browser, in every framework.
- Zero dependenciesA tiny core plus native wrappers. Import only the styles you ship.
- ThemeableColors are CSS variables, so avatars follow your brand and dark mode.
- Every frameworkReact, Vue, Svelte, Angular, Web Components, or plain SVG strings.
Make it yours.
Every option, live. What you see is the library's own output; copy the code for your framework or download the SVG.
One hundred seeds.
Names, emails and IDs, the way real apps pass them. Hover to see the seed.
Install
One core with zero dependencies, and a thin native component for each framework. Styles are separate imports, so you ship only what you use.
pnpm add @inlaylab/opaline
import { createAvatar } from '@inlaylab/opaline'
import { morph } from '@inlaylab/opaline/morph'
createAvatar(morph, { seed: 'ada@inlay.dev' }).svgpnpm add @inlaylab/opaline-element
<script type="module">import '@inlaylab/opaline-element'</script> <opaline-avatar seed="ada@inlay.dev" look="morph"></opaline-avatar>
pnpm add @inlaylab/opaline-react
import { Avatar } from '@inlaylab/opaline-react'
import { morph } from '@inlaylab/opaline/morph'
<Avatar seed="ada@inlay.dev" look={morph} src={user.photo} alt="Ada" />pnpm add @inlaylab/opaline-angular
import { OpalineAvatar } from '@inlaylab/opaline-angular'
import { morph } from '@inlaylab/opaline/morph'
<op-avatar seed="ada@inlay.dev" [look]="morph" [src]="user.photo" alt="Ada" />pnpm add @inlaylab/opaline-vue
import { Avatar } from '@inlaylab/opaline-vue'
import { morph } from '@inlaylab/opaline/morph'
<Avatar seed="ada@inlay.dev" :look="morph" :src="user.photo" alt="Ada" />pnpm add @inlaylab/opaline-svelte
import { Avatar } from '@inlaylab/opaline-svelte'
import { morph } from '@inlaylab/opaline/morph'
<Avatar seed="ada@inlay.dev" look={morph} src={user.photo} alt="Ada" />Options
Any option you set fixes that part; the seed fills in the rest.
| Option | Values | What it does |
|---|---|---|
seed | string | number | null | Any string: user ID, email, name. Emails are lower-cased; whitespace is trimmed. |
size | number | Pixel size. Default 64. |
palette | vivid · pastel · electric · muted · warm · cool · mono | Color family. Default vivid. |
finish | flat · soft · gloss | Light and shade. Morph and Gradient default to flat, Clay to soft. |
expression | beam · content · … · giggle | Fix the face. Or set mood: happy · calm · surprised · playful. |
face | boolean | Morph, Gradient and Clay show a face unless false. |
family | egg · duo · tri · cushion · clover · petal | Blob shape family. |
body | jelly · hood | Clay only. With ears: cat · bear · bunny. |
shape | circle · squircle | Aura only. |
backdrop | none · tint | A soft circle behind the body. |
src · alt | string | Wrappers only: a photo shown once it loads, and an accessible name. |
Theming
Colors come out as var(--avatar-c1, #hex). Set the variables on any parent to follow your brand or dark mode. --avatar-c1 is always the body.
Same seed, same avatar
The seed is normalized (trimmed, NFC, emails lower-cased) and hashed into a seeded generator; no Math.random, no dates. The same seed and options give the same picture on the server, in every browser and in every framework. Gradient IDs are scoped per seed and options, and each component instance adds its own suffix, so two avatars on one page never clash.