Ionic3 : the best way to import css from node_modules - css

I am trying to import the .css from full-calendar package.
First, I created a new component my-calendar (html, scss, ts).
Then, I tried 3 different ways but only the last one worked for me:
Reference the file directly, as the documentation suggested, in the index.html (it does not work because the reference to node_modules is lost when you build the project)
<link href="node_modules/fullcalendar/dist/fullcalendar.min.css" rel="stylesheet">
Adding #import "~fullcalendar/dist/fullcalendar.min.css"; in my-calendar.scss. If I am not wrong, this should add the style into main.css when the project is being built (is not working)
Create custom copy config (copy.config.js)
module.exports = {
...
copyFullCalendar: {
src: ['{{ROOT}}/node_modules/fullcalendar/dist/fullcalendar.min.css'],
dest: '{{BUILD}}'
}
}
and adding #import "fullcalendar.min.css"; into my-calendar.scss
UPDATE:
and adding #import "fullcalendar"; into my-calendar.scss
to avoid compiler errors when use ionic build --aot --minifycss --minifyjs
I would appreciate if someone could clarify the best way and explain if I misunderstood some concept.
PS: Remember that I am working with Ionic3 and I am not using the Angular CLI.

third method of yours will be the best way to implement , but it can be done in another way more like ionic.
You need to make use of the includePaths when configuring the custom path , as we are dealing with custom css, add sass.config.js to local project folder where we configure custom includePaths like this
includePaths: [
....
'node_modules/ap-angular2-fullcalendar'
],
In package.json scripts to include custom css configuration file, like this:
"scripts": {
.....
"ionic:serve": "ionic-app-scripts serve -s ./config/sass.config.js"
},
Only problem with this implementation is when you update ionic-app-scripts you have to compare the native sass.config.js file to the local file and check if there is anything changed.
This is a troublesome method and an issue was raised in Github but unfortunately they closed the issue with the following justification
Configs are extended, so only include the fields that you're changing.
Everything else will inherit the defaults.

As of #ionic/app-scripts : 3.2.0, it seems you'll still need to
#include FILE; somewhere
See this closed issue on app script's github
I found that as of
'Ionic Framework : ionic-angular 3.9.2'
you have two choices insert your import in src/theme/variables.scss or src/app/app.scss.
For example in variables.scss
/* some declarations here */
#import 'insrctest';/*file sits in src/test/insrctest.scss*/
And in my custom.config.js
includePaths: [
'node_modules/ionic-angular/themes',
'node_modules/ionicons/dist/scss',
'node_modules/ionic-angular/fonts',
'./src/test', /* when the import above gets called, node-sass will look in here */

Related

How to make module css works with typescript in a gatsby application?

I have an GastbyJS application, and I'm trying to add typescript on it. I solve most of the issues, but I'm not able to make the css module work with it.
I have this import in my file, that works fine:
import styles from "./card.module.css"
But when I added the typescript config it says that Cannot find module './card.module.css'.ts(2307)
I tried to use some gatsby plugins, but they didn`t work as expected.
The whole code is here: github
I had the same problem and after trying all the various plugins I came across this solution which worked for me.
Create a css.d.ts file with:
declare module '*.css' {
const content: { [className: string]: string };
export default content;
}
Add these lines to your tsconfig.json file:
"esModuleInterop": true,
"files": ["./src/typings/css.d.ts"]
The "files" path needs to match where your type definition file is.
https://github.com/thetrevorharmon/gatsby-starter-typescript-sass/issues/1#issuecomment-436748732

How to find css file of scss file in angular project

I have created the angular project in VS Code using the following command.
ng new my-app --style=scss
by following this github link
Now every style sheet that is being created using angular-cli is with extension of .scss instead of .css
Now there is a requirement to check that how Sass is being converted to css because I am new to Sass. I am facing some issues in designing thus it would be nice for me to look at css file.
I have searched in those folder where scss file exists but there I couldn't find css file. Please help
Update
Look at this picture, when I created the component using cli, it created .scss instead of css so I need to look for css file.
I've been able to find a way to view my compiled .scss files as a .css file.
Before I only saw the raw .scss files when inspecting from Chrome.
The trick was setting some flags in the angular.json file so it will tell webpack (what angular-cli uses to build the app) that I want the .scss files served as .css along with a sourcemap of the file:
./angular.json
{
...
"projects": {
"my-prject": { <-- or whatever your project is named
"architect": {
"configurations": {
"production": { // <-- production is default, you might be working w/ custom configurations [development, test, w/e]
...
"sourceMap": true, <-- will serve source maps w/ the file so you can view it in the browser easily
"extractCss": true, <-- actually serve the .css files and not the .scss files
...
}
}
}
}
}
}
Once that is updated, restart the dev server or rebuild your application
then you can go into chrome dev tools and look at find the styles.css file (or whatever you have the file name set to) and view it:
If you are working on local then:
local {
"sourceMap": true,
...
}
Sass in Angular 2 are always converted into Css in run time when you compile and build the project. However if you are using any other environment like Gulp tasks and watches, you can run 'sass --watch input.scss output.css'
As folks have already mentioned, the css is built at runtime. You can still set the result using inspect in chrome or firefox.
It's definitely a requirement to check the generated CSS when you find something wrong and Chrome Inspector can't help! So this is definitely a good question, which is why I'm here.
To summarize, #y_vyshnevska is right that "you may find your css inlined in script tags at the end of head", and he also gave an in-depth link: https://blog.angularindepth.com/this-is-how-angular-cli-webpack-delivers-your-css-styles-to-the-client-d4adf15c4975 on the topic. I put it here in case you neglect it.
It looks not possible to view compiled css files at a runtime.
However, you can do the following trick: angular applies components' styles using <style> attribute. Find the one you need in elements inspector (you can search there using ctrl (or cmd) + f.
After you've found the stylesheet you need, you'll see it's truncated. To see the entire content, click on the style element and select "Store as global variable". After that in console run
copy(Object.values(temp1.sheet.cssRules).map(r => r.cssText).join('\n'))
This will copy all css to your buffer

How could I make Aurelia include my styles as external styles via <link>?

I am trying to set up the conjunction of Atom editor, Sass, Typescript and Aurelia. This question is about Aurelia (installed via aurelia-cli) and its building system, I guess.
Well, I wrote style.sass for my component, then I required it in the component's view (app.html, for instance) as style.css. Fine, it works. But the content of compiled style.css gets included in index.html as internal styles, I mean everything goes inside <style>-tag, not through <link>. Also it seems that the corresponding .css file is never created at all. The stream just includes its content right in <style>-tag inside index.html.
How could I make Aurelia include my styles as external styles via <link>? In building task the last action is a build-plugin coming from aurelia-cli which is kinda black-box for me. Also aurelia.json is imported, so there should be a way to configure the needed behavior. A quick search didn't give me the answer, so here I am.
This is probably not the best solution, and not completely what you want, but perhaps it helps. You can do the following (I took a new TypeScript project):
First remove the css includes from your views.
Then, adjust the ./aurelia_project/tasks/process-css.ts task as follows:
import * as gulp from 'gulp';
import * as sourcemaps from 'gulp-sourcemaps';
import * as sass from 'gulp-sass';
import * as project from '../aurelia.json';
import {build} from 'aurelia-cli';
export default function processCSS() {
return gulp.src(project.cssProcessor.source)
.pipe(sourcemaps.init())
.pipe(sass().on('error', sass.logError))
.pipe(gulp.dest(project.platform.output));
};
This will output CSS files in the ./scripts folder. Then, adjust the aurelia_project/aurelia.json file as follows (remove css):
{
"name": "app-bundle.js",
"source": [
"[**/*.js]",
"**/*.{html}"
]
},
In your index.html you can now include the generated styles (or even in your components views).

How can I customise Bootstrap without losing the changes?

I'm using Bower to manage Bootstrap and would like to make some changes (colours, font size etc) to the default Bootstrap look and feel. Here's my workflow:
Edit bower_components/bootstrap/less/variables.less
Recompile bootstrap using grunt build
The problem is that I want to be able to upgrade bootstrap when a new version comes out and presumably I'll lose my changes to variables.less.
Is there a way I can keep my changes outside of bower_components and also avoid having bower_components in source control since it's 122MB?
you can create a variables-custom.less and import it into theme.less like this:
//
// Load core variables and mixins
// --------------------------------------------------
#import "variables.less";
//import custom-variables after variables so the values will override.
#import "custom-variables.less"; //only has variables that have changed.
#import "mixins.less";
IMO this is a little bit better than the first solution because you wont have to load two (almost) identical CSS files on the client.
I'm sorry I cant help you with what to to about Bower and your source control as I do not use Bower
Here's the solution which worked for me:
Use bower to install all UI packages e.g. bower install bootstrap chosen
Create a separate folder less which contains all the LESS modifications. This article was very helpful here.
Here's my less/styles.less file:
#import "../bower_components/bootstrap/less/bootstrap.less";
#import "../bower_components/bootstrap-chosen/bootstrap-chosen.less";
//My custom variables - overrides the bootstrap variables file
#import "variables-custom.less";
Use grunt to monitor changes within the less folder and compile them into .css
Here's my Gruntfile.js (thanks to this answer):
module.exports = function(grunt) {
grunt.initConfig({
less: {
development: {
options: {
paths: ["./less"],
yuicompress: true
},
files: {
"./static/css/styles.css": "./less/styles.less"
}
}
},
watch: {
files: "./less/*",
tasks: ["less"]
}
});
grunt.loadNpmTasks('grunt-contrib-less');
grunt.loadNpmTasks('grunt-contrib-watch');
};
This is indeed the best customization method. You create a theme.less and pull in original Bootstrap files (which can get upgraded in the future) and in the same file you call your own custom overrides. Either you #import them from a custom file which is not in the Bower directory or you just write your custom rules in your theme.less itself. You'll find this technique explained in this tutorial as well.
With Grunt, custom setups can get tricky. But with Brunch it's a piece of cake (yes!) and all pretty much goes automatically. Your grandma could do it.
As for avoiding the inclusion of bower_components in source control: with Git it's easy. You just check-in your bower.json but make sure to add /bower_components to your .gitignore file.
You should just create your own style sheet, use both with your custom one listed secondly. That way you can make changes but not change bootstrap at all.
Also, when you update, you keep your style sheet the same.
This allows you to change bits and pieces of Bootstrap but not actually changing the file, you're overriding it.
To be clear, your second CSS file would be SIGNIFICANTLY smaller... Only putting things your needed to change in it.

Import regular CSS file in SCSS file?

Is there anyway to import a regular CSS file with Sass's #import command? While I'm not using all of the SCSS syntax from sass, I do still enjoy it's combining/compressing features, and would like to be able to use it without renaming all of my files to *.scss
After having the same issue, I got confused with all the answers here and the comments over the repository of sass in github.
I just want to point out that as December 2014, this issue has been resolved. It is now possible to import css files directly into your sass file. The following PR in github solves the issue.
The syntax is the same as now - #import "your/path/to/the/file", without an extension after the file name. This will import your file directly. If you append *.css at the end, it will translate into the css rule #import url(...).
In case you are using some of the "fancy" new module bundlers such as webpack, you will probably need to use use ~ in the beginning of the path. So, if you want to import the following path node_modules/bootstrap/src/core.scss you would write something like #import "~bootstrap/src/core".
NOTE:
It appears this isn't working for everybody. If your interpreter is based on libsass it should be working fine (checkout this). I've tested using #import on node-sass and it's working fine. Unfortunately this works and doesn't work on some ruby instances.
This was implemented and merged starting from version 3.2 (pull #754 merged on 2 Jan 2015 for libsass, issues originaly were defined here: sass#193 #556, libsass#318).
To cut the long story short, the syntax in next:
to import (include) the raw CSS-file the syntax is **without `.css`** extension at the end (results in actual read of partial `s[ac]ss|css` and include of it inline to SCSS/SASS):
#import "path/to/file";
to import the CSS-file in a traditional way syntax goes in traditional way, **with `.css` extension** at the end (results to `#import url("path/to/file.css");` in your compiled CSS):
#import "path/to/file.css";
And it is damn good: this syntax is elegant and laconic, plus backward compatible! It works excellently with libsass and node-sass.
__
To avoid further speculations in comments, writing this explicitly: Ruby based Sass still has this feature unimplemented after 7 years of discussions. By the time of writing this answer, it's promised that in 4.0 there will be a simple way to accomplish this, probably with the help of #use. It seems there will be an implementation very soon, the new "planned" "Proposal Accepted" tag was assigned for the issue #556 and the new #use feature.
UPD: on 26 October 2020 lib-sass was deprecated, therefore issue #556 was immediately closed.
__
answer might be updated, as soon as something changes.
Looks like this is unimplemented, as of the time of this writing:
https://github.com/sass/sass/issues/193
For libsass (C/C++ implementation), import works for *.css the same way as for *.scss files - just omit the extension:
#import "path/to/file";
This will import path/to/file.css.
See this answer for further details.
See this answer for Ruby implementation (sass gem)
You must prepend an underscore to the css file to be included, and switch its extension to scss (ex: _yourfile.scss). Then you just have to call it this way:
#import "yourfile";
And it will include the contents of the file, instead of using the CSS standard #import directive.
Good news everyone, Chris Eppstein created a compass plugin with inline css import functionality:
https://github.com/chriseppstein/sass-css-importer
Now, importing a CSS file is as easy as:
#import "CSS:library/some_css_file"
If you have a .css file which you don't wish to modify, neither change its extension to .scss (e.g. this file is from a forked project you don't maintain), you can always create a symlink and then import it into your .scss.
Creates a symlink:
ln -s path/to/css/file.css path/to/sass/files/_file.scss
Imports symlink file into a target .scss:
#import "path/to/sass/files/file";
Your target output .css file is going to hold contents from imported symlink .scss file, not a CSS import rule (mentioned by #yaz with highest comment votes). And you don't have duplicated files with different extensions, what means any update made inside initial .css file immediately gets imported into your target output.
Symbolic link (also symlink or soft link) is a special type of file
that contains a reference to another file in the form of an absolute
or relative path and that affects pathname resolution.
– http://en.wikipedia.org/wiki/Symbolic_link
You can use a third-party importer to customise #import semantics.
node-sass-import-once, which works with node-sass (for Node.js) can inline import CSS files.
Example of direct usage:
var sass = require('node-sass');,
importOnce = require('node-sass-import-once');
sass.render({
file: "input.scss",
importer: importOnce,
importOnce: {
css: true,
}
});
Example grunt-sass config:
var importOnce = require("node-sass-import-once");
grunt.loadNpmTasks("grunt-sass");
grunt.initConfig({
sass: {
options: {
sourceMap: true,
importer: importOnce
},
dev: {
files: {
"dist/style.css": "scss/**/*.scss"
}
}
});
Note that node-sass-import-once cannot currently import Sass partials without an explicit leading underscore. For example with the file partials/_partial.scss:
#import partials/_partial.scss succeeds
#import * partials/partial.scss fails
In general, be aware that a custom importer could change any import semantics. Read the docs before you start using it.
If I am correct css is compatible with scss so you can change the extension of a css to scss and it should continue to work. Once you change the extension you can import it and it will be included in the file.
If you don't do that sass will use the css #import which is something you don't want.
I figured out an elegant, Rails-like way to do it. First, rename your .scss file to .scss.erb, then use syntax like this (example for highlight_js-rails4 gem CSS asset):
#import "<%= asset_path("highlight_js/github") %>";
Why you can't host the file directly via SCSS:
Doing an #import in SCSS works fine for CSS files as long as you explicitly use the full path one way or another. In development mode, rails s serves assets without compiling them, so a path like this works...
#import "highlight_js/github.css";
...because the hosted path is literally /assets/highlight_js/github.css. If you right-click on the page and "view source", then click on the link for the stylesheet with the above #import, you'll see a line in there that looks like:
#import url(highlight_js/github.css);
The SCSS engine translates "highlight_js/github.css" to url(highlight_js/github.css). This will work swimmingly until you decide to try running it in production where assets are precompiled have a hash injected into the file name. The SCSS file will still resolve to a static /assets/highlight_js/github.css that was not precompiled and doesn't exist in production.
How this solution works:
Firstly, by moving the .scss file to .scss.erb, we have effectively turned the SCSS into a template for Rails. Now, whenever we use <%= ... %> template tags, the Rails template processor will replace these snippets with the output of the code (just like any other template).
Stating asset_path("highlight_js/github") in the .scss.erb file does two things:
Triggers the rake assets:precompile task to precompile the appropriate CSS file.
Generates a URL that appropriately reflects the asset regardless of the Rails environment.
This also means that the SCSS engine isn't even parsing the CSS file; it's just hosting a link to it! So there's no hokey monkey patches or gross workarounds. We're serving a CSS asset via SCSS as intended, and using a URL to said CSS asset as Rails intended. Sweet!
To import a regular CSS file into Sass:
Official Sass Documentation: Import CSS into Sass
Simple workaround:
All, or nearly all css file can be also interpreted as if it would be scss. It also enables to import them inside a block. Rename the css to scss, and import it so.
In my actual configuration I do the following:
First I copy the .css file into a temporary one, this time with .scss extension. Grunt example config:
copy: {
dev: {
files: [
{
src: "node_modules/some_module/some_precompiled.css",
dest: "target/resources/some_module_styles.scss"
}
]
}
}
Then you can import the .scss file from your parent scss (in my example, it is even imported into a block):
my-selector {
#import "target/resources/some_module_styles.scss";
...other rules...
}
Note: this could be dangerous, because it will effectively result that the css will be parsed multiple times. Check your original css for that it contains any scss-interpretable artifact (it is improbable, but if it happen, the result will be hard to debug and dangerous).
to Import css file in to scss simply use the this:
#import "src/your_file_path";
without using extension .css at the end
It is now possible using:
#import 'CSS:directory/filename.css';
I can confirm this works:
class CSSImporter < Sass::Importers::Filesystem
def extensions
super.merge('css' => :scss)
end
end
view_context = ActionView::Base.new
css = Sass::Engine.new(
template,
syntax: :scss,
cache: false,
load_paths: Rails.application.assets.paths,
read_cache: false,
filesystem_importer: CSSImporter # Relevant option,
sprockets: {
context: view_context,
environment: Rails.application.assets
}
).render
Credit to Chriss Epstein:
https://github.com/sass/sass/issues/193
Simple.
#import "path/to/file.css";

Resources