Skip to main content

Theme Specification

morfeo's theme specification is strongly inspired by system-ui but it has some important differences. The Theme is an extendible object that describes the design language of your application, it's a composition of slices that contains different elements like colors, gradients, spacings and others:

interface Theme {
radii: Radii;
sizes: Sizes;
fonts: Fonts;
colors: Colors;
shadows: Shadows;
borders: Borders;
spacings: Spacings;
zIndices: ZIndices;
fontSizes: FontSizes;
gradients: Gradients;
opacities: Opacities;
fontWeights: FontWeights;
lineHeights: LineHeights;
breakpoints: BreakPoints;
transitions: Transitions;
borderWidths: BorderWidths;
mediaQueries: MediaQueries;
borderStyles: BorderStyles;
letterSpacings: LetterSpacings;

components: Components;

The main difference between morfeo's theme and others is the components slice that will contain the specification of your components.


In this table, for each slice, are indicated the css properties that will be resolved with values of that slice:

colorsbg, fill, color, stroke, caretColor, borderColor, outlineColor, borderTopColor, backgroundColor, columnRuleColor, borderLeftColor, borderRightColor, borderBottomColor
radiiborderRadius, borderEndEndRadius, borderTopLeftRadius, borderEndStartRadius, borderTopRightRadius, borderStartEndRadius, borderStartStartRadius, borderBottomLeftRadius, borderBottomRightRadius, corner, cornerEndEnd, cornerTopLeft, cornerEndStart, cornerTopRight, cornerStartEnd, cornerStartStart, cornerBottomLeft, cornerBottomRight,
sizessize, minSize, maxSize width, height, minWidth, maxWidth, minHeight, maxHeight, flexBasis, blockSize, inlineSize, maxBlockSize, minBlockSize, minInlineSize, maxInlineSize
shadowsboxShadow, textShadow, shadow
bordersborder, borderTop, borderLeft, borderRight, borderBlock, borderBottom, borderInline, borderBlockEnd, borderInlineEnd, borderBlockStart, borderInlineStart
spacingsm, mt, ml, mr, mb, mx, my, margin, marginTop, marginRight, marginBottom, marginLeft, marginBlock, marginBlockEnd, marginBlockStart, marginInline, marginInlineEnd, marginInlineStart, p, pt, pl, pr, pb, px, py, padding, paddingTop, paddingLeft, paddingRight, paddingBottom, paddingBlock, paddingBlockEnd, paddingBlockStart, paddingInline, paddingInlineEnd, paddingInlineStart, scrollPadding, scrollPaddingTop, scrollPaddingRight, scrollPaddingBottom, scrollPaddingLeft, inset, insetBlock, insetBlockEnd, insetBlockStart, insetInline, insetInlineEnd, insetInlineStart, top, right, bottom, left, gridGap, gridColumnGap, gridRowGap, gap, columnGap, rowGap
gradientsgradient, bgGradient, textGradient
borderWidthsborderWidth, borderTopWidth, borderLeftWidth, borderRightWidth, borderBlockWidth, borderBottomWidth, borderInlineWidth, borderBlockEndWidth, borderInlineEndWidth, borderBlockStartWidth, borderInlineStartWidth
borderStylesborderStyle, borderTopStyle, borderLeftStyle, borderRightStyle, borderBlockStyle, borderBottomStyle, borderInlineStyle, borderBlockEndStyle, borderInlineEndStyle, borderBlockStartStyle, borderInlineStartStyle
componentscomponentName, variant

Custom Properties

Some of the properties do not correspond to any CSS rule but they will be resolved to valid CSS rules. This table will clarify better:

sizeheight + width
minSize, maxSizeminheight + minWidth, maxHeight + maxWidth
m, mt, ml, mr, mbmargin, marginTop, marginLeft, marginRight, marginBottom
mxmarginLeft + marginRight
mymarginTop + marginBottom
p, pt, pl, pr, pbpadding, paddingTop, paddingLeft, paddingRight, paddingBottom
pxpaddingLeft + paddingRight
pypaddingTop + paddingBottom
gradient, bgGradientbackground
textGradientbackground + backgroundClip + textFillColor
corner, cornerEndEnd, cornerTopLeft, cornerEndStart, cornerTopRight, cornerStartEnd, cornerStartStart, cornerBottomLeft, cornerBottomRight,borderRadius, borderEndEndRadius, borderTopLeftRadius, borderEndStartRadius, borderTopRightRadius, borderStartEndRadius, borderStartStartRadius, borderBottomLeftRadius, borderBottomRightRadius,

componentName, variant will be explained better later in the components slice section.


morfeo.setTheme("default", {
colors: { primary: '#fefefe', ... },
spacings: { xxs: '8px', xs: '16px', ... },
// @morfeo/core | @morfeo/web
const style = morfeo.resolve({ bg: 'primary', px: 'xs' });
// @morfeo/react
const style = useStyle({ bg: 'primary', px: 'xs' });
// @morfeo/svelte
<button use:morfeoStyle={{ bg: 'primary', px: 'xs' }} />

In this case the style { bg: 'primary', px: 'xs' } will be resolved in:

"backgroundColor": "#fefefe",
"paddingLeft": "16px",
"paddingRight": "16px"

Morfeo Style Object

The object passed to morfeo.resolve (core api), useStyle (react) or use:morfeoStyle (svelte), is called morfeo style object, if your using typescript, this object is described by the type Style:

import { Style } from '@morfeo/spec';

const morfeoStyleObject: Style = {
bg: 'primary',
p: 'm',

const style = morfeo.resolve(morfeoStyleObject);
// or if you're using React
// const style = useStyle({ bg: 'primary', px: 'xs' });

The differences between a morfeo style object and a css-in-js object are:

  • the values inside a morfeo style object refer the theme;
  • the keys of a morfeo style object could be aliases

After the parsing by morfeo, a "morfeo style object" is converted into a valid css-in-js that you can use to stylize a component or an html element.

morfeo style objectcss in js object
{ p: 'm' }{ padding: '20px' }
{ color: 'primary' }{ color: '#06f' }
{ componentName: 'Button' }{ backgroundColor: '#06f', paddingLeft: '40px', paddingRight: '40px' }

since @morfeo/spec is re-exported by the other morfeo packages, you don't need to install directly @morfeo/spec to use it.



All the other slices are meant to make it easier to follow a design language by using aliases instead of values, so you'd rather use color: danger instead of color: #e74c3c, or padding: s instead of padding: 24px; But this is not enough to ensure that the UI will be consistent. For example:

import { MorfeoComponent, useClassName } from '@morfeo/react';

const Button = props => <MorfeoComponent componentName="Button" {...props} />;

function ConfirmButton({ children }) {
const className = useClassName({ px: 's', bg: 'successs' });
return <Button className={className}>{children}</Button>;

function CancelButton({ children }) {
const className = useClassName({
px: 'm',
py: 'xs',
bg: 'danger',
color: 'primary',

return <Button className={className}>{children}</Button>;

we are using @morfeo/react in this example but you can apply the same problem in each language / framework

In this case, every property is following the design language, but the buttons will look completely different, and they'll break the consistency of your app, which is the reason you're using @morfeo (or any other system) in the first place.

The style of your components is part of the design language of your application, that's why in morfeo you can define this style (and other properties) directly inside the theme object.


the component's theme slice is an object where the key is the name of the component and the value is its configuration:

const myTheme = {
components: {
Button: {
style: { height: 'm', px: 's', borderRadius: 'm' },
variants: {
cancel: {
style: { bg: 'danger' },
confirm: {
style: { bg: 'success' },
Typography: {
style: { fontFamily: 'regular' },
variants: {
h1: {
style: { fontSize: 'l', fontWeight: 'bold' },
h2: {

Let's repeat the previous example to see the advantages of having components inside the theme object:

function ConfirmButton({ children }) {
return <Button variant="success">{children}</Button>;

function CancelButton({ children }) {
return <Button variant="cancel">{children}</Button>;

The first advantage we can see is the complete removal of inline-style, the second one is that every component meant to be a button can use the property componentName to ensure it has the same style as all the other buttons.

Of course, every application has more than one button, that's why you can specify inside the theme a list of variants for each component, in this case, we create 2 variants for the Button component: cancel and success; The variants are a specialization of the base component, the style you put inside a variant will be merged with the parent:

// style of Button:
height: 'm', px: 's', borderRadius: 'm'
// style of success variant
height: 'm', px: 's', borderRadius: 'm', bg: 'success'
// style of cancel variant
height: 'm', px: 's', borderRadius: 'm', bg: 'danger'


More about the components slice can be found in the dedicated page here.