I have enabled CSS modules within webpack.config in my React application so that I can locally scope CSS files to individual components. I'm also trying to use the TabView component from PrimeReact. When I do so the themes from PrimeReact are not applied. If I create a separate project and do not enable CSS modules the themes apply correctly.
How can I use PrimeReact themes and enable CSS modules?
I've tested moving the content located in Tabs.js directly into App.js and get the same results.
CSS Modules Enabled
Webpack.config
require.resolve('style-loader'),
{
loader: require.resolve('css-loader'),
options: {
importLoaders: 1,
modules: true,
localIdentName: '[name]__[local]__[hash_base64:5]'
},
},
App.js
import React, { Component } from 'react';
import classes from './App.css';
import Tabs from './UI/Tabs';
class App extends Component {
render() {
return (
<Tabs/>
);
}
}
export default App;
Tabs.js
import React from 'react';
import {TabView, TabPanel} from 'primereact/components/tabview/TabView';
import classes from 'primereact/resources/primereact.css';
import theme from 'primereact/resources/themes/cupertino/theme.css';
const Tabs = () => (
<TabView>
<TabPanel header="Tab One">
This is content for Tab One.
</TabPanel>
<TabPanel header="Tab Two">
This is content for Tab Two.
</TabPanel>
</TabView>
);
export default Tabs;
Default React Global CSS Scoping
CSS Modules Enabled (Local Component Scoping)
I was able to use CSS modules and selectively apply global scoping to PrimeReact's themes by modifying webpack.config as follows below.
Original:
{
test: /\.css$/,
use: [
require.resolve('style-loader'),
{
loader: require.resolve('css-loader'),
options: {
importLoaders: 1,
modules: true,
localIdentName: '[name]__[local]__[hash:base64:5]'
},
},
{
loader: require.resolve('postcss-loader'),
options: {
// Necessary for external CSS imports to work
// https://github.com/facebookincubator/create-react-app/issues/2677
ident: 'postcss',
plugins: () => [
require('postcss-flexbugs-fixes'),
autoprefixer({
browsers: [
'>1%',
'last 4 versions',
'Firefox ESR',
'not ie < 9', // React doesn't support IE8 anyway
],
flexbox: 'no-2009',
}),
],
},
},
],
},
Modified:
{
test: /\.css$/,
//Exclude 3rd party css that needs to be scoped globally from using
//css-loader with modules enabled
exclude: [
path.resolve('node_modules/primereact/resources/primereact.css'),
path.resolve('node_modules/primereact/resources/themes/cupertino/theme.css'),
],
use: [
require.resolve('style-loader'),
{
loader: require.resolve('css-loader'),
options: {
importLoaders: 1,
modules: true,
localIdentName: '[name]__[local]__[hash_base64:5]'
},
},
{
loader: require.resolve('postcss-loader'),
options: {
// Necessary for external CSS imports to work
// https://github.com/facebookincubator/create-react-app/issues/2677
ident: 'postcss',
plugins: () => [
require('postcss-flexbugs-fixes'),
autoprefixer({
browsers: [
'>1%',
'last 4 versions',
'Firefox ESR',
'not ie < 9', // React doesn't support IE8 anyway
],
flexbox: 'no-2009',
}),
],
},
},
],
},
//Additional css-loader configuration
{
test: /\.css$/,
//Inlcude only 3rd party css that needs to be scoped globally to use
//css-loader with modules disabled
include: [
path.resolve('node_modules/primereact/resources/primereact.css'),
path.resolve('node_modules/primereact/resources/themes/cupertino/theme.css'),
],
use: [
require.resolve('style-loader'),
{
loader: require.resolve('css-loader'),
options: {
importLoaders: 1
},
},
{
loader: require.resolve('postcss-loader'),
options: {
// Necessary for external CSS imports to work
// https://github.com/facebookincubator/create-react-app/issues/2677
ident: 'postcss',
plugins: () => [
require('postcss-flexbugs-fixes'),
autoprefixer({
browsers: [
'>1%',
'last 4 versions',
'Firefox ESR',
'not ie < 9', // React doesn't support IE8 anyway
],
flexbox: 'no-2009',
}),
],
},
},
],
},
Use the below two npm commands to install the CSS and Style loader:
npm install style-loader - You can add the Version of the loaded if required
npm install css-loader
You are not required to change anything else.
Related
I'm having trouble getting storybook to play nice with css modules within my Gatsby project. I'm able to render the button component but it does not add any of my styling. On inspection of the element, I'm only getting undefined undefined from the following code.
button.jsx
import React from "react"
import * as css from "./style.module.css"
const Button = ({ variant = "button", type, value = null }) => {
const baseOfVariant = () => {
if (variant === "input") {
return (
<input
type={type}
value={value}
className={`${css.button} ${css.clear_button}`}
/>
)
}
return (
<button type={type} className={`${css.button} ${css.submit_button}`}>
{value}
</button>
)
}
return baseOfVariant()
}
export default Button
button.stories.jsx
import React from "react"
import Button from "./button"
export default {
title: "Button",
component: Button,
}
export const Template = args => <Button {...args} />
export const ButtonRegular = Template.bind({})
ButtonRegular.args = {
variant: "button",
value: "Click Me",
type: "submit",
}
main.js
module.exports = {
stories: ["../src/**/*.stories.mdx", "../src/**/*.stories.#(js|jsx|ts|tsx)"],
addons: ["#storybook/addon-links", "#storybook/addon-essentials"],
core: {
builder: "webpack5",
},
}
Storybook stuff in my devDeps
"devDependencies": {
"#babel/core": "^7.14.6",
"#babel/polyfill": "^7.12.1",
"#storybook/addon-actions": "^6.4.0-alpha.2",
"#storybook/addon-essentials": "^6.4.0-alpha.2",
"#storybook/addon-links": "^6.4.0-alpha.2",
"#storybook/addon-viewport": "^6.4.0-alpha.2",
"#storybook/builder-webpack5": "^6.4.0-alpha.2",
"#storybook/manager-webpack5": "^6.4.0-alpha.2",
"#storybook/react": "^6.4.0-alpha.2",
"babel-loader": "^8.2.2",
"prettier": "2.2.1",
"resize-observer-polyfill": "^1.5.1"
}
Gatsby needs to import css modules with the following synthax:
import * as css from "./style.module.css"
Where Storybook recognizes only this synthax:
import css from "./style.module.css"
This is due to the fact that Gatsby and Storybook don't use the same import convention. Fortunately, you can configure Storybook css module import mechanism via .storybook/main.js file.
const path = require("path")
module.exports = {
// You will want to change this to wherever your Stories will live
stories: ["../src/**/*.stories.mdx", "../src/**/*.stories.#(js|jsx|ts|tsx)"],
addons: ["#storybook/addon-links", "#storybook/addon-essentials"],
core: {
builder: "webpack5",
},
webpackFinal: async config => {
// Prevent webpack from using Storybook CSS rules to process CSS modules
config.module.rules.find(
rule => rule.test.toString() === "/\\.css$/"
).exclude = /\.module\.css$/
// Tell webpack what to do with CSS modules
config.module.rules.push({
test: /\.module\.css$/,
include: path.resolve(__dirname, "../src"),
use: [
{
loader: "style-loader",
options: {
modules: {
namedExport: true,
},
},
},
{
loader: "css-loader",
options: {
importLoaders: 1,
modules: {
namedExport: true,
},
},
},
],
})
// Transpile Gatsby module because Gatsby includes un-transpiled ES6 code.
config.module.rules[0].exclude = [/node_modules\/(?!(gatsby)\/)/]
// use babel-plugin-remove-graphql-queries to remove static queries from components when rendering in storybook
config.module.rules[0].use[0].options.plugins.push(
require.resolve("babel-plugin-remove-graphql-queries")
)
return config
},
}
With the above configuration, Storybook now accept this import synthax and button.jsx is correctly styled.
import * as css from "./style.module.css"
If any one is looking for sass/scss related fix
import * as style from "./style.module.scss"
Where Storybook recognizes only this synthax:
your .storybook/main.js file.
const path = require("path");
module.exports = {
stories: ["../src/**/*.stories.{js,mdx}"],
addons: [
"#storybook/addon-docs",
"#storybook/addon-actions",
"#storybook/addon-controls",
"#storybook/addon-a11y",
"#storybook/addon-viewport",
],
// https://gist.github.com/shilman/8856ea1786dcd247139b47b270912324
core: {
builder: "webpack5",
},
webpackFinal: async config => {
// https://www.gatsbyjs.com/docs/how-to/testing/visual-testing-with-storybook/
config.module.rules.push({
test: /\.(js)$/,
use: [
{
loader: require.resolve("babel-loader"),
options: {
presets: [
// use #babel/preset-react for JSX and env (instead of staged presets)
require.resolve("#babel/preset-react"),
require.resolve("#babel/preset-env"),
],
plugins: [
// use #babel/plugin-proposal-class-properties for class arrow functions
require.resolve("#babel/plugin-proposal-class-properties"),
// use babel-plugin-remove-graphql-queries to remove static queries from components when rendering in storybook
require.resolve("babel-plugin-remove-graphql-queries"),
// use babel-plugin-react-docgen to ensure PropTables still appear
require.resolve("babel-plugin-react-docgen"),
],
},
},
],
exclude: [/node_modules\/(?!(gatsby)\/)/],
});
config.module.rules.push({
test: /\.s[ac]ss$/i,
oneOf: [
// module.scss files (e.g component styles.module.scss)
// https://webpack.js.org/loaders/style-loader/#modules
{
test: /\.module\.s?css$/,
use: [
// Add exports of a module as style to DOM
{
loader: "style-loader",
options: {
esModule: true,
modules: {
namedExport: true,
},
},
},
// Loads CSS file with resolved imports and returns CSS code
{
loader: "css-loader",
options: {
esModule: true,
modules: {
namedExport: true,
},
},
},
// Loads and compiles a SASS/SCSS file
{
loader: "sass-loader",
// only if you are using additional global variable
options: {
additionalData: "#import 'src/styles/global.scss';",
sassOptions: {
includePaths: ["src/styles"],
},
},
},
],
},
// scss files that are not modules (e.g. custom.scss)
{
use: [
// Add exports of a module as style to DOM
"style-loader",
// Loads CSS file with resolved imports and returns CSS code
"css-loader",
// Loads and compiles a SASS/SCSS file
{
loader: "sass-loader",
// only if you are using additional global variable
options: {
additionalData: "#import 'src/styles/global.scss';",
sassOptions: {
includePaths: ["src/styles"],
},
},
},
],
},
],
});
return config;
},
};
With the above configuration, Storybook now accept this import synthax and button.jsx is correctly styled.
import * as styles from "./style.module.scss"
I am trying to use CSS Modules for CSS styling of my ReactJs project, for this I applied ant design documentation (see here: https://pro.ant.design/docs/style), however unfortunately it doesn't work.
The problem is that I want to override the component style of ant Button and it does not get the style.
Below there is a short sample of my code:
CSS class: in MyContainer.less file:
.antButton{
:global {
.ant-btn-primary {
background-color: rgb(215, 226, 233);
border-color: #848586;
font-size: 7pt;
color: red !important;
}
}
}
code:
import React from 'react';
import { Button } from 'antd';
import 'antd/dist/antd.less';
import styles from './MyContainer.less';
const MyContainer= () => {
return (
<Button type="primary" size="small" className={styles.antButton} >Download</Button>
);
};
export default MyContainer;
I'm using Ant design (Version 4.3.0) in react (Version 16.13.1 ) with Webpack (Version 4.42.0).I also installed less-loader (Version 7.3.0) and babel-plugin-import (Version 1.13.3).
I don't know if there is any specific config of the Webpack that I am missing or the problem is somewhere else?
Finally I could handle my problem with antd, when you use css modules you have to add extra config for antd styles to work, I've found my solution in this web site:
https://www.programmersought.com/article/3690902311/ As described there if you add these configs in these order in your Webpack.config in Rule section it will work with Css modules and overriding less styles of antd components.
{
test: /\.less$/,
include: [/src/],
use: [
require.resolve('style-loader'),
{
loader: require.resolve('css-loader'),
options: {
modules: {
localIdentName: "[name]__[local]___[hash:base64:5]",
},
sourceMap: true
},
},
{
loader: require.resolve('less-loader'), // compiles Less to CSS
options: { lessOptions:{javascriptEnabled: true }}
},
],
},
{
test: /\.css$/,
exclude: /node_modules|antd\.css/,
use: [
require.resolve('style-loader'),
{
loader: require.resolve('css-loader'),
options: {
importLoaders: 1,
// change
modules: {
localIdentName: "[name]__[local]___[hash:base64:5]",
},
},
},
{
loader: require.resolve('postcss-loader'),
options: {
ident: 'postcss',
plugins: () => [
require('postcss-flexbugs-fixes'),
autoprefixer({
browsers: [
'>1%',
'last 4 versions',
'Firefox ESR',
'not ie < 9', // React doesn't support IE8 anyway
],
flexbox: 'no-2009',
}),
],
},
},
],
},
{
test: /\.css$/,
include: /node_modules|antd\.css/,
use: [
require.resolve('style-loader'),
{
loader: require.resolve('css-loader'),
options: {
importLoaders: 1,
// change
// modules: true, // new support for css modules
// localIndetName: '[name]__[local]__[hash:base64:5]', //
},
},
{
loader: require.resolve('postcss-loader'),
options: {
ident: 'postcss',
plugins: () => [
require('postcss-flexbugs-fixes'),
autoprefixer({
browsers: [
'>1%',
'last 4 versions',
'Firefox ESR',
'not ie < 9', // React doesn't support IE8 anyway
],
flexbox: 'no-2009',
}),
],
},
},
],
},
Also you need to add babel import in your package.json:
"babel": {
"presets": [
"#babel/preset-env",
"#babel/preset-react",
"#babel/preset-typescript"
],
"plugins": [
[
"import",
{
"libraryName": "antd",
"libraryDirectory": "lib",
"style": true
}
]
]
},
and you have to set style to the wrapper div of antd Components in this way:
import React from 'react';
import { Button } from 'antd';
//import 'antd/dist/antd.less'; you don't need this line when add babel.
import styles from './MyContainer.less';
const MyContainer= () => {
return (
<div className={styles.antButton}>
<Button type="primary" size="small" >Download</Button>
</div >
);
};
export default MyContainer;
I wish it help
I'm implementing video.js in a React web-app.
Using
import video.js/dist/video-js.min.css
it doesn't load all the css classes. Whilst if I use the following form it does.
require('!style-loader!css-loader!video.js/dist/video-js.min.css');
The latter form though triggers a import/no-webpack-loader-syntax eslint error.
How can I configure webpack in order for it to load the video-js.min.css file?
My webpack css loader config looks like this right now:
{
test: /\.css$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
modules: true,
importLoaders: 1,
localIdentName: '[name]__[local]___[hash:base64:5]',
sourceMap: true
}
},
{
loader: 'postcss-loader',
options: {
ident: 'postcss',
plugins: () => [
autoprefixer()
],
sourceMap: true
}
}
]
}
In a new project, I need to add scss/css modules to a typescript/react app.
I added "typings-for-css-modules-loader" to the project and webpack.config.dev.js
like so : (here is the entire webpack.config.dev.js)
{
test: /\.css$/,
use: [
require.resolve('style-loader'),
{
loader: require.resolve('typings-for-css-modules-loader'),
options: {
importLoaders: 1,
modules: true
},
},
{
loader: require.resolve('postcss-loader'),
options: {
// Necessary for external CSS imports to work
// https://github.com/facebookincubator/create-react-app/issues/2677
ident: 'postcss',
plugins: () => [
require('postcss-flexbugs-fixes'),
autoprefixer({
browsers: [
'>1%',
'last 4 versions',
'Firefox ESR',
'not ie < 9', // React doesn't support IE8 anyway
],
flexbox: 'no-2009',
}),
],
},
},
],
},{
test: /\.scss$/,
use: [
require.resolve('style-loader'),
require.resolve('sass-loader'),
{
loader: require.resolve('typings-for-css-modules-loader'),
options: {
namedexport: true,
camelcase: true,
modules: true
}
}
]
},
When i add a test.scss file to my project, the compilation successfully creates a test.scss.d.ts which contains :
export interface ITestScss {
'toto': string;
}
export const locals: ITestScss;
When i try to import this css in my project like so :
import styles from './scss/test.scss';
I get this error :
Module '"/home/cyprien/projets/test/typescript-sass-modules-boilerplate/src/scss/test.scss"' has no default export.
Finally, In the browser, i get this error :
Failed to compile
./src/scss/test.scss
Module build failed:
.toto{
^
Invalid CSS after "e": expected 1 selector or at-rule, was "exports = module.ex"
in /home/cyprien/projets/test/typescript-sass-modules-boilerplate/src/scss/test.scss (line 1, column 1)
You need to use the plugin mini-css-extract-plugin. Here is an example of configuration with TypeScript and SASS SCSS (but without CSS modules neither PostCSS):
// webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin")
module.exports = {
mode: "development",
devtool: "source-map",
resolve: {
extensions: [".ts", ".js"]
},
module: {
rules: [
{
test: /\.ts$/,
exclude: /node_modules/,
use: {
loader: "ts-loader"
}
},
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
"css-loader",
"sass-loader"
]
}
]
},
plugins: [
new MiniCssExtractPlugin()
]
}
I hope you'll be able to adapt it.
Found this solution:
webpack config (dev), this is for less :
{
test: /\.modules\.less$/,
use: [{
loader: 'style-loader' // creates style nodes from JS strings
},{
loader: 'typings-for-css-modules-loader',
options:{
modules:true,
namedExport: true,
camelCase: true,
localIdentName:'[path][name]---[local]---[hash:base64:5]'
}
},{
loader: 'less-loader',
options: { javascriptEnabled: true }// compiles Less to CSS
}]
}
then name your less file something.modules.less
import it in the js as so:
import * as styles from './something.modules.less';
and use it like this:
<div className={styles.yourClassName}></div>
I can't figure out how to render css with the webpack sass-loader.
App.js file:
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import Test from "./Test";
class App extends Component {
render() {
return (
<div className="App">
<div className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h2>Welcome to React</h2>
</div>
<p className="App-intro">
To get started, edit <code>src/App.js</code> and save to reload.
</p>
<Test />
</div>
);
}
}
export default App;
Test.jsx file:
import React, { Component } from 'react';
import './Test.scss';
class Test extends Component {
render() {
return (
<p className="intro">
Test
</p>
);
}
}
export default Test;
Test.scss file:
.intro{
background-color: #dddddd;
color: red;
}
webpack.config.dev.js file:
{
test: /\.css$/,
use: [
require.resolve('style-loader'),
{
loader: require.resolve('css-loader'),
options: {
importLoaders: 1,
},
},
{
loader: require.resolve('postcss-loader'),
options: {
ident: 'postcss', // https://webpack.js.org/guides/migrating/#complex-options
plugins: () => [
require('postcss-flexbugs-fixes'),
autoprefixer({
browsers: [
'>1%',
'last 4 versions',
'Firefox ESR',
'not ie < 9', // React doesn't support IE8 anyway
],
flexbox: 'no-2009',
}),
],
},
},
],
},
{
test: /\.scss$/,
use: [{
loader: "style-loader" // creates style nodes from JS strings
}, {
loader: "css-loader" // translates CSS into CommonJS
}, {
loader: "sass-loader" // compiles Sass to CSS
}]
}
Image:
Result
Expected
I'm doing something wrong with the sass loader. What is it? Please help.
{
exclude: [
/\.html$/,
/\.(js|jsx)$/,
/\.css$/,
/\.scss$/,
/\.json$/,
/\.bmp$/,
/\.gif$/,
/\.jpe?g$/,
/\.png$/,
],
loader: require.resolve('file-loader'),
options: {
name: 'static/media/[name].[hash:8].[ext]',
},
}
I added /.scss$/ here, the code is running successfully, thank you all
This is how I use sass-loader together with the help of extract-text-webpack-plugin to create a separate file instead of just including it to bundle.js file.
I'm using webpack v2.6.1
// webpack-config.js
const ExtractTextPlugin = require('extract-text-webpack-plugin');
module: {
rules: [
{ test: /\.css$/, use: ExtractTextPlugin.extract({ fallback: 'style-loader', use: ['css-loader']}) },
{ test: /\.scss$/, use: ExtractTextPlugin.extract({ fallback: 'style-loader', use: ['css-loader', 'sass-loader']}) },
],
},
plugins: [
new ExtractTextPlugin('[name]-[chunkhash].css'),
]
and import it to my index.js, like so:
import '../public/assets/sass/style.scss';