Fast and simple zero-dependency library of a single-argument function that converts Tailwind classes of default configuration to style objects using pre-compiled key-value pairs of class names and corresponding styles. Perfect for email rendering! Can be used on front-end, back-end and your microwave if it supports JavaScript. Check list of supported classes (can take a while to load).
npm i tailwind-to-object
# Or
yarn add tailwind-to-object
Accepts a space-delimited string of Tailwind classes as the only argument and returns an object of camel-cased styles.
import tailwindToObject from 'tailwind-to-object';
const style = tailwindToObject(`
text-2xl
font-bold
text-center
!px-3
text-red-200
bg-[#FFFFFF]
border-[5px]
-top-4
w-[calc(100%_-_100px)]
h-1/2
`);
console.log(style);
/*
{
// text-2xl
fontSize: '1.5rem',
lineHeight: '2rem',
// font-bold
fontWeight: '700',
// text-center
textAlign: 'center',
// !px-3
paddingLeft: '0.75rem !important',
paddingRight: '0.75rem !important',
// text-red-200
color: '#FECACA',
// bg-[#FFFFFF]
background: '#FFFFFF',
// border-[5px]
borderWidth: '5px',
// -top-4
top: '-1rem',
// w-[calc(100%_-_100px)]
width: 'calc(100% - 100px)',
// h-1/2
height: '50%',
}
*/
You can simulate the regular className property in your React component that is going to be converted and applied as a style object. Optionally, install tailwind-merge to avoid potential conflicts. Since the library is not related to any framework, you can create something with similar idea for your own environment. Feel free to create a PR to add more examples.
// tailwindComponents.ts
import { ComponentProps, createElement } from 'react';
import { twMerge } from 'tailwind-merge';
import tailwindToObject from 'tailwind-to-object';
// put your custom classes here
const classesToReplace = {
'my-custom-class': 'text-[#FF0000] bg-white',
// since the function doesn't use Tailwind config, you may want to define custom font sizes here
'text-sm': 'text-[14px]',
};
const replaceClasses = (classNames: string[]) => {
const classesToBeApplied = [];
for (const cls of classNames) {
if (classesToReplace[cls as keyof typeof classesToReplace]) {
classesToBeApplied.push(classesToReplace[cls as keyof typeof classesToReplace]);
} else {
classesToBeApplied.push(cls);
}
}
return classesToBeApplied;
};
function createTag<T extends keyof JSX.IntrinsicElements>(tag: T) {
const component = ({ className, style, ...rest }: ComponentProps<T>) => {
const classNames = replaceClasses(className?.trim().split(/\s+/) ?? []);
const tailwindStyle = classNames.length ? tailwindToObject(twMerge(...classNames)) : {};
return createElement(tag, {
style: { ...tailwindStyle, ...(style ?? {}) },
...rest,
});
};
component.displayName = tag;
return component;
}
export const Div = createTag('div');
export const Span = createTag('span');
export const Table = createTag('table');
export const Tbody = createTag('tbody');
export const Thead = createTag('thead');
export const Tr = createTag('tr');
export const Td = createTag('td');
export const Th = createTag('th');
export const Ul = createTag('ul');
export const Ol = createTag('ol');
export const Li = createTag('li');
export const P = createTag('p');
export const A = createTag('a');
export const Button = createTag('button');
export const Img = createTag('img');
export const H1 = createTag('h1');
export const H2 = createTag('h2');
export const H3 = createTag('h3');
export const H4 = createTag('h4');
export const H5 = createTag('h5');
export const H6 = createTag('h6');
export default createTag;
Now you can use the new components like that:
import { Div } from './tailwindComponents';
// ...
<Div className="mt-6 leading-6 font-semibold my-custom-class" style={{ ...someOtherStyles }}>
Hello World
</Div>
Note that, by default, if Tailwind class is not supported, tailwindToObject
is going to throw an error.