How to get Tailwind.css working with Gatsby.js? - css

Has anyone managed to get Tailwind.css working with Gatsby.js?
Configuring postCSS plugins with Gatsby is a bit tricky... If anyone has managed to get Tailwind up and running with Gatsby, I'd love to know how!

I managed to get this working (including hot reloading) thanks to this post.
Basically I had to install postcss and autoprefixer additionally:
npm install autoprefixer postcss-cli
I added a postcss.config.js to the root of my Gatsby site folder with this content (tailwind.js is my Tailwind config - yours might be named differently):
const tailwindcss = require('tailwindcss');
module.exports = {
plugins: [
tailwindcss('./tailwind.js'),
require('autoprefixer'),
],
};
Then I added a CSS watch and build script to my package.json, and included these scripts in my default develop and build scripts:
"scripts": {
"build:css": "postcss src/layouts/index.css -o src/layouts/generated.css",
"watch:css": "postcss src/layouts/index.css -o src/layouts/generated.css -w",
"build": "npm run build:css && gatsby build",
"develop": "npm run watch:css & gatsby develop",
...
}
(Please note the input (index.css) and output (generated.css) filenames and locations for my css are specific to my project. Feel free to use your own convention.)
Let me know, if this works for you.

As a supplement to morgler's answer, here is a similar solution I ended up with (which includes Sass and PurgeCSS).
I went with a CLI solution because gatsby-plugin-postcss-sass currently runs PostCSS before Sass (which breaks Tailwind), and Gatsby's PostCSS plugins are a bit difficult to configure via Webpack at the moment.
I included Sass so I can break main.sass into more manageable partials, and added PurgeCSS so I can remove any unused Tailwinds classes in production. I've found that PurgeCSS is more effective than PurifyCSS, which is why I opted not to use gatsby-plugin-purify-css.
To begin, create a src/styles folder with the following structure (feel free to customize this for your project and adapt the settings below accordingly):
src/
styles/
builds/
after-postcss/
main.css
after-purgecss/
main.css
after-sass/
main.css
// other subfolders for sass partials...
main.sass
Install the necessary dependencies:
npm i node-sass-chokidar postcss-cli purgecss
Add the following to gatsby-node.js (to disable Gatsby's default PostCSS plugins):
const ExtractTextPlugin = require('extract-text-webpack-plugin')
exports.modifyWebpackConfig = ({ config, stage }) => {
switch (stage) {
case 'develop':
// Remove postcss from Gatsby's dev process:
config.removeLoader(`css`)
config.loader(`css`, {
test: /\.css$/,
loaders: [`style`, `css`]
})
break
case 'build-css':
// Remove postcss from Gatsby's build process:
config.removeLoader(`css`)
config.loader(`css`, {
test: /after-purgecss\/main\.css/,
loader: ExtractTextPlugin.extract([`css?minimize`])
})
break
}
return config
}
Add a postcss.config.js file to the project root:
const tailwind = require('tailwindcss')
const cssnext = require('postcss-cssnext')
module.exports = {
plugins: [
// your file's name or path may differ:
tailwind('./src/styles/tailwind.config.js'),
cssnext()
// add any other postcss plugins you like...
]
}
Add the following scripts to package.json:
"scripts": {
"watch:sass": "node-sass-chokidar --source-map true src/styles/main.sass -o src/styles/builds/after-sass -w",
"watch:postcss": "postcss src/styles/builds/after-sass/main.css -o src/styles/builds/after-postcss/main.css -w",
"watch:styles": "npm run watch:sass & npm run watch:postcss",
"build:sass": "node-sass-chokidar src/styles/main.sass -o src/styles/builds/after-sass",
"build:postcss": "postcss src/styles/builds/after-sass/main.css -o src/styles/builds/after-postcss/main.css",
"build:purgecss":
"purgecss --css src/styles/builds/after-postcss/main.css --con public/index.html src/**/*.js -o src/styles/builds/after-purgecss",
"build:styles": "npm run build:sass && npm run build:postcss && npm run build:purgecss",
"develop": "gatsby develop & npm run watch:styles",
"build": "npm run build:styles && gatsby build"
// ...
},
In development, run npm run develop instead of gatsby develop. The watch: scripts will run Sass + PostCSS (in that order) whenever a change is made to main.sass or any of its imports.
To build the site, run npm run build instead of gatsby build. The build: scripts will run Sass + PostCSS (without the watch tasks) + PurgeCSS (in that order).
Add the following to layouts/index.js to import the after-postcss version of main.css during development and the after-purgecss version during production:
switch (process.env.NODE_ENV) {
case `development`:
require('../styles/builds/after-postcss/main.css')
break
case `production`:
require('../styles/builds/after-purgecss/main.css')
break
}
Hope that helps someone! If anyone knows how to convert this into a Webpack equivalent that works with Gatsby, please feel free to post it here.

I recently added it on top of the Gatsby starter default and wrote a detailed step by step guide.
https://www.michaelfasani.com/2020/installing-tailwind-css-on-top-of-the-gatsby-starter-default/

That's my setup and is working perfectly fine with Gatsby:
tailwind.config.js
module.exports = {
mode: "jit",
purge: [
"./src/pages/**/*.{js,ts,jsx,tsx}",
"./src/components/**/*.{js,ts,jsx,tsx}",
],
package.json
"scripts": {
"develop": "gatsby develop",
"start": "gatsby develop",
"build": "gatsby build",
"serve": "gatsby serve",
"clean": "gatsby clean",
"tw:build": "tailwindcss build ./src/styles/global.css -o ./public/styles/global.css",
"tw:prod": "cross-env NODE_ENV=production postcss build ./src/styles/global.css -o ./public/styles/global.css",
"tw:watch": "onchange \"tailwind.config.js\" \"src/**/*.css\" -- npm run tw:build"
},
You can also use cssnano it's an awsome extension for purging tailwind css
postcss.config.js
const cssnano = require("cssnano");
module.exports = {
plugins: [
require("tailwindcss"),
cssnano({
preset: "default",
}),
require("autoprefixer"),
],
};
Also the devDependencies that are needed for the latest Tailwind version are these:
package.json devDependencies
"devDependencies": {
"autoprefixer": "^10.3.6",
"gatsby-plugin-postcss": "^4.14.0",
"postcss": "^8.3.9",
"postcss-cli": "^9.0.1",
"tailwindcss": "^2.2.17"
}
}
Also make sure to include these on top of the global.css file:
#tailwind base;
#tailwind components;
#tailwind utilities;

Related

Is it normal that tailwind.config.js, vite.config.js are in root folder of Laravel 9?

Fresh install of Vite and Tailwind results in tailwind.config.js, postcss.config.js and vite.config.js in the root folder of Laravel 9.
Is this expected? I want to organize these file into the existing resources/js folder. Where do I update references to these files to avoid breaking things?
Yes this is the default behaviour.
You can change the location of your vite.config.js to any location you want by using the --config flag in your package.json script:
"scripts": {
"dev": "vite --config custom/location/vite.config.js",
"build": "vite build --config custom/location/vite.config.js"
},
In the vite.config.js you can change the tailwind.config.js and remove the need for your postcss.config.js entirely like this:
...
css: {
postcss: {
plugins: [
require("tailwindcss")({
config: "custom/location/tailwind.config.js",
}),
require("autoprefixer"),
],
},
},

Tailwind will not purge

I am trying to get tailwind to purge CSS on my files, but I can't seem to get it working.
To provide some context, I have a public folder that contains a CSS folder and a views folder. I am trying to purge the single ejs file within the views folder.
Here is my tailwind.config.js
module.exports = {
purge: {
enabled: true,
content: ['./public/**/*.ejs']
},
theme: {},
variants: {},
plugins: [],
}
Here is my postcss.config.js
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
}
}
Here is my script I'm running from my package.json
"tw-prod": "tailwind build public/css/tailwind.css -o public/css/style.css"
I have also tried the following, without any luck
"tw-prod": "postcss public/css/tailwind.css -o public/css/style.css"
And finally here is some code from my app.js which may help diagnose my problem
app.use(express.static("public"));
app.set("view engine", "ejs");
app.set('views', path.join(__dirname, '/public/views'));
Each time I run the build script, the size of the stylesheet remains the same at 3.81mb. Can anyone tell me what I'm doing wrong here, please?
Did you try running the script with NODE_ENV=production?
like
NODE_ENV=production npx tailwindcss -i ./src/tailwind.css -o ./dist/tailwind.css
EDIT:
Instead of running
"tw-prod": "tailwind build public/css/tailwind.css -o public/css/style.css"
run this
"tw-prod": "NODE_ENV=production tailwind build public/css/tailwind.css -o public/css/style.css"
Tailwind requires the NODE_ENV to be set for the purge function to kick in and do its job.
Read more about this here
PS: BTS postcss file now comes configured by default that I guess takes care of this purging functionality

How to #import Compass in .SASS file within Simple React App

I just started a React App using the Facebook tutorial here:
https://github.com/facebook/create-react-app/blob/master/packages/react-scripts/template/README.md#adding-a-css-preprocessor-sass-less-etc
I wanted to get this code snippet working in my react app:
https://codepen.io/saransh/pen/BKJun
I npm installed these modules: node-sass-chokidar,react-compass, compass-importer, sass-resources-loader
I put the CSS from the Code pen into a .sass file within my project like so:
Here is the first snippet of the SASS code in Starr.sass
#import compass
// n is number of stars required
#function multiple-box-shadow ($n)
$value: '#{random(2000)}px #{random(2000)}px #FFF'
#for $i from 2 through $n
$value: '#{$value} , #{random(2000)}px #{random(2000)}px #FFF'
#return unquote($value)
$shadows-small: multiple-box-shadow(700)
$shadows-medium: multiple-box-shadow(200)
$shadows-big: multiple-box-shadow(100)
html
height: 100%
But this seems to be the wrong strategy because I get this error when I do "npm run watch-css":
"File to import not found or unreadable: compass"
I tried to find online resources for steps to take to get compass to import, and they all talk about different tools: Babel, Webpack, etc, but I am relatively new and do not know which steps to take next.
What are the concrete steps I have to take to go from npm create-react-app to being able to do #import in .SASS files to be used by app? Here is my current package.json file:
{
"name": "my-app",
"version": "0.1.0",
"private": true,
"dependencies": {
"compass": "^0.1.1",
"node-sass-chokidar": "0.0.3",
"react": "^16.2.0",
"react-compass": "^0.1.0",
"react-dom": "^16.2.0",
"react-scripts": "1.1.1",
"sass-resources-loader": "^1.3.2"
},
"scripts": {
"build-css": "node-sass-chokidar src/ -o src/",
"watch-css": "npm run build-css && node-sass-chokidar src/ -o src/ --watch --recursive",
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
},
"devDependencies": {
"compass-importer": "^0.4.1",
"node-sass": "^4.7.2",
"sass-loader": "^6.0.6"
}
I looked at some stackoverflow questions, but did not find what my next logical step would be. Here is one:
How to configure webpack to use compass in my project

React & Next.js - Added a SCSS parser and tried adding CSS to webpack module config, but it doesn't live-reload, why?

In my package.json I've changed a few things:
"scripts": {
"build-css": "node-sass-chokidar ./static/style.scss ./static/style.css",
"watch-css": "npm run build-css && node-sass-chokidar ./static/style.scss ./static/style.css --watch --recursive",
"dev": "npm-run-all -p watch-css next",
"next": "next",
"build": "next build",
"start": "next start"
},
Because I much prefer a single SASS file containing all styles, until a solution is found to make a require('./style.scss'); work server-side and client-side.
The stylesheet is parsed and output as a single CSS-file while developing, just fine. I just need to reload the entire page to see my changes. That's a little bit of a drag, of course.
So I created a next.config.js file and added this:
const path = require('path');
const glob = require('glob');
const node_modules_dir = path.resolve(__dirname, 'node_modules');
module.exports = {
webpack: (config, { dev }) => {
config.module.rules.push(
{
test: /\.(css|scss)/,
exclude: [node_modules_dir],
loaders: [
'style-loader',
'css-loader',
'postcss-loader'
]
}
);
return config
}
};
And next.js is running in my terminal just fine, and the SCSS-file is parsed into a CSS-file just fine, too. Just, no client-side live-reload. I was expecting adding this to the config file would be sufficient to live-reload a CSS-file.
In my components/Page I've added this line:
<Head>
<title>{title}</title>
<link rel="stylesheet" type="text/css" href="/static/style.css" />
</Head>
But I'm not too familiar with hot-reload/live-reload inner workings.
What am I doing wrong?

How to use LESS preprocessor in React Create-React-APP

I want to use LESS preprocessor in my create-react-app.
React Code
ReactDOM.render(
<form>
<input type="email" data-info="Enter Email" pattern="/\S+#\S+\.\S+/" required title="Please enter value" required="required"/>
<input type="submit"/>
</form>
,document.getElementById('root'))
index.less
body{
background: red;
}
Here is the way I am doing it
You should use node-sass-chokidar npm package:
npm install node-sass-chokidar --save-dev
Then add the following to your npm scripts in package.json :
"build-css": "node-sass-chokidar src/ -o src/",
"watch-css": "npm run build-css && node-sass-chokidar src/ -o src/ --watch --recursive"
The watcher will find every Sass file in src subdirectories, and create a corresponding CSS file next to it.
Remember to remove all css files from the source control and add src/**/*.css to your .gitignore.
Finally you might want to run watch-css automatically with npm start, and run build-css as a part of npm run build . For it, install the following npm package in order to be able to execute two scripts sequentially:
npm install --save-dev npm-run-all
Then change your npm start and build scripts in package.json file to the following:
"scripts": {
"build-css": "node-sass-chokidar src/ -o src/",
"watch-css": "npm run build-css && node-sass-chokidar src/ -o src/ --watch --recursive"
"start-js": "react-scripts start",
"start": "npm-run-all -p watch-css start-js",
"build": "npm run build-css && react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
}
See this link for further information: https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#adding-a-css-preprocessor-sass-less-etc
With create-react-app 2 you can use "Create React App Configuration Override" (craco) and craco-less to configure this:
set up craco:
npm install #craco/craco
in package.json:
"scripts": {
"start": "craco start",
"build": "craco build",
"test": "craco test",
"eject": "craco eject"
},
setting up craco for less:
npm install craco-less
create new file: craco.config.js
module.exports = {
plugins: [
{
plugin: require('craco-less'),
},
],
};
The simplest and painless way to add less support with reactjs app by far is to use custom-react-scripts with create-react-app for LESS/SASS/decorators support :
Install: npm install -g create-react-app custom-react-scripts
Create app:
create-react-app <app_name> —scripts-version custom-react-scripts
Example less file:
.myDiv{ background: gray; }
and then in your component:
import lessStyles from '<less file path>';
<div style={lessStyles.myDiv}>
...
</div>
or the regular way:
import '<less file path>';
<div className="myDiv">
...
</div>
For reference:
https://github.com/kitze/custom-react-scripts
https://github.com/fawaz-ahmed/fawaz-ahmed.github.io
I've had a similar problem.
Just include the following lines into your webpack configuration rules section (taken from the official less loader examples):
{
test: /\.less$/,
use: [{
loader: 'style-loader' // creates style nodes from JS strings
}, {
loader: 'css-loader' // translates CSS into CommonJS
}, {
loader: 'less-loader' // compiles Less to CSS
}]
},
Of course, you need to add respective packages into your package.json
And then in you code simply import needed styles
import './style.less'
Using such approach you won't introduce an extra step of creating additional css files.

Resources