use global scss files in reactjs compoent scss file - css

I am trying to develop a web application using sass and reactjs.
The Sass structure is like the one in the image attached.
Image - ![1]: http://i.imgur.com/1XPwP87.png
The library.scss and settings.scss file is imported in the styles.scss file.
Inside each reactjs component, I have a js, scss, css.
MainLayout (Component)
MainLayout.js
MainLayout.css
MainLayout.scss
Now, all the breakpoints, grids, etc generated in the "style.css" file and I want to use it in the "MainLayout.scss".
So, in the "MainLayout.scss" file, I did
#import '../../assets/css/styles.scss';
.main-content {
display: flex;
flex-wrap: wrap;
#include from-breakpoint(tablet-portrait) {
position: relative;
}
}
But, I get this error stated below :
=> changed: C:\projects\vliegtickets-frontend\src\components\MainLayout\MainLayout.scss
{
"status": 1,
"file": "C:/projects/vliegtickets-frontend/src/components/MainLayout/MainLayout.scss",
"line": 53,
"column": 14,
"message": "no mixin named grid-desktop\n\nBacktrace:\n\tsrc/components/MainLa
yout/MainLayout.scss:53, in mixin #content\n\tsrc/assets/css/library/_breakpoi
nts.scss:16, in mixin from-breakpoint\n\tsrc/components/MainLayout/MainLayout.
scss:52",
"formatted": "Error: no mixin named grid-desktop\n\n
Backtrace:\n
\tsrc/components/MainLayout/MainLayout.scss:53, in mixin #content\n \tsr
c/assets/css/library/_breakpoints.scss:16, in mixin from-breakpoint\n \t
src/components/MainLayout/MainLayout.scss:52\n on line 53 of src/componen
ts/MainLayout/MainLayout.scss\n>> \t\t\t\t#include grid-desktop;\n -----------
--^\n"
}
Can someone please help me with this ? What should I do to to make my "scss" files inside the components make use of the "style.scss"?

Related

Target a css class in 'a component generated by library' in react

I have used a chart library. I want to target and modify the properties of the CSS class generated by that library using external CSS. Let's assume the code in inspector is like this-
<div id="apexcharts9xagqubx" class="apexcharts-canvas apexcharts9xagqubx apexcharts-theme-light" style="width: 319.5px; height: 200px;">
<svg id="SvgjsSvg1001" width="319.5" height="200" xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svgjs="http://svgjs.dev/svgjs" class="apexcharts-svg apexcharts-zoomable hovering-zoom">
<div>
the apex chart documentation says I can target .apexcharts-canvas and change the background color. I have done this:
import React from "react";
import ReactApexChart from 'react-apexcharts'
import './apex.module.css'
return (
<div id="chart">
<ReactApexChart options={data.options} series={data.series} type="area" height={200}/>
</div>
);
inside apex.module.css I did this:
.apexcharts-canvas{
background-color: black;
}
now what?
looks like it doesn't work.
It looks like a CSS specifity thing.
You could try including the parent in the selector:
#chart .apexcharts-canvas {
background-color: black;
}
Hey friend when you import a css file with module prefix you shouldn't import that way, that kind of file will be imported giving it a name for example in this image:
This works equally with css extension files, since I am doing it with scss, this rule is for all css file types.
When you declare with module it's not a global style anymore but a style for a component because there is another way to import it but without the prefix module, in the image I already showed you the name of the declared name and then the name of the class.
Luckily my friend, it is not so complicated, I am also learning this little by little.
IF you are using CSS modules (else let me know):
TL;DR
You can either target the HTML element (instead of its class) where .apexcharts-canvas class is used (option 1), or you can make sure the global CSS imports are compatible with the CSS modules (option 2), checking webpack configuration.
I had same issue, I wanted to edit a CSS class in Apexcharts.
I am assumming you are using CSS modules (.module.css).
Option 1
Use this option if:
you used cra or you do not want to edit webpack configuration
it is enough to target the HTML element instead of the class directly
Steps:
The ID of the div where the chart is should be namespaced (CSS modules): id={styles.chart}, with CSS modules file imported as import styles from 'path-to-file'
In code inspector find div with chart id
Drill down until you find HTML element with your class .apexcharts-canvas
In your CSS modules file, target the HTML element with .apexcharts-canvas, using CSS selectors (example below)
.chart > div > div > :last-child {
background-color: black;
}
Option 2
Use this option if:
you can access the webpack config file (not using cra), AND
you want to target class directly
In the webpack configuration, you need to create a rule not only for CSS modules (import styles from 'path-to-file'), but also for global (normal) CSS (import 'path-to-other-file').
(credit: link)
rules: [
{
test: /\.(css|scss)$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 1,
modules: {
localIdentName: "[name]__[local]___[hash:base64:5]",
},
}
}
],
include: /\.module\.css$/
},
{
test: /\.(css|scss)$/,
use: [
'style-loader',
'css-loader'
],
exclude: /\.module\.css$/
},
]
After that you can import a global CSS file (import 'path-to-other-file') with a class .apexcharts-canvas on it.
Important: the webpack rules are mutually exclusive. Files ending with ".module.css" are considered CSS modules, other CSS files not ending like that are global CSS imports.

Extending bootstrap in create react app

I am tyring to extend boostrap classes in my sass file. I'm compiling my sass as in this example.
I have copied the boostrap files into my /src folder.
However, using this basic example:
#import "bootstrap/*";
.header{
#extend .container;
background-color:red;
}
I get the error:
{
"status": 1,
"file": "C:/sites/mharrisweb-redux/src/sass/style.scss",
"line": 1,
"column": 1,
"message": "File to import not found or unreadable: bootstrap/.\nParent style sheet: C:/sites/mharrisweb-redux/src/sass/style.scss",
"formatted": "Error: File to import not found or unreadable: bootstrap/.\n Parent style sheet: C:/sites/mharrisweb-redux/src/sass/style.scss\n on line 1 of src/sass/style.scss\n>> #import \"bootstrap/*\";\n ^\n"
}
If you have this file structure:
src
bootstrap
sass
style.scss
You should use:
#import "../bootstrap/scss/bootstrap";
If you installed Bootstrap using package manager (npm or yarn), you could use:
#import "~bootstrap/scss/bootstrap";

Cannot import 'font-awesome/scss/variables' in local SCSS module

I have Font Awesome v4.7.0 installed and I'm trying to write Sass classes that extend Font Awesome icon classes, like this:
div.edit-icon {
#extend .fa-pencil-square-o;
font-size: $icon-font-size;
}
At the start of one of my SCSS files (_shared.scss), I try importing the bare essentials I need from Font Awesome (installed in node_modules):
#import '~font-awesome/scss/variables';
#import '~font-awesome/scss/mixins';
#import '~font-awesome/scss/icons';
However, Webpack gives me this error when I save the file:
ERROR in ./~/sass-extract-loader!./app/views/components/_shared.scss
Module build failed: Error: File to import not found or unreadable: ~font-awesome/scss/variables.
Parent style sheet: C:/Users/<me>/WebstormProjects/<project>/app/views/components/_shared.scss
at options.error (C:\Users\<me>\WebstormProjects\<project>\node_modules\node-sass\lib\index.js:291:26)
# ./app/views/components/candb/MessageDefinitionView/CoreMessageDefinitionView.tsx 9:28-77
# ./app/views/components/candb/MessageDefinitionView/TxMessageDefinitionView.tsx
# ./app/views/components/candb/index.ts
# ./app/views/components/index.ts
# ./app/views/layouts/Page/Page.tsx
# ./app/routes.tsx
# ./app/index.tsx
# multi (webpack)-dev-server/client?http://localhost:1212 webpack/hot/dev-server react-hot-loader/patch webpack-dev-server/client?http://localhost:1212/ webpack/hot/only-dev-server ./app/index.tsx
Here's the start of node_modules\font-awesome\scss\_variables.scss:
// Variables
// --------------------------
$fa-font-path: "../fonts" !default;
$fa-font-size-base: 14px !default;
$fa-line-height-base: 1 !default;
//$fa-font-path: "//netdna.bootstrapcdn.com/font-awesome/4.7.0/fonts" !default; // for referencing Bootstrap CDN font files directly
$fa-css-prefix: fa !default;
$fa-version: "4.7.0" !default;
$fa-border-color: #eee !default;
$fa-inverse: #fff !default;
$fa-li-width: (30em / 14) !default;
What I noticed is that the value of $fa-css-prefix is an unquoted string (fa), and that commenting out this assignment allows this SCSS file to compile.
How is it legal for this string to be unquoted, and what can I do to allow me to import this SCSS file?
For reference, this is a relevant part of my Webpack config for loading SCSS modules:
// Add SASS support - compile all other .scss files and pipe it to style.css
{
test: /^((?!\.global).)*\.scss$/,
loader: extractModuleCSS.extract({
fallback: 'style-loader',
use: [
'css-loader?modules&sourceMap&camelCase&importLoaders=1&localIdentName=[path]___[name]__[local]___[hash:base64:5]',
'sass-loader'
]
})
}
Edit
I thought that the fact that Webpack displayed an error about a different file when I commented out $fa-css-prefix: ... meant that at least _variables.scss was compiling fine:
Undefined variable: "$fa-css-prefix".
in C:\Users\<me>\WebstormProjects\<project>\node_modules\font-awesome\scss\_icons.scss (line 4, column 4)
Apparently that isn't the case, though. If I comment out the other imports in _shared like this:
#import '~font-awesome/scss/variables';
//#import '~font-awesome/scss/mixins';
//#import '~font-awesome/scss/icons';
Then I still see the original error ('File to import not found or unreadable: ~font-awesome/scss/variables.') regardless of the changes I make to _variables.scss - even commenting out the entire file.
I've updated the title to reflect this new information.
Edit 2
Based on #CloudTseng's advice I tried this:
$fa-css-prefix: 'fa';
#import '~font-awesome/scss/variables';
#import '~font-awesome/scss/core';
#import '~font-awesome/scss/icons';
$icon-font-size: 16px;
div.edit-icon {
#extend .fa;
#extend .fa-pencil-square-o;
font-size: $icon-font-size;
}
div.cross-icon {
#extend .fa;
#extend .fa-times;
font-size: $icon-font-size;
}
Surprisingly, this gives me exactly what I want. The reason I find this surprising is that apparently I only needed to redefine fa-css-prefix locally - I was expecting that I would have to redefine all the Font Awesome variables from _variables.scss if I went this route.
However, inspecting my generated CSS shows me that all the other variables are magically resolved without me needing to redefine them:
font-awesome/scss/_icons.scss:
.#{$fa-css-prefix}-glass:before { content: $fa-var-glass; }
.#{$fa-css-prefix}-music:before { content: $fa-var-music; }
.#{$fa-css-prefix}-search:before { content: $fa-var-search; }
...
/dist/modules.css:
/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen
readers do not read off random characters that represent icons */
.app-views-components-candb-FieldDefinitionTable-___FieldDefinitionTable__fa-glass___2rm6a:before {
content: "\F000"; }
.app-views-components-candb-FieldDefinitionTable-___FieldDefinitionTable__fa-music___3q-Vg:before {
content: "\F001"; }
.app-views-components-candb-FieldDefinitionTable-___FieldDefinitionTable__fa-search___f89bE:before {
content: "\F002"; }
...

How are `postcss-import` configured plugins applied

I've just started using PostCSS exclusively with Webpack. When using postcss-import to inline external stylesheets, I see it's options allow us to configure plugins and transformers to be applied on imported sources, but I'm a bit confused on how this fits in together with other options configured for the main PostCSS runner.
For instance, if I want to inline URLs, should I be adding the postcss-url plugin to postcss-import, the PostCSS runner or both (if my main stylesheet also has URL references)?
It's recommended to make postcss-import the first plugin in your list when you're defining the plugins for postcss in webpack. Since postcss-import just inlines the #import to the start of the file, any postcss plugin defined afterwards will be applied to it.
Example:
(For the example i'm gonna assume you use a postcss.config.js file, the same logic applies if you use an array for the plugins in the webpack 1 format)
// Header.css
#import 'button.css';
.foo {
font-size: 3rem;
transform:translateY(-10px);
}
// Button.css
.bar {
transform:translateX(20px);
}
If the import plugin is behind autoprefixer, it will first apply the autoprefixer plugin on the file and then afterwards import the #import file. So by the time the file is imported the prefixing will have already happened, the output will be:
// postcss.config.js
module.exports = {
plugins: {
'autoprefixer': {},
'postcss-import': {}
},
};
// output.css
.bar {
transform: translateX(20px); // Prefixing hasn't happened on the imported file
}
.foo {
font-size: 3rem;
transform:translateY(-10px);
-webkit-transform:translateY(-10px); // original file has been prefixed though
}
If you put the import first though, it will inline the imported file and then do the autoprefixing, this means both the imported and the original file will be autoprefixed:
// postcss.config.js
module.exports = {
plugins: {
'postcss-import': {},
'autoprefixer': {}
},
};
// output.css
.bar {
transform: translateX(20px);
-webkit-transform:translateX(20px); // Also prefixed now
}
.foo {
font-size: 3rem;
transform:translateY(-10px);
-webkit-transform:translateY(-10px);
}
So this means you don't actually have to add plugins again in the option of the postcss-import plugin.

Using css-loader inline with Webpack + React

I'm building my React app with Webpack, and css-loader w/modules. I love it. Most of my stylesheets are very small, though, and I'd like to inline them within the same JSX file as my markup and JavaScript.
The CSS loader I'm using right now looks like this:
{ test: /\.(css)$/i,
loader: ExtractTextPlugin.extract("style-loader", "css-loader?modules") }
In my JSX, I import my separate CSS files like this:
import classNames from 'dashboard.css';
...
<div className={classNames.foo}></div>;
This is then compiled and translated into something like:
<div class="xs323dsw4sdsw_"></div>
But what I'd like to do is something more like below, while still preserving the localized modules that css-loader gives me:
var classNames = cssLoader`
.foo { color: blue; }
.bar { color: red; }
`;
...
<div className={classNames.foo}></div>;
Is this possible? How can I do this without having to actually require / import a separate file?
I believe your issue is that you your current webpack configuration uses CSS Modules. CSS Modules automatically rename your CSS Classes to avoid global class name collisions.
The fix:
// remove 'modules' from the end of your css-loader argument
{ test: /\.(css)$/i,
loader: ExtractTextPlugin.extract("style-loader", "css-loader?modules") }
// like so
{ test: /\.(css)$/i,
loader: ExtractTextPlugin.extract("style-loader", "css-loader") }
Now your class names will be preserved. Although, I'm not sure why you want to do this. Do you care to share why?

Resources