Blog

Build custom themes using Theme UI

Oct 3, 2020 5 min read

Share Build custom themes using Theme UI article on different platforms.

web-development

Build themes for any JavaScript application using Theme UI.

Theme UI - Themes

Theme UI - Themes

Theme UI is a graph based design framework for creating themeable user interfaces based on constraint-based design principles.

👀 Demo

Theme UI

The Design Graph Framework

https://theme-ui.com/home
Theme UI
Sai Nikhil | Blog

Personal blog with articles related to Web Development, Software Tools, Tips & Tricks, etc.

https://blog.iamsainikhil.com/
Sai Nikhil | Blog

🎉 Features

  • JSON based theme configuration to truly customize properties & values on the fly and develop a custom theme for a website or a web application.
  • Provides sx prop which can be used in React components to use all the properties mentioned in the theme object.
  • Useful configuration flags that can be used to quickly toggle features.
Theme UI Configuration Fla

Theme UI Configuration Fla

🔌 Theme Specification

Treat theme specification as a set of guidelines to construct a proper Theme UI theme object that can be used in any React or Gatsby based application.

For more information on the Theme UI specification, check Theme UI spec documentation.

The theme object is made up of the following data types:

  • Scales: plain objects or arrays of values for related CSS properties
  • Variants: partial style objects that can be used for stylistic component variants or making part of an application themeable
  • Styles: a collection of styles for Markdown content
Theme Spec – Theme UI

The Design Graph Framework

https://theme-ui.com/theme-spec
Theme UI

I created a theme based on the above specification guidelines which you can find below:

Theme breakdown

1. Configuration Flags

JAVASCRIPT
useBodyStyles: true,
useCustomProperties: true,
initialColorMode: 'dark',
useColorSchemeMediaQuery: true,
useLocalStorage: true

2. Variants

JAVASCRIPT
breakpoints: ['30em', '47em', '64em', '100em'],
space: [0, 4, 8, 16, 32, 64, 128, 256, 512],
borders: [0],
colors: {
text: '#000',
background: '#ffff',
primary: '#333',
secondary: '#5b5b5b',
muted: '#f6f6f6',
highlight: '#9f9f9f',
gray: '#6c6c6c',
accent: '#3f3f3f',
gatsby: '#352065',
code: '#fdf6e3',
shade1: '#d2d2d2',
shade2: '#e0e0e0',
modes: {
dark: {
text: '#fff',
background: '#181818',
primary: '#d2d2d2',
secondary: '#b2b2b2',
muted: '#202020',
highlight: '#3c3c3c',
gray: '#999',
accent: '#e0e0e0',
gatsby: '#b2b2b2',
code: '#1b1b1b',
shade1: '#0a0a0a',
shade2: '#262626'
}
}
},
fonts: {
light: "'CeraRoundPro-Light', 'Inter', 'Lato', sans-serif",
body: "'CeraRoundPro', 'Inter', 'Lato', sans-serif",
medium: "'CeraRoundPro-Medium', 'Inter', 'Lato', sans-serif",
heading: "'CeraRoundPro-Bold', 'Inter', 'Lato', sans-serif",
code: "'Fira Code', monospace",
title: "'Inter', 'Lato', sans-serif"
},
fontSizes: [12, 14, 16, 20, 24, 32, 48, 64, 72],
fontWeights: {
light: 300,
body: 400,
medium: 500,
heading: 700
},
lineHeights: {
body: 1.5,
heading: 1.125
},
textStyles: {
title: {
fontFamily: 'title',
fontWeight: 'heading',
lineHeight: 'heading'
},
medium: {
variant: 'medium',
fontWeight: 'medium'
},
heading: {
fontFamily: 'heading',
fontWeight: 'heading',
lineHeight: 'heading'
},
body: {
fontFamily: 'body',
fontWeight: 'body',
lineHeight: 'body'
},
light: {
fontFamily: 'light',
fontWeight: 'light'
}
}

3. Styles

JAVASCRIPT
Container: {
p: 3,
maxWidth: 1024
},
root: {
variant: 'textStyles.body'
},
h1: {
variant: 'textStyles.title',
fontSize: [4, 5, 6]
},
h2: {
variant: 'textStyles.heading',
fontSize: [3, 4, 5]
},
h3: {
variant: 'textStyles.heading',
fontSize: [3, 4],
color: 'primary'
},
h4: {
variant: 'textStyles.medium',
fontSize: [3, 4],
color: 'primary'
},
h5: {
variant: 'textStyles.medium',
fontSize: 2
},
h6: {
variant: 'textStyles.medium',
fontSize: 1
},
p: {
fontSize: [1, 2, 3]
},
em: {
fontFamily: 'light',
fontSize: [1, 2, 3]
},
a: {
color: 'gatsby',
textDecoration: 'underline',
'&:hover': {
color: 'secondary',
textDecoration: 'none'
}
},
blockquote: {
fontSize: [1, 2, 3],
variant: 'textStyles.body',
margin: '1.45rem',
padding: '0 0 0 1rem',
borderColor: 'gatsby',
borderStyle: 'solid',
borderTopWidth: 0,
borderLeftWidth: 2,
borderRightWidth: 0,
borderBottomWidth: 0
},
pre: {
fontFamily: 'code',
fontSize: [0, 1],
p: [1, 2],
color: 'text',
bg: 'code',
borderColor: 'accent',
borderStyle: 'solid',
borderWidth: 2
},
code: {
fontFamily: 'code',
fontSize: 1,
color: 'muted',
bg: 'gatsby',
px: 1
},
inlineCode: {
fontFamily: 'code',
color: 'secondary',
bg: 'muted',
px: 2
},
ul: {
listStyleType: 'disc'
},
li: {
my: 2
},
table: {
width: '100%',
my: 4,
borderCollapse: 'separate',
borderSpacing: 0,
'th,td': {
textAlign: 'left',
py: '4px',
pr: '4px',
pl: 0,
borderColor: 'text',
borderBottomStyle: 'solid'
}
},
th: {
backgroundColor: 'muted',
verticalAlign: 'bottom',
borderBottomWidth: 8
},
td: {
verticalAlign: 'top',
borderBottomWidth: 4
},
hr: {
border: 0,
borderBottom: '8px solid',
borderColor: 'text'
},
buttons: {
primary: {
color: 'background',
bg: 'primary',
'&:hover': {
bg: 'text'
}
},
secondary: {
color: 'background',
bg: 'secondary'
}
}
}

🎨 Result

JAVASCRIPT
{
useBodyStyles: true,
useCustomProperties: true,
initialColorMode: 'dark',
useColorSchemeMediaQuery: true,
useLocalStorage: true,
breakpoints: ['30em', '47em', '64em', '100em'],
space: [0, 4, 8, 16, 32, 64, 128, 256, 512],
borders: [0],
colors: {
text: '#000',
background: '#ffff',
primary: '#333',
secondary: '#5b5b5b',
muted: '#f6f6f6',
highlight: '#9f9f9f',
gray: '#6c6c6c',
accent: '#3f3f3f',
gatsby: '#352065',
code: '#fdf6e3',
shade1: '#d2d2d2',
shade2: '#e0e0e0',
modes: {
dark: {
text: '#fff',
background: '#181818',
primary: '#d2d2d2',
secondary: '#b2b2b2',
muted: '#202020',
highlight: '#3c3c3c',
gray: '#999',
accent: '#e0e0e0',
gatsby: '#b2b2b2',
code: '#1b1b1b',
shade1: '#0a0a0a',
shade2: '#262626'
}
}
},
fonts: {
light: "'CeraRoundPro-Light', 'Inter', 'Lato', sans-serif",
body: "'CeraRoundPro', 'Inter', 'Lato', sans-serif",
medium: "'CeraRoundPro-Medium', 'Inter', 'Lato', sans-serif",
heading: "'CeraRoundPro-Bold', 'Inter', 'Lato', sans-serif",
code: "'Fira Code', monospace",
title: "'Inter', 'Lato', sans-serif"
},
fontSizes: [12, 14, 16, 20, 24, 32, 48, 64, 72],
fontWeights: {
light: 300,
body: 400,
medium: 500,
heading: 700
},
lineHeights: {
body: 1.5,
heading: 1.125
},
textStyles: {
title: {
fontFamily: 'title',
fontWeight: 'heading',
lineHeight: 'heading'
},
medium: {
variant: 'medium',
fontWeight: 'medium'
},
heading: {
fontFamily: 'heading',
fontWeight: 'heading',
lineHeight: 'heading'
},
body: {
fontFamily: 'body',
fontWeight: 'body',
lineHeight: 'body'
},
light: {
fontFamily: 'light',
fontWeight: 'light'
}
},
styles: {
Container: {
p: 3,
maxWidth: 1024
},
root: {
variant: 'textStyles.body'
},
h1: {
variant: 'textStyles.title',
fontSize: [4, 5, 6]
},
h2: {
variant: 'textStyles.heading',
fontSize: [3, 4, 5]
},
h3: {
variant: 'textStyles.heading',
fontSize: [3, 4],
color: 'primary'
},
h4: {
variant: 'textStyles.medium',
fontSize: [3, 4],
color: 'primary'
},
h5: {
variant: 'textStyles.medium',
fontSize: 2
},
h6: {
variant: 'textStyles.medium',
fontSize: 1
},
p: {
fontSize: [1, 2, 3]
},
em: {
fontFamily: 'light',
fontSize: [1, 2, 3]
},
a: {
color: 'gatsby',
textDecoration: 'underline',
'&:hover': {
color: 'secondary',
textDecoration: 'none'
}
},
blockquote: {
fontSize: [1, 2, 3],
variant: 'textStyles.body',
margin: '1.45rem',
padding: '0 0 0 1rem',
borderColor: 'gatsby',
borderStyle: 'solid',
borderTopWidth: 0,
borderLeftWidth: 2,
borderRightWidth: 0,
borderBottomWidth: 0
},
pre: {
fontFamily: 'code',
fontSize: [0, 1],
p: [1, 2],
color: 'text',
bg: 'code',
borderColor: 'accent',
borderStyle: 'solid',
borderWidth: 2
},
code: {
fontFamily: 'code',
fontSize: 1,
color: 'muted',
bg: 'gatsby',
px: 1
},
inlineCode: {
fontFamily: 'code',
color: 'secondary',
bg: 'muted',
px: 2
},
ul: {
listStyleType: 'disc'
},
li: {
my: 2
},
table: {
width: '100%',
my: 4,
borderCollapse: 'separate',
borderSpacing: 0,
'th,td': {
textAlign: 'left',
py: '4px',
pr: '4px',
pl: 0,
borderColor: 'text',
borderBottomStyle: 'solid'
}
},
th: {
backgroundColor: 'muted',
verticalAlign: 'bottom',
borderBottomWidth: 8
},
td: {
verticalAlign: 'top',
borderBottomWidth: 4
},
hr: {
border: 0,
borderBottom: '8px solid',
borderColor: 'text'
},
buttons: {
primary: {
color: 'background',
bg: 'primary',
'&:hover': {
bg: 'text'
}
},
secondary: {
color: 'background',
bg: 'secondary'
}
}
}
}

A theme does not require that all these fields be present and can include additional values as needed.

That's it, you can now use this theme directly in your application or customize the above properties to create a new theme of your choice. #skyisthelimit

Please don't forget to share your theme configuration in the comments section.

This article was last updated on Oct 3, 2020

JavaScript

Theme UI

ShareShare this article on different platforms.

Sai Nikhil - Photo

Sai Nikhil

A passionate developer who brings creative ideas from areas, including networking & data storage, security, UI/UX design, and progressive web applications with a strong understanding of the entire web development process.

Related Articles

NextJS Prismic Blog Starter

Build a Blog using NextJS & Prismic

Learn and build a blog using NextJS Prismic Blog starter template as quickl... Read Full Article

web-development

Dec 1, 2020| 15 min read

Prismic Webhooks

Prismic Webhooks

A Prismic Webhook allow you to automatically or manually trigger a deployme... Read Full Article

Oct 8, 2020| 3 min read

Weather React Application UI

Build a Weather Application Using React

This weather application provides current and 24 hour 7-day weather forecas... Read Full Article

Jul 31, 2020| 10 min read