I have a partial sass called "_color.scss" where it has these code from materializecss.
$materialize-red: (
"base": #e51c23,
"lighten-5": #fdeaeb,
"lighten-4": #f8c1c3,
"lighten-3": #f3989b,
"lighten-2": #ee6e73,
"lighten-1": #ea454b,
"darken-1": #d0181e,
"darken-2": #b9151b,
"darken-3": #a21318,
"darken-4": #8b1014,
);
...
#each $color_name, $color in $colors {
#each $color_type, $color_value in $color {
#if $color_type == "base" {
.#{$color_name} {
background-color: $color_value !important;
}
.#{$color_name}-text {
color: $color_value !important;
}
}
#else if $color_name != "shades" {
.#{$color_name}.#{$color_type} {
background-color: $color_value !important;
}
.#{$color_name}-text.text-#{$color_type} {
color: $color_value !important;
}
}
}
}
// Shade classes
#each $color, $color_value in $shades {
.#{$color} {
background-color: $color_value !important;
}
.#{$color}-text {
color: $color_value !important;
}
}
// usage: color("name_of_color", "type_of_color")
// to avoid to repeating map-get($colors, ...)
#function color($color, $type) {
#if map-has-key($colors, $color) {
$curr_color: map-get($colors, $color);
#if map-has-key($curr_color, $type) {
#return map-get($curr_color, $type);
}
}
#warn "Unknown `#{name}` in $colors.";
#return null;
}
Then in my every other .scss files, i import that in.
#import "../../bower_components/materialize/sass/components/color";
Given this statement by their site, "The underscore lets Sass know that the file is only a partial file and that it should not be generated into a CSS file.", should this be excluded from the actual css? But my current environment is including the partial into my css
was it something to do with my grunt?
You shouldn't have to include the partial file in every over sass file, it defeats the purpose.
What does your file structure look like?
For example, my file structure would look something like:
main.scss
_variables.scss
_mixins.scss
_grid.scss
_whatever.scss
and then within main.scss
#import 'variables'
#import 'mixins'
#import 'grid'
#import 'whatever'
With grunt or sass you are then compiling main.scss , or using sass:
sass --watch main.scss:style.css
Without the underscore, there is a chance that your build tool (grunt) will output a CSS file for every SCSS file in your folders. For example, with this folder structure (without underscores):
my_project
scss
main.scss
colors.scss
mixins.scss
component1.scss
component2.scss
grunt might output a CSS file for every partial:
my_project
css
main.css
colors.css
mixins.css
component1.css
component2.css
Most people don't want this, so we use underscores to tell grunt not to compile every file, like so:
my_project
scss
main.scss
_colors.scss
_mixins.scss
_component1.scss
_component2.scss
This will output as:
my_project
css
main.css
Related
I have a Next.js Application with a main.scss global css file imported in the pages/_app.js file.
_app.js
import '../global-styles/main.scss'
export default function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />
}
The styles from this file work.
I also have some modular scss files attached to components, using [component].module.scss.
I have written a variable in my variables.scss file, one of the files which I #import in main.scss,
variables.scss
$mobile: 750px;
main.scss
#import './fonts.scss';
#import './variables.scss';
#import './global.scss';
However, when I try to use this variable in one my modular css, I get an error
./module-styles/navbar.module.scss (./node_modules/css-loader/dist/cjs.js??ref--5-oneOf-3-1!./node_modules/postcss-loader/src??__nextjs_postcss!./node_modules/resolve-url-loader??ref--5-oneOf-3-3!./node_modules/sass-loader/dist/cjs.js??ref--5-oneOf-3-4!./module-styles/navbar.module.scss)
SassError: Undefined variable: "$mobile".
on line 19 of /Users/Parv/Documents/reactx/module-styles/navbar.module.scss
>> #media (max-width: $mobile) {
---------------------------^
My question is, why aren't my global variables which I declare in my main.scss coming through?
the easier way is to add a file with variable import and add alias to tsconfig
sassOptions: {
includePaths: ['./src'],
prependData: `#import "~#styles/variable.scss";`,
}
Update:
In file next.config.js need add this code (you need to create it if there is no such file)
module.exports = (phase, {defaultConfig}) => {
if ('sassOptions' in defaultConfig) {
defaultConfig['sassOptions'] = {
includePaths: ['./src'],
prependData: `#import "~#styles/variables.scss";`,
}
}
return defaultConfig;
}
In file tsconfig.json need add alias
"baseUrl": ".",
"paths": {
...
"#styles/*": [
"src/styles/*"
],
...
Then create file with styles on path: src/styles/variable.scss in variable.scss you can import other scss file
It is not related to Next.js, but to the way sass-loader works.
Each import of scss file from js file is treated as an isolated sass env, therefore, there is no such thing "global variables".
This behaviour requires you to import the variables.scss file from each scss file that uses one of the variables.
Side note, It is important that these common scss files (such your variables.scss) will not contain "regular" css, because if so, they will be duplicated many times (the amount of imports).
Just add this to your next.config.js file and restart
const path = require('path')
module.exports = {
sassOptions: {
includePaths: [path.join(__dirname, 'styles')],
prependData: `#import "main.scss";`
}
}
Apparently you can only import variables from a module file, not a global file.
Import variables.scss into your module's SCSS file, then import your variables from your module:
variables.scss:
$my-color = #123456;
:export {
myColor: $my-color;
}
page.module.scss:
#import './variables.scss';
page.jsx:
import color from './page.module.scss'
console.log(color.myColor); // '#123456'
This worked for me.
I solve it by adding my global variables to next.config.js. It is not a good solution but it works.
module.exports = {
sassOptions: {
includePaths: [path.join(__dirname, 'styles')],
prependData: `
$primary-font-regular: 'Gotham';
$primary-font-medium: 'Gotham';
$default-font-size: 16px;
$h1: 5.208vw;
$h4: 1.458vw;
$primary-color: #000000;
$gray: #CCCCCC;
`,
},
};
You can follow this link for the answer: https://github.com/vercel/next.js/pull/12277
Consider this code:
// File A1.scss
.abc {
// styles for abc
}
.def {
// styles for def
}
// File B2.scss
.xyz {
// styles for xyz
}
Is it possible to import and use .abc from A1.scss into B2.scss without having the class .def in B2.css (i.e. the output of B2.scss)?
A1.scss is large in real project, so can't afford to have B2.scss be bloated with other styles. I am using this in a React app with Webpack.
I am using angular 5 material and i created a theme.scss as below
theme.scss
#import '~#angular/material/theming';
#include mat-core();
$custom-primary: mat-palette($mat-deep-purple,600);
$custom-accent: mat-palette($mat-lime, 100);
$custom-warn: mat-palette($mat-red);
$custom-theme: mat-light-theme($custom-primary, $custom-accent, $custom-warn);
#include angular-material-theme($custom-theme);
// ALTERNATIVE THEME
$alt-primary: mat-palette($mat-yellow);
$alt-accent: mat-palette($mat-grey, 200);
$alt-theme: mat-dark-theme($alt-primary, $alt-accent);
.alternative {
#include angular-material-theme($alt-theme);
}
I have my default styles.scss as below
style.scss
#import "~#angular/material/prebuilt-themes/indigo-pink.css";
.fa-icon-nav {
color: #507889;
font-size: x-large;
}
The color is currently hardcoded in the fa-icon-nav. I want it to use primary color from the currently selected theme. Please advise how this would work if possible? Happy to hear if this is totally the wrong way to do it and how it should be done.
EDIT:
ADDED ONLINE DEMO
I am working on a project where I used the Material 2 Themes and I used this approach where I use the class name and add colors class globally.
This is what I did :
FileName: mytheme-sidemenu.scss:
// Import all the tools needed to customize the theme and extract parts of it
#import "~#angular/material/theming";
// Define a mixin that accepts a theme and outputs the color styles for the component.
#mixin mytheme-sidemenu($theme) {
// Extract whichever individual palettes you need from the theme.
$primary: map-get($theme, primary);
$accent: map-get(
$theme,
accent
); // Use mat-color to extract individual colors from a palette as necessary.
.col-primary {
color: mat-color($primary, 500) !important;
}
.col-accent {
color: mat-color($accent, 300) !important;
}
}
Here is my main theme file: mytheme-theme.scss:
#import '~#angular/material/theming';
#import './variables/helper.scss';
#import './variables/spacemanager.scss';
#import './mytheme-sidemenu.scss';
// Primary theme
#include mat-core();
$mytheme-app-primary: mat-palette($mat-light-blue, 700, 600);
$mytheme-app-accent: mat-palette($mat-pink, A200, 900, A100);
$mytheme-app-warn: mat-palette($mat-deep-orange);
$mytheme-app-theme: mat-light-theme($mytheme-app-primary, $mytheme-app-accent, $mytheme-app-warn);
#include angular-material-theme($mytheme-app-theme);
// Secondary Theme
.mytheme-alt-theme {
$mytheme-alt-primary: mat-palette($mat-blue-grey, 500);
$mytheme-alt-accent: mat-palette($mat-pink, 500);
$mytheme-alt-warn: mat-palette($mat-deep-orange);
$mytheme-alt-theme: mat-light-theme($mytheme-alt-primary, $mytheme-alt-accent, $mytheme-alt-warn);
#include angular-material-theme($mytheme-alt-theme);
}
// Using the $theme variable from the pre-built theme you can call the theming function
#include mytheme-sidemenu($mytheme-app-theme);
and in app.module.ts update this :
export class AppModule {
constructor(
#Inject(OverlayContainer) private overlayContainer: OverlayContainer
) {
this.overlayContainer
.getContainerElement()
.classList.add("mytheme-alt-theme"); // this for double theme add to the root css class
}
}
This is already asked and I just copy paste my answer from here
EDIT :
As per your need, you can achieve this:
I have my default styles.scss as below style.scss that you need to change to _theme-color.scss
.fa-icon-nav {
color: mat-color($primary, 500) !important; // 500, 600 , 700 check material color pallet for more info
// You can use this too
// color: mat-color($alt-primary, 500) !important;
font-size: x-large;
}
or you can use this material color library from here
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"; }
...
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.