LESS CSS Hierarchical Heritance - css

In a project I have separated the CSS into two sub-projects:
C:/Projects/_Framework/css
C:/Projects/_Base/css
Note: I've purposely prefixed the above with the C:/Projects/ to illustrate that they are totally separate projects from each other.
The _Framework has basic things like reset, typography, forms, and a grid.
The _Base has the default theme for the project. _Base imports the _Framework
Inside _Base I have files like header.less and variables.less which store the design of the header and the colours for the theme.
So if I have my project at: C:/Projects/App
And inside this App project, I have a master CSS file that looks like:
#import "/_Framework/_loadAll.less
#import "/_Base/_loadAll.less
Which imports both the Framework and the Base theme (the reason that Base doesn't load the Framework itself is for flexibility but has scope to be done this way instead if needed).
The plan is to make it so that if a header.less file existed inside _App then it would automatically override the import of the one in _Base.
How could this be achieved?

You can't exclude a whole .less file by checking for duplicate names. Just make sure that the header.lessfile of your _App project is imported after the one from _Base.
Pseudo code:
#import "/_Framework/_loadAll.less
#import "/_Base/_loadAll.less
#import "_App/header.less"
And overwrite any properties you need in the _App/header.less file.
If you need to overwrite everything in the _Base/header.less file, I would suggest it's not a good fit for a Base style.

Related

Include external CSS in an Angular library by modules

I am working on an angular design library based on bootstrap, similar to ng-bootstrap
I currently created multiples modules for each design component that can be imported separately based on user needs.
ex :
src/
modules/
inputs/
buttons/
navs/
tooltips/
....
Each module can be imported independently and used in application.
The problem I face is with bootstrap scss. Has explained here we can import all bootstrap with
#import "../node_modules/bootstrap/scss/bootstrap";
or by chunk
#import "../node_modules/bootstrap/scss/root";
#import "../node_modules/bootstrap/scss/reboot";
#import "../node_modules/bootstrap/scss/type";
#import "../node_modules/bootstrap/scss/images";
#import "../node_modules/bootstrap/scss/containers";
#import "../node_modules/bootstrap/scss/grid";
I would like each of my modules to import their specific scss files. The table would import the tables scss, the navs the navs etc...
Since bootstrap files are scss they need to be compiled before added to the page, and the easy solution of manually adding in each module a stylesheet element would not work.
In ng-bootstrap they require users to manually add each bootstrap scss that they wish to use, but this could be kind of a pain for users since they need to manually add a module and the associated styles.
Are there any solution to bind a scss file to a module, and compile it if that module is used in the app ?
I would follow in the footsteps of Angular Material's implementation and provide users of your library instructions on how to include the design library styles default styles or custom styles. Take a look at Angular Materials build code and the corresponding exported assets made available as an NPM package. Essentially to manually import a single SCSS file per module that is imported as described above a user would need to take the following steps and understand the styles will be applied globally. There is no dynamic inclusion and compilation of SCSS in Angular upon loading of a module the chunks under the hood would need to be recompiled and the styles would be preprocessed again.
In angular.json under the "build.options" object modify "styles" and "stylePreprocessorOptions" and update the configuration to point to the new global styles directory "entry" such as "styles":["src/styles/styles.scss"], "stylePreprocessorOptions": { "includePaths": [ "styles" ] } then in styles.scss import your bootstrap scss. Under the styles directory you can now create a custom directory structure and the angular compiler will be able to find everything imported in the global "styles.scss" file. Further reading: read about the shadow DOM in Angular in the context of styles applied based on view encapsulation for component scoped styles vs. globally applied styles.

Switching #import sass modules (files) in Vue (Vuex) to change color themes

I'm trying to get my head around the best approach to this (or if it's even possible). I have a rather large application i have set the color sass variables globally within two separated files - _theme-dark.scss and _theme-light.scss. Now i would like to allow the user to switch between the two say via a click of a button.
Here's an example of my app.scss file:
app.scss
#import 'modules/theme-dark';
//#import 'modules/theme-light';
FYI switch the code comments between the two files manually works, no i just need to make it dynamic.

Import custom stylesheets into create-react-app's app.scss

I am new to styling using app.scss for a new create-react-app and would like to know the following:
Should i store all the .scss and .css files in the style folder?
If I would like to import all of them into the app.scss, how do I
go about doing that?
I noticed that app.scss does these:
#import '~bootstrap/scss/bootstrap'
$fa-font-path: '~#fortawesome/fontawesome-free/webfonts'
When i tried to do this: #import './myStyles.css' it does not get picked up. I am not sure what is going on.
The reason i am adament about putting it in the app.scss file is becauase i created a toggle that allows me to switch between dark and light theme. However, I am unable to add customed theme to the existing themes.
Hope my question is clear
Here is reply for you query-
1.Should i store all the .scss and .css files in the style folder? - for this you have to make two folder, one is css and another sass(better approach)
2.If I would like to import all of them into the app.scss, how do I go about doing that?-
"#import 'reset';" no need of scss extension
If you are working on big project then i would suggest you that better follow this structure.
inside sass or scss folder make subfolder for diffrent works like vendor, module,particles etc. like modules/_colors.scss and follow below structure
// Modules and Variables
#import "partials/base";
#import "partials/buttons";
I hope this will help.

how to prevent a sass build of each page file when just changing a common scss file

I have a _common.scss file which I import to various page.scss files:
page.scss:
#import "common";
#page {
...
}
_common.scss:
#import "partials/all";
#import "components/all";
...
But the problem is, since all my pages import _common.scss, the way I have things structured, if I make any changes inside _common.scss (or any of the files it imports), sass has to rebuild all the page css files. But if I just make _common.scss its own file and call it with a <link> tag (<link href="common.css">), then the page.scss file has errors, because it is trying to use variables and mixins defined in _common.scss and its imports.
Is it possible to structure my project so that the page.scss files can use all the mixins and variables in _common, but so that sass doesn't have to rebuild each page.css file each time I make a change to the common file? i.e. - make it so that sass only builds the common file when a change is made in common, and only builds the page file when a change is made in page?
I would say it is not possible, since the aim is to have one css for each page at the end. This said it HAS to be rebuild if something is changed in common.

Page Specific Sass files and Duplication

I am really struggling to structure the Sass files in a Rails 3.1 project to avoid massive duplication ...
I have the following structure, with application.css.scss being imported as part of my main layout:
application.css.scss
- [*= require] main.css.scss
- [#import] 'variables';
- [#import]'bootstrap_overrides';
- [#import]'bootstrap';
- [#import]'base_elements';
- [#import]'superstructure';
- [#import]'modules';
So far so good. All these files are combined by sprockets into a single document. However I then want to modularise my Sass further, with page-specific files or files shared across regions of my site.
So on my GalleryResource#show page I need to use additional Sass files:
resource.scss
gallery_resource.scss
badges.scss
And maybe a css file from a lib:
gallery_lib.scss
These files need to reference a number of the files already imported in application.css. They need to make use of variables defined in variables.css.scss and of mixins defined in bootstrap. So I am forced to reimport these files in each file that uses them, causing massive duplication. I could write a manifest file for each and every page, but this is a maintenance nightmare and still results in duplication and two css files; application.css and page_specific.css.
So what is the solution? Do I need to dispence with application.css and move its imports into each page-specific file? So using the above example I would end up with a single manifest file that looks like this:
gallery_resource_manifest.css.scss
- [*= require] gallery_lib.css
- [*= require] gallery_resource.css.scss
- [#import] 'variables';
- [#import]'bootstrap_overrides';
- [#import]'bootstrap';
- [#import]'base_elements';
- [#import]'superstructure';
- [#import]'modules';
- [#import]'resource';
- [#import]'gallery_resource';
- [#import]'gallery';
- [#import]'badges';
I also attempted to do the same thing you are mentioning when organizing styles. Rails almost pushes you in this direction by constantly generating controller based stylesheets for you. In the end I've opted for adding everything to application.sass. The main advantage to this method is that you only make one request on page load and you don't end up having to re-import code that the user requested on the last page.
My personal opinion would be that if you abstract your CSS well you only need to use one stylesheet as you don't have a lot of view specific code to bring into the stylesheet in the first place. Either way, the alternative (randomly loading up modules based on page needs while you may have done the same on the previous page) doesn't sound like it's solving that problem anyway. Plus you are making more requests for completely new files.
CSS can be kind of tricky to organize. Here is an example of how I would typically organize my styles and also my stylesheets directory. This method works for a single namespace (application) or it can be broken out to work for multiple namespaces if need be (i.e. admin, application).
application.sass
// vendor ----------------------------------------------------------------------
// compass
#import "compass/reset"
#import "compass/css3/box-shadow"
#import "compass/css3/border-radius"
#import "compass/css3/box-sizing"
#import "compass/css3/opacity"
#import "compass/layout/sticky-footer"
#import "compass/utilities"
// grid
#import "susy"
// application -----------------------------------------------------------------
// base
// for mixins, variables and helpers to aid in building
// the application. no styling of actual elements should
// go in base.
#import "base/colors"
#import "base/fonts"
#import "base/mixins"
#import "base/grid"
// layout
// generic site styles. this includes site chrome styles
// such as the header, footer, flash messages, nav, as well
// as common patterns used around the site like forms, type,
// links, etc. the loose idea is that you could take these
// styles and create a similar "layout" but it wouldn't
// include contextual patterns like books, originals, etc.
#import "layout/buttons"
#import "layout/content"
#import "layout/header"
#import "layout/flash"
#import "layout/forms"
#import "layout/footer"
#import "layout/links"
#import "layout/tooltips"
#import "layout/typography"
// modules
// elements used on multiple pages that are loosely tied
// to our domain and data structure. examples are dependent
// on the needs of your site. as a general guideline, all
// modules should be used on multiple pages. elements used
// on a single page should be included in views.
#import "modules/articles"
#import "modules/buttons"
#import "modules/forms"
#import "modules/links"
#import "modules/pagination"
#import "modules/users"
#import "modules/stats"
#import "modules/some_other_domain_specific_styling_unique_to_your_site"
// views
// elements used on a single page. these styles are
// often needed to help put finishing touches on a
// page where modules didn't quite line up perfectly,
// or where a page has completely unique elements.
// these styles could often be abstracted to modules
// but lack a reason to do so. keeping them here helps
// explain their singular usage.
#import "views/welcome/index"
#import "views/settings/all"
#import "views/articles/show"
#import "views/users/show"
Organizing your styles in this manner helps to create a single responsibility for each file (which it looks like you are trying to do as well). I've found that this makes your CSS a lot more maintainable. Also, if you need to add media queries or target a specific browser with a given module it gives you a place to do so that is contextually relevant while still keeping your code legible and separate.
Note, the example above would be used if you only had one namespace. If you had an admin section (or something else) you could stick all of these directories/files inside of an "application" directory and create a similar structure for "admin". This would leave you with the following structure in app/stylesheets.
- admin
- application
- admin.sass
- application.sass
You could even create a structure to share items between the two, but that may or may not be necessary. The point is that you have a lot of flexibility and organization for whatever you may need to do. This same structure can also be used for JS if you were so inclined. This circumvents the issue of reloading modules and making new requests.
FWIW, I tried to find a solution to bringing in only what I need per page (your question) but in the end I just ended up passing more bits on the whole while simultaneously increasing my number of requests. YMMV.
Hope this helps to get you on your way!
I solved this by taking a cue from rspec, and creating a _sass_helper.sass partial, which contains all my non-direct-style imports (variables, mixins, placeholders), which is then included at the top of each file. The non-code bit is important, because if _sass_helper.sass contained any styles, they would be written into each file.
This effectively allows me to get the same "Sass environment" for each of my files, without any code duplication.
I have my tree organized like so:
includes/
_variables.sass
_mixins.sass
_extends.sass
posts/
_post_partial_1.sass
_post_partial_2.sass
application.sass
posts.sass
_sass_helper.sass
Then, something like posts.sass would look like:
#import 'sass_helper'
#import 'posts/post_partial_1'
#import 'posts/post_partial_2'
.some.globally.shared.post
styles: here
It works great. The post partials don't need the sass helper, so I end up with one master file per controller, with partials for individual features, and the same environment everywhere.

Resources