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 inangular-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
Install the normalize.css library:
npm install --save normalize.css
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:
npm i normalize.css
- add
"../node_modules/normalize.css/normalize.css"
inapps[0].styles
in the config fileangular-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
andmaterialize.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
How to Style Form Drop Down Lists
CSS: Styling The Content of Before Pseudo Element on a List
How to Select Multiple Input Field Types with CSS
Why Can't an <Ul> (With Absolute Position) Inside a <Li> (With Relative Position) Auto Size
When and Why Should We Use View Encapsulation in Angular
Object Oriented CSS: Should It Matter
Remove All Borders on a Specific Datatable
HTML.Actionlink with a Specified HTML Id
Remove or Add Class in Angular
Is Browser Prefix Still Required for Linear-Gradient
Regression Testing for Styling and Layout of Web Applications
Make Empty Div of One Line Height
Make Flex Item Full Width After It's Been Wrapped Without Using Media Queries
Adding CSS Class to Multiple Elements
Bootstrap Amazon Style Search Bar