jackardios / css-to-tailwindcss Goto Github PK
View Code? Open in Web Editor NEWConvert CSS to TailwindCSS 3.x
License: MIT License
Convert CSS to TailwindCSS 3.x
License: MIT License
The converter is currently breaking when trying to convert any CSS code that contains @Keyframes:
@keyframes test {
50% {
opacity: 1;
}
}
... normal CSS here
It tries to convert 50%
thinking it's a selector, then it breaks with Unmatched selector: %
For now, it could ignore and don't convert @keyframes
(because it's currently breaking the whole CSS conversion instead)
I’ll elaborate a bit more on the issue soon. Just want to get an issue id first to mention it in the codebase
If Tailwind config contains custom spacing with dashes, classes like marging, padding. etc. don’t fold. Example:
"spacing": {
"spacinga": "var(--spacing-a)",
"spacing-b": "var(--spacing-b)",
}
Input:
margin: var(--spacing-a);
padding: var(--spacing-b);
Ouput:
m-spacinga pt-spacing-b pr-spacing-b pb-spacing-b pl-spacing-b
m-spacinga p-spacing-b
So if we have a width that isnt supported by the config it generates a one off class like tw-w-[250px]
How ever it should be genearating classes of the format tw-w-[250]
.
When applying the provided CSS styles to the converter:
color: #666;
& > td {
text-align: left;
padding: 20px;
vertical-align: top;
border-top: 0;
}
The CSS to Tailwind CSS converter only outputs text-[#666]
for the color property, but doesn't generate classes for child <td>
like text-align, padding, vertical-align, and border-top. Additionally, it does not generate a class for the td selector with the arbitrary variant.
https://tailwindcss.com/docs/hover-focus-and-other-states#using-arbitrary-variants
https://stackoverflow.com/a/72683383
I know that this is not the recommended way of doing things in Tailwind, but I am trying to create a converter from styled-components to Tailwind and I need this feature to ensure I can migrate many features in the codebase safely. For example:
// A table body with child td selector
export const Tbody = styled.tbody`
color: #666;
& > td {
text-align: left;
padding: 20px;
vertical-align: top;
border-top: 0;
}
`;
Gets converted into:
// A table body with child td selector
export const Tbody = React.forwardRef((props: React.ComponentPropsWithoutRef<"tbody">, ref: React.ComponentProps<"tbody">["ref"]) => {
return(
<tbody className="text-[#666]" ref={ref} {...props}>
{props.children}
</tbody>
);
});
I expect the CSS to Tailwind CSS converter to generate appropriate classes for all the CSS properties provided, not just for the color property. For example, it should generate classes like [&>td]:text-left
for the child td component:
text-[#666]
and does not contain classes for arbitary variants like [&>td]:text-left
If a selector is only declared inside a media query, even if the media query is a valid Tailwind screen, such as lg
, it will keep the media query as unconverted.
Example code:
h3.jsx-2946570823 {
font-size: 1em;
}
@media (min-width: 1024px) {
h3.jsx-2946570823 {
font-size: 1.5em;
}
}
returns correctly:
h3.jsx-2946570823 {
@apply text-[1em] lg:text-[1.5em];
}
but
@media (min-width: 1024px) {
h3.jsx-2946570823 {
font-size: 1.5em;
}
}
returns
@media (min-width: 1024px) {
h3.jsx-2946570823 {
@apply text-[1.5em];
}
}
If the screen exists, it should wrap everything outside @media queries, like a normal selector:
h3.jsx-2946570823 {
@apply lg:text-[1.5em];
}
So when i put in a string of css where we have a rule set: with a media block, selector and some styles, the outputted tailwind doesn't include the media block. However when i include the same css, but additionally the same selector outside the media block, the outputted tailwind will include the media block.
E.G
const input = `
.selector {
display: block;
}
@media (min-width: 768px) {
.selector {
display: flex;
}
}
// Output
[
'block',
'md: flex'
]
const input2 = `
@media (min-width: 768px) {
.selector {
display: flex;
}
}
// Output 2
[
'flex'
]
As you can see, when i don't include that initial declaration block outside the media block, the media screen size gets ignored and the output is wrong.
You can also refer to another example in the screenshot i took:
What should happen is that the input shouldn't need that initial declaration block. I feel like if we don't have that initial block outdside the media, the block inside the media query should still take the screen width into account.
E.G
const input = `
@media (min-width: 768px) {
.selector {
display: flex;
}
}
// Output
[
'md: flex'
]
eg.
const style = {
width: '100px',
height: '30px',
backgroundColor: '#009eeb'
}
// to tailwindcss ^3.0
> w-[100px] h-[30px] bg-[#009eeb]
In [email protected]
, background: red
converts to ""
, while background-color: red
converts to "bg-[red]"
.
It’d be great if CSS like background: red
could be mapped to a tailwind class too. I understand that the value of background
shorthand can also contain image URL and its placement. It ca be hard to parse, but even supporting simple cases would be great. In practice, a lot of CSS I have seen is using background: color
shorthand.
[email protected]
PS: Great lib @Jackardios! Thanks for working on it 🙌
Setting multiple selectors in the same CSS rule returns an unexpected result: For example:
import { TailwindConverter } from 'css-to-tailwindcss';
import postcssNested from "postcss-nested";
const converter = new TailwindConverter({
remInPx: 16, // set null if you don't want to convert rem to pixels
postCSSPlugins: [postcssNested], // add any postcss plugins to this array
tailwindConfig: {
// your tailwind config here
content: [],
theme: {
extend: {
colors: {},
},
},
},
});
const inputCSS = `
.test{
color:red;
&:hover, &:focus{
color: blue;
}
}`;
converter.convertCSS(inputCSS).then(({ convertedRoot, nodes }) => {
console.log(convertedRoot.toString());
});
Obtained result:
.test {
@apply text-[red];
}
.test:hover,
.test:focus {
@apply text-[blue];
}
Expected result:
.test {
@apply text-[red] focus:text-[blue] hover:text-[blue];
}
Given config:
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [],
theme: {
extend: {
screens: {
'custom-screen-1': {
raw: 'screen and (min-width: 0px)',
},
}
},
},
plugins: [],
}
And CSS:
h2 {
font-size: 45px;
}
@media screen and (min-width: 0px) {
h2 {
font-size: 32px;
}
}
The output is:
(...)
h2 {
@apply text-[45px];
}
@media screen and (min-width: 0px) {
h2 {
@apply text-[32px];
}
}
Shouldn't it be:
h2 {
@apply text-[45px] custom-screen-1:text-[32px];
}
?
border-radius: 4px; --> rounded
border-radius: 4px !important; --> !rounded
Did you make it by hand?
It'd be nice to have a setting to keep the custom styles (unconverted) as regular CSS instead of using @apply
.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.