Nested syntax with PostCSS for :hover and :focus - css

I'm using TailwindCSS and PostCSS and I have this css code:
.btn {
#apply py-1;
#apply px-4;
#apply border;
#apply rounded;
}
.btn:hover {
#apply bg-white text-black;
}
.btn:focus {
#apply bg-black text-white;
}
Is there a native way in PostCSS (or with a plugin) to write this code like the below?
.btn {
#apply py-1;
#apply px-4;
#apply border;
#apply rounded;
&:hover {
#apply bg-white text-black;
}
&:focus {
#apply bg-black text-white;
}
}

Use postcss-preset-env.
First install, npm install postcss-preset-env --save-dev.
Then enable nesting-rules in your postcss.config.js file,
module.exports = {
plugins: [
"tailwindcss",
[
"postcss-preset-env",
{
stage: 3,
features: {
"nesting-rules": true,
},
},
],
],
};
Here you can find the list of features ID that can be enabled

You could also use postcss-nested plugin.
In your package.json:
{
"dependencies": {
"postcss": "^8.2.9",
"tailwindcss": "^2.0.4",
"postcss-nested": "^5.0.5"
}
}
In your postcss.config.js:
module.exports = {
plugins: [
require('postcss-nested'),
require('tailwindcss'),
]
}

Works too, following the object notation Reference
module.exports = {
plugins: {
'postcss-import': {},
tailwindcss: {},
autoprefixer: {},
'postcss-preset-env': { stage: 2 },
},
}

Related

Svelte + Tailwind: "Semicolon or block is expected"

I have a Svelte project using Tailwind, with this style in a component:
<style global lang="postcss">
input {
#apply block border-black border-2 mb-4 p-2 outline-none focus:border-blue-500;
}
</style>
The error that I'm getting, caused by the focus: class:
Semicolon or block is expected
My postcss.config.cjs file:
import tailwind from 'tailwindcss'
import tailwindConfig from './tailwind.config.cjs'
import autoprefixer from 'autoprefixer'
export default {
plugins: [tailwind(tailwindConfig), autoprefixer]
}
tailwind.config.cjs:
/** #type {import('tailwindcss').Config} */
module.exports = {
theme: {
extend: {},
},
plugins: [],
content: ["./index.html", './src/**/*.{svelte,js,ts}'], // for unused CSS
variants: {
extend: {},
},
darkMode: 'media', // or 'media' or 'class'
}
vite.config.js:
import postcss from './postcss.config.cjs'
import { defineConfig } from 'vite'
import { svelte } from '#sveltejs/vite-plugin-svelte'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [svelte()],
css: {
postcss
}
})

TailwindCSS - Applied styles removed in production

[UPDATE 28-9-2021]
What I also did to eliminate other causes: Update OS packages (Centos 8), rebuilt Apache / NGINX, rebuilt NPM modules, updated and rebuilt TailwindCSS, tried default config files / json files, but all these didn't give me any result :-( I'm really stuck here
[/UPDATE]
Maybe I'm overlooking something here.
I added some basic styling to my style.css for headings:
#tailwind base;
#tailwind components;
#tailwind utilities;
#layer base {
p {
#apply text-theme-gray-lighter pb-4;
}
h1 {
#apply text-3xl py-2;
}
h2 {
#apply text-2xl py-2 border-b mb-2;
}
h3 {
#apply text-xl py-1 font-semibold text-theme-blue;
}
h4 {
#apply text-lg font-semibold;
}
h3.price {
#apply text-theme-gray;
}
.boks-bold {
#apply font-semibold p-4 px-6 text-lg m-4 my-6 mt-2 border shadow-md rounded;
}
}
This file is located at the root of my project.
This is my tailwind.config.js:
module.exports = {
variants: {
extend: {
grayscale: ['hover', 'focus'],
backgroundColor: ['checked'],
borderColor: ['checked'],
borderColor: ['focus-within'],
}
},
darkMode: 'media',
purge: ["*.jsx", "*.js", "*.php"],
plugins: [
// require('daisyui'),
// require('#tailwindcss/forms'),
require('#tailwindcss/custom-forms'),
],
daisyui: {
// styled: false,
// themes: false,
// rtl: false,
},
theme: {
customForms: theme => ({
default: {
'input, textarea, multiselect, checkbox, radio': {
borderdColor: theme('colors.gray.200'),
},
},
}),
container: {
padding: '1rem',
center: true,
},
extend: {
width: {
'full-150': '150vw',
'full-200': '200vw',
},
height: {
'18': '4.5rem',
'40rem': '40rem',
'730px': '730px',
'650px': '650px',
'1191px': '1191px',
'901px': '901px',
'722px': '722px',
'110perc': '110%',
},
maxHeight: {
'110perc': '110%',
},
zIndex: {
'-10': '-10',
},
borderWidth: {
'12': '12px',
},
colors: {
'theme-brown': '#BF8A23',
'theme-yellow': '#FAA71B',
'theme-brown-brighter': '#DDB15B',
'theme-gray': '#333333',
'theme-gray-lighter': '#444444',
'theme-blue': '#547A82',
},
minWidth: {
'0': '0',
'1/4': '25%',
'1/2': '50%',
'3/4': '75%',
'full': '100%',
},
animation: {
'scroll-rtl-slow': 'scrollbrand scroll 40s linear infinite',
},
keyframes: {
scrollbrand: {
'0%': { transform: 'translateX(0)' },
'100%': { transform: 'translateX(calc(-250px * 7))',
}
}
}
}
}
And this is my package.json:
{
"dependencies": {
"#tailwindcss/forms": "^0.3.3",
"#tailwindcss/typography": "^0.4.1",
"autoprefixer": "^10.3.1",
"daisyui": "^1.10.0",
"node-cron": "2.0.3",
"postcss": "^8.3.6",
"postcss-cli": "^8.3.1",
"tailwindcss": "^2.2.6",
"vue-tailwind": "^2.4.2"
},
"scripts": {
"build-css": "tailwindcss build -i style.css -o css/style.css",
"build": "tailwindcss style.css -o css/style.css",
"production": "cross-env NODE_ENV=production tailwindcss css/style.css -o css/style.min.css"
},
"name": "templateh.sceneryworkshop.com",
"version": "1.0.0",
"main": "tailwind.config.js",
"devDependencies": {
"#tailwindcss/custom-forms": "^0.2.1",
"cross-env": "^7.0.3",
"webpack": "^5.52.1",
"webpack-cli": "^4.8.0"
},
"keywords": [],
"author": "",
"license": "ISC",
"description": ""
}
To get the #apply working, I had to add -i to the command:
*"build-css": "tailwindcss build -i style.css -o css/style.css"*
But when I do the same when building production:
"production": "cross-env NODE_ENV=production tailwindcss -i css/style.css -o css/style.min.css"
The file doesn't get purged at all, so it keeps it's total size.
Anyone who has an idea what I'm doing wrong here?
Make sure to add path to your config file in your command:
"production": "cross-env NODE_ENV=production tailwindcss -c ./tailwind.config.js -i css/style.css -o css/style.min.css"

TailwindCSS nesting not working with tailwindcss/nesting or postcss-nesting

postcss.config.js
module.exports = {
plugins: {
"postcss-import": {},
"tailwindcss/nesting": {},
tailwindcss: {},
autoprefixer: {},
},
};
global.css
.form-control {
#apply w-full px-3;
& p {
#apply mb-1;
}
& input:not([type="checkbox"]),
& select,
& option,
& textarea {
#apply placeholder-gray-500 dark:placeholder-gray-text focus:outline-none focus:border-2 focus:border-brand-100 bg-bg-light-100 dark:bg-bg-dark-100 p-1 px-3 h-9 shadow-md;
}
& textarea {
#apply h-24;
}
&.error {
& input {
&:not([type="checkbox"]) {
#apply border-red-600 outline-none border-2;
}
}
}
}
The import plugin is working postcss-import but the nesting plugins aren't working (my styles are rendering) I'm using Nextjs by the way.
What do you want the css to output as? For instance if you want:
.form-control p{
//styles
}
then you should write it as
.form-control {
p {
#apply mb-1;
}
}
without the &.

CSS not getting imported in component

I have the following Test component:
Test.css
.SomeClass {
background-color: blue;
width: 100px;
height: 100px;
}
Test.tsx
import React from 'react';
import './Test.css';
export const Test = () => {
return (
<div className={'SomeClass'}>
hello
</div>
);
};
Relevant section of webpack config:
{
test: /\.css$/,
use: [
{
loader: 'style-loader'
},
{
loader: 'css-loader',
options: {
sourceMap: !isProduction,
modules: {
localIdentName: '[local]',
},
},
}],
},
The problem is that the styles are not applied. On inspection, the div looks like this:
<div class="SomeClass">hello</div>
but there is no "SomeClass" css.
I suspect it is to do with some webpack config. I tried this too: use: ['style-loader', 'css-loader'] instead of the above use array, but no luck.
Edit
This project uses react-jss.

Importing global css custom variables

I'm trying to use webpack with postcss to import a theme-variables.css file that contains my css custom variables.
//theme-variables.css
:root {
--babyBlue: blue;
}
Basically I want any css that imports theme-variable to be able to access these css custom properties and resolve to static values using postcss-css-variables.
//style.css
#import "./theme-variable.css";
div {
display: flex;
color: var(--babyBlue);
}
becomes
//main.css
div {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
color: blue;
}
However I keep getting webpack errors variable --babyBlue is undefined and used without a fallback
main.js ends up looking like this:
:root {
--babyBlue: blue;
}
div {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
color: undefined;
}
Here's my webpack (index.js requires styles.js):
const path = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
entry: { main: "./src/index.js" },
output: {
path: path.resolve(__dirname, "dist"),
filename: "[name].js"
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader
},
{
loader: "css-loader",
options: { importLoaders: 1 }
},
{
loader: "postcss-loader",
options: {
ident: "postcss",
plugins: loader => [
require("postcss-css-variables")(),
require("postcss-cssnext")(),
require("autoprefixer")(),
require("postcss-import")()
]
}
}
]
}
]
},
plugins: [
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: "[name].css",
chunkFilename: "[id].css"
})
]
};
Solution:
The postcss-import plugin has to come first HOWEVER the plugins for Postcss-loader does not go in reverse order like webpack loaders do.
This fixes it:
loader: "postcss-loader",
options: {
ident: "postcss",
plugins: loader => [
require("postcss-import")()
require("postcss-css-variables")(),
require("postcss-cssnext")(),
require("autoprefixer")(),
]
}

Resources