Keeping CSS Out of Js in Angular 2/Angular-Cli

Keeping CSS out of JS in Angular 2/Angular-CLI

This is the whole point of encapsulated components.

A component should have it's own styles encapsulated with it so it can be shipped with the styles.

Imagine you want to publish one of your components to be used by others, shouldn't it have its own styles with it ?

That means Angular needs a way to link those css to the component , thus seperates them into chunks and injects them into head tag.

To solve your problem though , you have couple of options :

1- Not using the Emulated Encapsulation :

Components by default have a property called encapsulation which is set to Emulated , you need to change it to None:

@Component({
encapsulation:ViewEncapsulation.None
})

Then , you can put all you css in the head tag your self like you'd do with a normal html page.

2- If the problem is theme ing , you can make your component themeable .

You can have a theme attribute for your component and then based on that change the styleing :

@Component({
selector:'my-component',
styles:[
`
:host{
[theme="blue"]{

change what ever you want :

h1{
color:blue;
}
}

}
`
]
})

And then , using this component would be like :

  <my-component [attr.theme]='"blue"'></my-component> // would be blue theme
<my-component></my-component> // would be default

how to make an extra copy of css within angular app

I think we found a convenient way to accomplish this. We're continuing to allow the app to use the default js way of packaging the styles, but we've also done the following:

First we added the "--extract-css" flag to our ng build command.

Then, in the styles.scss file, we are adding each component's scss file individually, like this:

 @import "app/pages/report/pdf/report-preview/report-preview.component";

When the app is built, we're seeing the styles from the components appearing in the main.css file - as well as in the .js versions that the app is using.

angular-cli how to add global styles?

As of the beta.14 release of the CLI (which uses Angular 2.0 final), a global stylesheet can be linked inside angular-cli.json under the "styles" key. This is a reference to a file relative to the src/ directory, which is style.css by default.

Leveraging this method you could:

  • Copy the global styles into src/styles.css
  • Use CSS imports to import external rules into styles.css
  • Add more global styles via the apps[0].styles property in angular-cli.json

See also Global Styles in angular-cli's wiki.

How to adjust import order of .css files in Angular

You need to change to,

"styles": [
"styles.css"
],

Then,
Link all CSS files in styles.css.
Include all files at the top of the styles.css file.

@import url('~bootstrap/dist/css/bootstrap.min.css');
@import url('deeppurple-amber.css');
@import url('~@angular/material/prebuilt-themes/deeppurple-amber.css');
@import url('another_css_file_from_angular_material.css');
@import url('app.component.css');
@import url('current-vehicle.component.css');

I hope this will work.

Is it possible to build separate CSS file with angular-cli?

You can do this using --extract-css flag of ng build. This is the default in --prod mode. More details here: https://github.com/angular/angular-cli/wiki/build

Angular 2: How to correctly automatically import normalize.css

Update for Angular 8

  1. Install the normalize.css library:

    npm install --save normalize.css
  2. Import it in your styles.css

    @import '~normalize.css';

With the current (1.0.0-beta.15) version of angular-cli, the solution is quite easy:

  1. npm i normalize.css
  2. add "../node_modules/normalize.css/normalize.css" in apps[0].styles in the config file angular-cli.json

Note: If using Angular 7, the config file is now angular.json, and the path to normalise.css in apps[0].styles should be "../node_modules/normalize.css/normalize.css".

Example:

{
"project": {
"version": "1.0.0-beta.15",
"name": "normalize.css-in-angular2"
},
"apps": [
{
"root": "src",
"outDir": "dist",
"assets": "assets",
"index": "index.html",
"main": "main.ts",
"test": "test.ts",
"tsconfig": "tsconfig.json",
"prefix": "app",
"mobile": false,
"styles": [
"../node_modules/normalize.css/normalize.css",
"styles.css"
],
"scripts": [],
"environments": {
"source": "environments/environment.ts",
"dev": "environments/environment.ts",
"prod": "environments/environment.prod.ts"
}
}
],
"addons": [],
"packages": [],
"e2e": {
"protractor": {
"config": "./protractor.conf.js"
}
},
"test": {
"karma": {
"config": "./karma.conf.js"
}
},
"defaults": {
"styleExt": "css",
"prefixInterfaces": false
}
}

How to import CSS from node_modules in webpack angular2 app

You won't be able to import any css to your vendors file using that stack, without making some changes.

Why? Well because this line:

import 'bootstrap/dist/css/bootstrap.css';

It's only importing your css as string, when in reality what you want is your vendor css in a style tag. If you check config/webpack.commons.js you will find this rule:

 {
test: /\.css$/,
loaders: ['to-string-loader', 'css-loader']
},

This rule allows your components to import the css files, basically this:

@Component({
selector: 'app',
encapsulation: ViewEncapsulation.None,
styleUrls: [
'./app.component.css' // this why you import css as string
],

In the AppComponent there's no encapsulation, because of this line encapsulation: ViewEncapsulation.None, which means any css rules will be applied globally to your app. So you can import the bootstrap styles in your app component:

@Component({
selector: 'app',
encapsulation: ViewEncapsulation.None,
styleUrls: [
'./app.component.css',
'../../node_modules/bootstrap/dist/css/bootstrap.css'
],

But if you insist in importing to your vendor.ts then you will need to install a new loader, npm i style-loader --save-dev this will allow webpack to inject css to your page. Then you need to create a specific rule, on your webpack.common.js and change the existing one:

 { //this rule will only be used for any vendors
test: /\.css$/,
loaders: ['style-loader', 'css-loader'],
include: [/node_modules/]
},
{
test: /\.css$/,
loaders: ['to-string-loader', 'css-loader'],
exclude: [/node_modules/] //add this line so we ignore css coming from node_modules
},

The firs rule will be only applied when you try to import css, from any package inside node_modules the second rule will be applied to any css that you import from outside the node_modules

Integrate materialize in a Angular2 project with webpack and SCSS

There are many ways to use MaterializeCSS framework.

Few things to keep in mind before going to installation

  • It is not a CSS only framwork, though it has CSS name in it. We can use its SCSS too
  • It is not built for Angular
  • It is a component framework too built on jquery. Though we are not supposed to use jquery ( not suggested ) in angular, still we import .

You can use any of the following methods:

  • CDN
  • Assets
  • Include in Angular (NPM)

Each has its own advantages and disadvantages.

CDN

Just add this to index.html and you are good to go .

 <!-- Compiled and minified CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.98.2/css/materialize.min.css">

<!-- We need jquery first -->
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>

<!-- Compiled and minified JavaScript -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.98.2/js/materialize.min.js"></script>

Assets

Add it as an asset in your project. This helps in not depending on internet when building and running locally.

Download jQuery

Download CSS version

  • Extract them
  • Copy materialize.min.css, jquery-3.2.1.min.js and materialize.min.js in your assets folder
  • add them to index.html

    <link rel="stylesheet" href="./assets/materialize.min.css" >
    <script src="./assets/jquery-3.2.1.min.js"></script>
    <script src="./assets/materialize.min.js"></script>

Include in angular ( NPM)

In this method we directly include the files to our angular build. I am assuming the angular project is built with @angular/cli for simplicity.

Do

npm install materialize-css --save 
npm install jquery --save
npm install url-loader --save

Add the following to .angular-cli.json:

"styles": [
"styles.scss"
]

"scripts":[
"../node_modules/jquery/dist/jquery.js",
"../node_modules/materialize-css/dist/js/materialize.js"
]

Inside styles.scss , add this :

$roboto-font-path: "~materialize-css/dist/fonts/roboto/";
@import "~materialize-css/sass/materialize";

Integration with Angular:

The above all installation methods provide full functionality with materialize and no need to further install anything to work in angular.
Take any example and just use the appropriate HTML structure inside the HTML part of angular components and you are good to go.

In some instances you might need to tinker with javascript and for that we need to use jQuery. Instead of that we can use the angular wrapper developer at angular2-materialize. I developed a full functional site using angular and materialize and never felt a need for that.

If you still believe you need it . You can install as follows :

  • Install materialize with any of the above mentioned ways
  • Install angular2-materialize

    npm install angular2-materilize --save 

    Add in angular app.module.ts

    import { MaterializeModule } from "angular2-materialize";

    @NgModule({
    imports: [
    //...
    MaterializeModule,
    ],
    //...
    })

Follow other examples provided in the home page of angular2-materialize

What is the equivalent of ngShow and ngHide in Angular 2+?

The hidden property can be used for that

[hidden]="!myVar"

See also

  • https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/hidden

issues

hidden has some issues though because it can conflict with CSS for the display property.

See how some in Plunker example doesn't get hidden because it has a style

:host {display: block;}

set. (This might behave differently in other browsers - I tested with Chrome 50)

workaround

You can fix it by adding

[hidden] { display: none !important;}

To a global style in index.html.

another pitfall

hidden="false"
hidden="{{false}}"
hidden="{{isHidden}}" // isHidden = false;

are the same as

hidden="true"

and will not show the element.

hidden="false" will assign the string "false" which is considered truthy.

Only the value false or removing the attribute will actually make the element
visible.

Using {{}} also converts the expression to a string and won't work as expected.

Only binding with [] will work as expected because this false is assigned as false instead of "false".

*ngIf vs [hidden]

*ngIf effectively removes its content from the DOM while [hidden] modifies the display property and only instructs the browser to not show the content but the DOM still contains it.



Related Topics



Leave a reply



Submit