Configuration and Theming
Twind offers configuration and theming options via a setup
function. The setup
function is a named export of the twind
module and accepts a configuration object as an argument.
TIP
The setup
function is not required to use Twind. If used, it must be called before any tw
calls.
import { setup, strict, voidSheet } from 'twind'
setup({
preflight: false, // do not include base style reset (default: use tailwind preflight)
mode: strict, // throw errors for invalid rules (default: warn)
hash: true, // hash all generated class names (default: false)
theme: {}, // define custom theme values (default: tailwind theme)
darkMode: 'class', // use a different dark mode strategy (default: 'media')
sheet: voidSheet, // use custom sheet (default: cssomSheet in a browser or no-op)
})
Theme
For maximum compatibility and ease of adoption, theming in Twind works exactly the same as theming in Tailwind.
Here is an example of overriding and extending values in the theme:
import { setup } from 'twind'
setup({
theme: {
fontFamily: {
sans: ['Helvetica', 'sans-serif'],
serif: ['Times', 'serif'],
},
extend: {
spacing: {
128: '32rem',
144: '36rem',
},
},
},
})
Colors
The Tailwind v2 extended color palette is available in the twind/colors
module.
List of colors: amber
,black
,blue
,blueGray
,coolGray
,cyan
,emerald
,fuchsia
,gray
,green
,indigo
,lightBlue
,lime
,orange
,pink
,purple
,red
,rose
,teal
,trueGray
,violet
,warmGray
,white
, yellow
import * as colors from 'twind/colors'
setup({
theme: {
colors: {
// Build your palette here
gray: colors.trueGray,
red: colors.red,
blue: colors.lightBlue,
yellow: colors.amber,
},
},
})
To extend the existing color palette use theme.extend
:
import * as colors from 'twind/colors'
setup({
theme: {
extend: {
colors,
},
},
})
Referencing theme values
If you need to reference another theme value, you can do so by providing a function instead of a static value. The function will receive a theme()
function as an argument that you can use to look up other values in your theme.
setup({
theme: {
fill: (theme) => theme('colors'),
},
})
Preflight
To smooth over browser inconsistencies, Twind provides the same opinionated modern reset provided by Tailwind. By default, the base reset styles will be injected into the head of the document before any other rules.
Preflight can be configured in the setup
function.
Disable preflight:
setup({
preflight: false,
})
Customize preflight be providing a function that returns an object:
setup({
// context: tw, theme and, tag functions
preflight: (preflight, { theme }) => ({
...preflight,
h2: {
color: 'dodgerblue',
},
}),
})
You can also use the apply
function to apply Twind rules:
import { apply, setup } from 'twind'
setup({
preflight: {
body: apply`bg-gray-900 text-white`,
h1: apply`text(gray-800 uppercase)`, // Grouping syntax
},
})
You can use the css
function to merge rules:
import { css, theme, apply } from 'twind/css#css_directive'
setup({
preflight: (preflight) =>
css(
preflight,
{
body: {
backgroundColor: theme('colors.gray.900'),
},
},
{ body: apply`text-gray-100` },
),
})
// Or using template literal:
setup({
preflight: (preflight) => css`
${preflight}
body {
background-color: ${theme('colors.gray.900')};
${apply`text-gray-100`}
}
`,
})
Custom fonts and imports
Preflight includes two special keys, @font-face
and @import
:
@import
allows you to import external style sheets.
@font-face
allows you to declare font faces.
In the example below, we are using @font-face
and @import
together to import and declare font faces, which are used to extend the sans
font family theme value:
import { setup } from 'twind'
setup({
theme: {
extend: {
fontFamily: {
sans: 'Roboto, sans-serif',
'proxima-nova': '"Proxima Nova"',
},
},
},
preflight: {
// Import external stylesheet
'@import': `url('https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,400;0,700;1,400&display=swap')`,
// Declare font face
'@font-face': [
{
fontFamily: 'Proxima Nova',
fontWeight: '400',
src: 'url(/fonts/proxima-nova/400-regular.woff) format("woff")',
},
{
fontFamily: 'Proxima Nova',
fontWeight: '500',
src: 'url(/fonts/proxima-nova/500-medium.woff) format("woff")',
},
],
},
})
Mode
One benefit of doing compilation at runtime is that it is possible to warn developers about errors such as:
- Unknown directive: warn when an unrecognized rule is encountered
- Missing theme values: warn when a unknown theme value is encountered
By default, these kind of warnings will be surfaced in the developer console but will not cause the program to throw an error and crash.
However, sometimes throwing an error might be desirable. For example, during testing or continuous integrations.
To force the program to error instead of warn set mode
to strict
:
import { setup, strict } from 'twind'
setup({
mode: strict, // Throw errors for invalid rules instead of logging
})
To ignore all warnings set the mode
to silent
:
import { setup, silent } from 'twind'
setup({
mode: silent,
})
💡 If you are using JSON configuration the modes can be set using strings:
"strict"
,"warn"
or"silent"
.
Hash
Most CSS-in-JS solutions, such as styled components or emotion will create hashed class names for rule sets. This makes sense because there is no logical way of naming an arbitrary set of styles. Doing this makes less sense when using an utility class approach because directives are usually carefully named.
By default, rules that are passed into the tw
function are not hashed. This helps retain the advantage of using utility classes, aiding inspection and debugging.
To enable hashing of class names set hash
to true
.
setup({
hash: true,
})
Alternatively a custom hash function can be provided:
import hash from '@emotion/hash'
setup({
hash: (string) => 'tw-' + hash(string),
})
Dark Mode
Now that dark mode is a first-class feature of many operating systems, it's becoming more and more common to design a dark version of your website to go along with the default design.
To make this as easy as possible, Twind includes a dark variant that lets you style your site differently when dark mode is enabled:
tw`
bg-white text-black
dark:(bg-gray-800 text-white)`
💡 It's important to note that the dark mode variant is always enabled and available for all directives.
Now whenever dark mode is enabled on the user's operating system, dark:{directive}
rules will take precedence over unprefixed rules. The media
strategy uses the prefers-color-scheme media feature under the hood, but if you'd like to support toggling dark mode manually, you can also use the class
strategy which uses adds a .dark
class selector for more control:
setup({
darkMode: 'class', // default is 'media'
})
For an example how to toggle dark mode manually read the Tailwind Guide.
Sheet
Twind collects generated CSS rules in sheet to make theme available to the environment. By default Twind uses a speedy (CSSOM) implementation when running in the browser. On the server a no-op implementation is used.
CSSOM Sheet
💡 This is the default implementation in browser environments.
If the cssomSheet
is passed no target
it looks for an style element with the id __twind
. If no such element is found it will create one and append it to the document.head
.
import { setup, cssomSheet } from 'twind'
const sheet = cssomSheet({ target: new CSSStyleSheet() })
setup({ sheet })
💡 See Examples - LitElement how this can be used.
Void Sheet
💡 This is the default implementation on server environments.
import { setup, voidSheet } from 'twind'
setup({ sheet: voidSheet() })
DOM Sheet
A sheet implementation which inserts style rules through the Document Object Model.
💡 This implementation is way slower than the default (cssomSheet) but may be useful to see the generated CSS right in the DOM. Most modern browser display CSS rules from the speedy default sheet using their CSS inspector.
import { setup } from 'twind'
import { domSheet } from 'twind/sheets'
setup({ sheet: domSheet() })
💡 See twind/sheets for details.
Virtual Sheet
A sheet implementation which collects style rules into an array.
import { setup } from 'twind'
import { virtualSheet } from 'twind/sheets'
const sheet = virtualSheet()
setup({ sheet })
// An array of all inserted CSS rules
sheet.target
Custom Sheet Implementation
In case the builtin sheet implementations do not solve your use case, you can create your own.
Plugins
The plugins
property allows to define new plugins or override core plugins. See plugins for details.
Variants
The variants
property allows to define new variants or override core variants.
setup({
variants: {
'not-checked': '&:not(:checked)',
},
})