Hi everyone I have noticed that SASS doesn't seem clever enough to understand to don't duplicate code imported (or maybe I am missing something in the way that I have planned my code architecture).
Here is my repository:
Duplication of classes, if I try to insert a class in one of the .scss that I import the most
My CSS code is structured in this way, trying to following a standard of loading the code
My architecture
FILE main.scss
// ITCSS: https://www.xfive.co/blog/itcss-scalable-maintainable-css-architecture/
// Variable configurations for things like colors, fonts, sizes, etc…
#use "./01-settings.scss" as *;
// Globally used mixins and functions
#use "./02-tools.scss" as *;
// CSS resets and normalizing rules to create a foundation for your styles
#use "./03-generic.scss" as *;
// Style rules for bare HTML elements (like h1 or button)
#use "./04-elements.scss" as *;
// Load generic elements that are used in layouts
#use "./05-objects.scss" as *;
// Define basic values for main layout to make it responsive
#use "./06-media-queries.scss" as *;
Because the code is split, I have than inside of various of the element recall some includes once again otherwise SASS is not able to recognise the different variables or functions that I am using across the project.
FILE #01-settings.scss
#use '00-load-fonts' as *;
#use '02-tools' as *;
// VARIABLES
// --BREAKPOINTS
$break-mobile:toRem(576);
$break-tablet-potrait:toRem(768);
$break-tablet-landscape:toRem(992);
$break-desktop:toRem(1200);
$break-desktop-l:toRem(1440);
$break-desktop-xl:toRem(1920);
// --SPACING
$space-xxl: toRem(48);
$space-xl: toRem(32);
$space-l: toRem(24);
$space-m: toRem(16);
$space-s: toRem(8);
$space-xs: toRem(4);
$space-xxs: toRem(2);
...etc...
FILE #04-elements.scss
#use '01-settings' as *;
#use '02-tools' as *;
// GENERIC
html{height:100%;}
.body{background:var(--bg); color:var(--color-txt); min-height:100%;}
// LINK
a{text-decoration:none; color:$color-link;}
a:visited{color:$color-link-visited;}
a:hover, a:focus{text-decoration:underline;}
a:active{color:$color-link-active;}
// TYPOGRAPHY
.body{
text-align:center;
font-family: $font-family-primary;
font-size: $font-size-m;
line-height: $line-height-m;
}
..etc...
My files have different kind of generic variables and function that I use across the SASS/React project so that I can have everything very customisable.
I clearly understand that this cause an issue of duplication because I am loading multiple time the same files, but it is really rubbing me the wrong way in having CSS that duplicates and there is not a way to filter it.
is there a way to configure sass so that its be able to load classes once?
or is there a way to structure so that this doesn't happen while retaining the ability of having smaller file with specific code instead of a BIG SINGLE FILE?
any other suggestion/tip/idea that I am not aware?
I am sure that there are some kind of best practices that I am not aware about REACT & SASS, or probably a common solution for a common problem.
p.s. I would like if possible to maintain the ITCSS structure. Here the article on the reason why is useful
Related
I have a custom sass setup with bootstrap 5 and bunch of my own SCSS files, all of this gets compiled in style.css using gulp. I have a _colors.scss file which stores all the colors according to our design language. We use this to generate a bunch of classes that can be used any where to change colors:
// Text Colors
$colors: (
"icon-color": $slate-500,
'slate-10': $slate-10,
'slate-40': $slate-40,
'slate-300': $slate-300,
"secondary": $secondary-text-color,
"green": $green,
"light-green": $green-color,
"blue": $blue,
"blue-200": $blue-200,
"blue-300": $blue-300,
"blue-400": $blue-400,
"dodger-blue": $dodger-blue,
"mariner-blue": $mariner-blue,
"light-blue": $blue-100,
"cadet-blue" : $cadet-blue,
"aqua-10": $aqua-10,
"gray": $gray,
"gray-light": $gray-light,
"light-gray": $gray-100,
"bright-gray": $bright-gray,
"gray-200": $gray-200,
"clay": $clay,
"clay-10": $clay-10,
"mandy-pink": $mandy-pink,
"aqua": $aqua,
"violet": $violet,
"white": $white,
"primary": $primary-text-color
);
#each $color-name, $color-value in $colors {
.text-#{$color-name} {
color: $color-value !important;
}
.bg-#{$color-name} {
background-color: $color-value !important;
}
.border-#{$color-name} {
border-color: $color-value !important;
}
}
Problem is certain classes like .text-gray or .text-blue are not working. My guess is that since bootstrap also uses variables called gray and blue, its conflicting with my variables in _colors.scss.
On closer look, the css does gets generated properly (I found below declaration in final style.css):
.case-study .case-study-right .card .data-bar p:last-of-type,.share .social-media>span,.text-color-gray-200,.text-gray-200 {
color: #69727A!important
}
But using .text-gray has no effect, the class is not getting applied.
How do I fix this? please help!
First, if you're sure that you see the correct selector and the correct rule in your CSS file: it should be applied. And so, the rule should be visible in the browser console (even if overridden).
If you see it in your CSS file, but not applied in the browser console: check that your CSS file is valid (and that your gulp production script compiles fine), as a bad character could mess some part of it.
If you see your CSS in the browser console, but it's overridden by some bootstrap rules, you can override bootsrap variables, and change bootstrap colors by yours like so (import bootstrap before this):
$theme-colors: (
primary: #121212,
success: #8bcea8
...
);
You could also try this to replace bootstrap values by yours:
$theme-colors: map-merge($theme-colors, $colors);
The simple answer is:
Use Bootstrap 5 the intended way!
Bootstrap is a complex framework. All that huge number of classes work together including overwriting color settings if provided and used the intended way. In your code example you additional create helper classes Bootstrap would provide to you out of the box if you use it the Bootstrap way. As you did not do it leads to conflicts which are not easy to handle ... and nearly impossible to solve without to have the possibility to analyize the page itself.
This is what you may check:
You may check: are there other classes which blocks your classes?
In your example you use !important to get higher specifity. But the color is overwritten by other classes ...
Maybe that are Bootstrap which uses !important as well. In that case you can try to add your classes at the end of your CSS (after the Bootstrap classes) so they are able to overwrite in case of identical specifity.
Additional: in your example you added a huge bunch of non-bootstrap-classes. Maybe this individual added classes blocks your styling by adding a color with higher specifity (using !important as well which is not a good technique at all) to your element than your added class do.
In that case same solution may be possible ... but individual classes with !important and an additional higher specifity (i.e. using two class names in the selector) will win over your helper classes also your helper class comes later in your CSS file.
To be honest: most often analyzing such an huddle of classes indeed is only possible in the browser on the page direct using the developer tools.
But best way indeed would be ...
Do a correct Bootstrap theming and use Bootstrap classes!!!
You really don't need to create the helper classes on your own. Just do a SASS setup of Bootstrap ... and add your needed/additional colors NOT (or not only) to map $colors but AS WELL TO Bootstrap map $theme-colors. Bootstrap builds up helper-/utility-/elements-color-classes not on $colors but on $theme-colors. That means: doing that this intended way ... all your helper classes you added in your project on your own will be provided by Bootstrap mechanic in the correct order and avoiding conflicts to your CSS.
Use Bootstrap classes to style your page. Now you don't need to create an additional class .case-study { color: gray }. Just use the Bootstrap helper class and add .text-gray to same element. (Note: In your example you use the incredible number of NINE classes to do the same styling. In case 'text in cards' here is a nice hint how to realize it the bootstrap way: https://getbootstrap.com/docs/5.0/components/card/#border).
Just thinking about using complex Framework...
Bootstrap is done to help you. As there is a lot of code using that Framework only makes sense to use the code as much as possible without writing new classes. So best way indeed to work with it is to use the Bootstrap elements and styling them the Bootstrap way. That makes it simple and avoids conflicts... And: you are able to do nearly everything with these elements.
And if you need to extend Bootstrap i.e. with additonal classes: avoid (deep) nested classes and !important as well so you are able to overwrite settings with simple helper classes.
i had the similar problem it was my scss was successfully converted to the css but not applied, after checking for hours i found out ,i have written B capital while the class name was btn
so when everything is working then the problem is always in your code syntax!
I've been assigned to rewrite an existing CSS code into SASS. This is my first experience with SASS, still a beginner.
So, first thing that I started with, I merged all css files into single file. Now I'm going through it and try to separate things into different .scss files.
I have layouted my SASS folder's architecture according to "7-1" pattern, which consists of 7 folders: abstracts, base, layout, modules, pages, themes and vendors. So far so good.
In process of separating my CSS into different files I came across a problem that I couldn't find answers to on google:
Say I have 2 CSS files - main.css and admin.css. There is defined a class in main.css:
.first-line {
padding-bottom:10px;
padding-left:30px;
padding-right:30px;
}
and a class with the same name is defined in admin.css
.first-line {
padding-left:15x;
padding-right:10px;
}
As I understood from SASS tutorials online (correct me if I'm wrong), SASS code should result in only one main.scss where I import all particles, modules etc. and it get's compiled to single main.css file. If so, how do I solve a problem like this, where I need a class to be defined differently only for a single page?
Try to nest that .first-line class in both the files (parent would be diff while nesting) ..... so while compiling into single file, it wont cause a problem
If it is a single-page application, that means you have JavaScript in use.
You can simply define a unique class for each page and assign this class to either body or html element (I prefer the latter one), and in run time you can simply set the page class dynamically. This way, you can define the first-line class and set the default values and put it into a shared .scss file and then overwrite the existing attributes or add new ones to that class for each individual page as needed.
E.g., you might want to structure it like this.:
pages/common.scss:
first-line {
padding-bottom:10px;
padding-left:30px;
padding-right:30px;
}
main.scss:
html {
import 'pages/common';
&.admin {
#import 'pages/admin';
}
&.other-page {
#import 'pages/other-page';
}
}
I'm wondering if there's a grunt plugin that can compare two files and remove duplicates from one of them.
Example: if both blog.css and main.css contain the rule .button { color: red; } I'd like to remove that rule from blog.css. (main.css should always remain unchaged)
Background:
I've got two LESS-bundles, main.less and blog.less, which I compile into main.css and blog.css
The idea is that my site should load main.css on every page. On blog pages I'll load both both main.css and blog.css.
The problem is that these LESS-files share a few "utility"-files (with variables, mixins and some common classes like .button)
So I end up with blog.css containing duplicates of some rules which are already defined in main.css, and I'd like to get rid of those duplicates to reduce file size.
Found it
https://www.npmjs.com/package/grunt-csscss
csscss: {
dist: {
src: ['css/x.css', 'css/y.css']
}
}
Allthough in my case the solution was actually much simpler. Turns out LESS now has import ("reference") which will import a file to use as a dependency only, without outputting any of it's css.
So now I can use import ("reference") commonstuff.less in blog.less and thus none of the styles from commonstuff.less will be output to blog.css! :)
I need to include the file
"#{request.domain.split(".").first}.css.scss"
into my custom.css.scss file.
I don't know how to proceed. The goal is to declare specific variable, and give them different values in each file, loading dynamically different files for each different request
file one.css.scss
$button_primary_color: #xxx;
$header_background_color: blue;
file two.css.scss
$button_primary_color: #zzz;
$header_background_color: red;
I also tried using CSS3 variables, without success:
home[sn="one"] {
--button_primary_color: #xxx;
}
home[sn="two"] {
--button_primary_color: #yyy;
}
(it doesn't behave standard in the different browser), and also it doesn't substitute the following statement.
div {
color: var(--button_primary_color);
}
I'd like to have a more bootstrap/sass solution. How can I accomplish this?
I'm still trying to figure out a best method, but one thing I've done in the past is to set the config.assets.precompile to effectively have domain specific css files and then have your layout generate the appropriate code to pull in that specific css file.
config.assets.precompile += %w( application.js application.css domain1.css domain2.css)
where you have in your asset pipeline
domain1.css pulling in whatever domain specific code you need.
much cleaner than trying to include logic switches within the css code (which you cannot do btw afaik).
I really like the idea and the concept of LESS. Yet I stumbled upon a bug, which i reported quite a while ago to the author but did not yet get any feedback. Maybe it's just me who is doing something wrong.
My application.less-File that looks similar to this:
#import "reset";
#import "config";
#import "header";
#import "forms";
[…]
I like that it is possible to use the #import rule to split up my files to gain a better overview of my css-declarations. Yet every imported file needs to re-import the config.less-File again to be able to make use of the mixins and variables i defined in there.
I bet you already know about what kind of redundancy I am driving at: Everytime the config.less is imported, its "output" becomes part of the application.css.
My config-file contains about 200 lines of code. Since I split up my CSS-into about 5 files (based on my controller names) that need to re-import the config, I end up having about 1000 lines of generated CSS-Code that are 100% redundant.
Only solution that I can come up with is not to split up my files, what I really like to avoid.
Although not ideal, the practical reason for this is that the files you import theoretically don't need to contain any CSS. Typically, you would have variables and dynamic mixins, which don't contribute to your CSS output:
lib.less:
#colors {
#blue: #0011ff;
#red: #ee2222;
}
.button (#width: 10px) {...}
main.less:
#import "lib";
a { color: #colors[#blue]; }
output, main.css:
a { color: #0011ff; }
#colors {} and .button will not be output in this case.
LESS now supports #import-once "stylename.less";
Maybe you can split them up in your development environment and then merge them together, not needing all the extra code, when you deploy to your live web server?
You can use dynamic mixins in your LESS config file if they are declared and mixed-in using $ instead of ..
In config.less:
$mixin
{
a { color: #light; }
h2 { //etc.
}
In header.less:
#import "config";
.header
{
$mixin;
}
Source. I've also tried this and it works.