How do I add global styles without requiring an extra component? - css

I want to apply some global styles to my website (body, h1, h2, h3, etc).
To do this with Angular2, the view encapsultation of a component needs to be set thusly: encapsulation: ViewEncapsulation.None.
example:
#Component({
selector: 'app-root',
templateUrl: template(),
styleUrls: ['global.scss', 'app.component.scss'],
encapsulation: ViewEncapsulation.None,
})
export class AppComponent {
title = 'Hello world!';
}
The problem is that this encapsulation rule applies to all of this components stylesheets, which means I must have a separate component just for global styles.
Is there another way to do this without requiring an extra component and without needing to edit Angular-CLI's build config?
(I'm using angular/core 2.0.0-rc.5 and angular-cli 1.0.0-beta.11-webpack.2)

The PR mentioned by drbishop has been merged and released as 1.0.0-beta.11-webpack.3.
To upgrade from 1.0.0-beta.11-webpack.2 to 1.0.0-beta.11-webpack.3, run:
npm uninstall -g angular-cli
npm cache clean
npm install -g angular-cli#1.0.0-beta.11-webpack.3
Note: if you get SyntaxError: Unexpected token ... errors on running ng version after upgrading you may need to upgrade to Node.js 6. See https://github.com/angular/angular-cli/issues/1883 for details.
If you generate a new project using 1.0.0-beta.11-webpack.3, you can add a styles.css file to your src directory which will be automatically included in your build. You can also add external CSS imports to the apps[0].styles property of angular-cli.json.
Your angular-cli.json should look something like this for a new project generated by 1.0.0-beta.11-webpack.3:
{
"project": {
"version": "1.0.0-beta.11-webpack.3",
"name": "demo"
},
"apps": [
{
"root": "src",
"outDir": "dist",
"assets": "assets",
"index": "index.html",
"main": "main.ts",
"test": "test.ts",
"tsconfig": "tsconfig.json",
"prefix": "app",
"mobile": false,
"styles": [
"styles.css"
],
"scripts": [],
"environments": {
"source": "environments/environment.ts",
"prod": "environments/environment.prod.ts",
"dev": "environments/environment.dev.ts"
}
}
],
"addons": [],
"packages": [],
"e2e": {
"protractor": {
"config": "./protractor.conf.js"
}
},
"test": {
"karma": {
"config": "./karma.conf.js"
}
},
"defaults": {
"styleExt": "css",
"prefixInterfaces": false,
"lazyRoutePrefix": "+"
}
}

This is currently being designed and will be implemented before a final release. The general idea will be to provide a reference to a style file (CSS/SCSS/LESS...) and have it included within the application.

As mentioned before, it's being implemented for future releases. There's already a pull request to fix this. You can update it manually as a workaround for now.
Then, update your angular-cli.json file:
"apps": [
{
"root": "src",
"outDir": "dist",
"assets": "assets",
"index": "index.html",
"main": "main.ts",
"test": "test.ts",
"tsconfig": "tsconfig.json",
"mobile": false,
"additionalEntries": [
{ "input": "polyfills.ts", "output": "polyfills.js" },
"styles.sass"
],
"environments": {
"source": "environments/environment.ts",
"prod": "environments/environment.prod.ts",
"dev": "environments/environment.dev.ts"
}
}
],

Related

Vuetify works locally but breaks when deployed to firebase, why might this be happening?

I have a website that is hosted through Firebase that uses Vue and Vuetify. Vuetify is only used for one component and the rest of the app uses SCSS for styling. Vuetify has been a recent addition to the project and getting it set up and working locally went fine. However when I tried to deploy my changes to Firebase for the first time since adding Vuetify, the app renders with no styling at all - no Vuetify and no SCSS.
Below are the files I had to change in order to get Vuetify working locally following the installation guide + my firebase.json because it seems relevant.
Part of package.json
{
"scripts": {
"serve": "vue-cli-service serve",
"build": "npm run lint && vue-cli-service build --mode test",
},
"dependencies": {
"core-js": "^2.6.12",
"firebase": "^9.5.0",
"regenerator-runtime": "^0.13.11",
"register-service-worker": "^1.7.2",
"vue": "^2.6.12",
"vuetify": "^2.6.12",
"vuex": "^3.6.2"
},
"devDependencies": {
"#babel/preset-env": "^7.20.2",
"#vue/cli-plugin-babel": "^3.8.0",
"#vue/cli-plugin-eslint": "^3.8.0",
"#vue/cli-plugin-pwa": "^3.8.0",
"#vue/cli-service": "^3.8.0",
"babel-eslint": "^10.1.0",
"imagemin-webpack-plugin": "^2.4.2",
"sass": "^1.32.8",
"sass-loader": "^10.1.1",
"vue-cli-plugin-vuetify": "~2.5.8",
"vue-cli-plugin-webpack-bundle-analyzer": "^4.0.0",
"vue-template-compiler": "^2.6.12",
"vuetify-loader": "^1.7.0"
},
}
plugins/vuetify.js
import Vue from "vue";
import Vuetify from "vuetify/lib/framework";
import "vuetify/dist/vuetify.min.css";
//have deployed with and without the above line to no avail, some stackoverflow threads suggested it but was not in the documentation
Vue.use(Vuetify);
export default new Vuetify({
theme: {
options: {
customProperties: true,
},
themes: {
light: {
primary: "#007BFF",
secondary: "#424242",
accent: "#82B1FF",
error: "#FF5252",
info: "#2196F3",
success: "#4CAF50",
warning: "#FFC107",
},
},
},
icons: {
iconfont: "fa",
},
});
Part of main.js
import "core-js";
import "regenerator-runtime/runtime";
import Vue from "vue";
import vuetify from "#/plugins/vuetify";
var createApp = function() {
if (!app) {
app = new Vue({
router,
store,
vuetify,
data: {},
render: (h) => h(App),
}).$mount("#app");
}
};
bable.config.js
//bable.config.js
module.exports = {
presets: ["#vue/app", "#babel/preset-env"],
};
firebase.json
{
"firestore": {
"rules": "firestore.rules",
"indexes": "firestore.indexes.json"
},
"functions": {
"predeploy": [],
"source": "functions"
},
"hosting": {
"public": "dist",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"headers": [
{ "source":"/service-worker.js", "headers": [{"key": "Cache-Control", "value": "no-cache"}] }
],
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
]
},
"storage": {
"rules": "storage.rules"
},
"database": {
"rules": "database.rules.json"
}
}
Lastly, my vue.config.js also contains the line
transpileDependencies: ["vuetify"],
I've cleared the web browser cache several times and made sure to wrap my Vuetify component within v-app.
npm run build and firebase deploy both run without error but since my app lacks styling after deployment I think something is going wrong with my firebase.json.
Relatively new to Vue, Vuetify, and Firebase so appreciate any explanations or guesses as to why this behavior might be occurring.
Thanks

How do I get Angular 13 to include CSS when running without an Internet connection?

Update 1/2/22: I downgraded to version 11.1.2 (same version as another app of mine which didn't have this issue) and the issue no longer appears. While this allows me to move forward, I more or less circumvented the issue than resolved it. I'll leave this open and hopefully a true fix can be discovered.
Original Post:
I need my Angular 13.0.0 app to run offline (no Internet) and in a war with embedded tomcat. The initial page is a login page and the HTML and Javascript (compiled TS) seem to work fine as logging in reaches the back end successfully and the home page loads. Upon commenting out my styles.scss file and running online, I'm seeing the exact issue. In addition, running offline via Angular CLI does not produce this issue.
I can literally leave the executable war running and disable my wifi to go from having CSS to not having it. The opposite is also true. Based on that, the issue appears to be completely in the front end.
I've done this with other applications but older versions (11.1.2 and 10.0.0-rc.6 and not using embedded containers) this issue doesn't occur. I've reviewed the angular.json files from those applications and I don't see any glaring differences. Did something change in the newer versions of Angular? Otherwise, there’s something I may be missing due to the container being embedded.
The entire app is missing CSS but to keep it simple here is how my login page looks:
Offline:
Online:
Here is my angular.json:
"$schema": "./node_modules/#angular/cli/lib/config/schema.json",
"cli": {
"analytics": false
},
"version": 1,
"newProjectRoot": "projects",
"projects": {
"client": {
"root": "",
"sourceRoot": "src",
"projectType": "application",
"prefix": "app",
"schematics": {
"#schematics/angular:component": {
"style": "scss"
}
},
"architect": {
"build": {
"builder": "#angular-devkit/build-angular:browser",
"options": {
"outputPath": "../src/main/resources/static",
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "src/tsconfig.app.json",
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"src/styles.scss"
],
"scripts": []
},
"configurations": {
"development": {
"sourceMap": true,
"optimization": false
},
"production": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"namedChunks": false,
"aot": true,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"budgets": [
{
"type": "initial",
"maximumWarning": "20mb",
"maximumError": "25mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "20mb",
"maximumError": "25mb"
}
]
}
}
},
"serve": {
"builder": "#angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "client:build:development"
},
"configurations": {
"production": {
"browserTarget": "client:build:production"
}
}
},
"extract-i18n": {
"builder": "#angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "client:build"
}
},
"test": {
"builder": "#angular-devkit/build-angular:karma",
"options": {
"main": "src/test.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "src/tsconfig.spec.json",
"karmaConfig": "src/karma.conf.js",
"styles": [
"src/styles.scss"
],
"scripts": [],
"assets": [
"src/favicon.ico",
"src/assets"
]
}
},
"lint": {
"builder": "#angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"src/tsconfig.app.json",
"src/tsconfig.spec.json"
],
"exclude": [
"**/node_modules/**"
]
}
}
}
},
"client-e2e": {
"root": "e2e/",
"projectType": "application",
"prefix": "",
"architect": {
"e2e": {
"builder": "#angular-devkit/build-angular:protractor",
"options": {
"protractorConfig": "e2e/protractor.conf.js",
"devServerTarget": "client:serve"
},
"configurations": {
"production": {
"devServerTarget": "client:serve:production"
}
}
},
"lint": {
"builder": "#angular-devkit/build-angular:tslint",
"options": {
"tsConfig": "e2e/tsconfig.e2e.json",
"exclude": [
"**/node_modules/**"
]
}
}
}
}
},
"defaultProject": "client"
}
And my client build.gradle file:
plugins {
id "com.github.node-gradle.node" version "3.1.1"
}
node {
version = '17.0.1'
npmVersion = '8.1.0'
download = true
workDir = file("${project.buildDir}/node")
nodeModulesDir = file("${project.projectDir}")
}
task buildClient(type: NpmTask) {
group = 'build'
description = 'Compile client side assets for production'
args = ['run', 'build:prod']
}
buildClient.dependsOn(npm_install)
And finally, my main build.gradle file (there are only two):
buildscript {
ext {
springBootVersion = '2.4.3'
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
plugins {
id 'org.springframework.boot' version "${springBootVersion}"
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id 'java'
}
apply plugin: 'war'
group = 'com.group.'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
repositories {
mavenCentral()
}
task deleteStaticFolder(type: Delete) {
def dirName = "src/main/resources/static"
file( dirName ).list().each{
f ->
delete "${dirName}/${f}"
}
}
processResources.dependsOn('client:buildClient')
println 'Using build.gradle'
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-rest'
// https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-jpa
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-data-jpa', version: '2.3.9.RELEASE'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-data-jdbc'
// https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-tomcat
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-tomcat', version: '2.5.6'
compileOnly 'org.projectlombok:lombok'
implementation 'com.microsoft.sqlserver:mssql-jdbc'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
// https://mvnrepository.com/artifact/com.fasterxml.jackson.dataformat/jackson-dataformat-csv
implementation group: 'com.fasterxml.jackson.dataformat', name: 'jackson-dataformat-csv', version: '2.13.0'
// https://mvnrepository.com/artifact/com.jcraft/jsch
implementation group: 'com.jcraft', name: 'jsch', version: '0.1.55'
// https://mvnrepository.com/artifact/com.unboundid/unboundid-ldapsdk
implementation group: 'com.unboundid', name: 'unboundid-ldapsdk', version: '5.1.4'
// https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-websocket
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-websocket', version: '2.5.6'
}
test {
useJUnitPlatform()
}
I've spent way too much time on this and I'm out of ideas. Things I’ve tried:
Update 12/28/21 - created a simple CSS class (changing the background color) in styles.scss and referenced it in the login component template. With an Internet connection, the class was applied, without a connection it was not.
Different things in the angular.json related to architect/build/configurations/production`
Commenting out the RequestFilter class in my spring boot code
Cleared browser cache to make sure online/offline comparisons are accurate
Network tab:
Offline:
Online:
Console:
Offline:
Online:
The missing theme console warning is suspicious but as it appears even when the CSS is working I am not convinced it's related.
Finally, the Roboto font error is also present in the console for my other apps but doesn't impact their CSS so again I don't believe is causing my CSS to be MIA.
Thank you in advance!

My SASS variables into :root are not interpolated

I'm fairly new to the Nuxt ecosystem. Awesome package that makes our lives much easier.
I'm trying to add sass to my project. After following the documentation my build runs perfectly but my scss files are not being compiled. An example of the problem:
Notice that --thm-font is set to $primaryTypography and not the actual value from the .scss.
I'm expecting to see --thm-font: 'Barlow', sans-serif. I'm assuming that the sass is not being compiled. It is important to note I'm not looking for a component base style but I'm trying to have a main.scss where I will import the component, layouts and many other styles.
_variables.scss
// Base colors
$base: #ee464b;
$baseRgb: (238, 70, 75);
$black: #272839;
$blackRgb: (39, 40, 57);
$grey: #f4f4f8;
// Typography
$primaryTypography: 'Barlow', sans-serif;
#debug $primaryTypography; // -> this one outputs the correct value
:root {
--thm-font: $primaryTypography;
--thm-base: $base;
--thm-base-rgb: $baseRgb;
--thm-black: $black;
--thm-black-rgb: $blackRgb;
--thm-gray: $grey;
}
nuxt.config.js
export default {
mode: 'universal',
loading: { color: '#fff' },
css: [
'~assets/scss/main.scss'
],
plugins: [
],
buildModules: [
],
modules: [
],
optimizedImages: {
optimizeImages: true
},
build: {
extend (config, ctx) {
},
loaders: {
sass: {
prependData: '#import "~#/assets/scss/main.scss";'
}
}
},
server: {
port: process.env.APP_PORT
}
}
package.json
{
"name": "zimed",
"version": "1.1.0",
"description": "Zimed - Vue Nuxt App Landing Page Template",
"author": "Layerdrops",
"private": true,
"scripts": {
"dev": "nuxt",
"build": "nuxt build",
"start": "nuxt start",
"generate": "nuxt generate"
},
"dependencies": {
"#bazzite/nuxt-optimized-images": "^0.3.0",
"nuxt": "^2.0.0",
"sass-loader": "10"
},
"devDependencies": {
"fibers": "^5.0.0",
"sass": "^1.38.2"
}
}
Which configuration am I missing so that .scss files get compiled?
You need to interpolate the variable like this --thm-font: #{$primaryTypography}; in the scope of :root.
Not sure the why of this behavior, but this answer was my way of finding this out.

How to import CSS from node_modules in webpack angular2 app

Let's say that we start with the following starter pack:
https://github.com/angularclass/angular2-webpack-starter
After npm install and npm run start everything works fine.
I want to add an external css module, for example bootstrap 4's css (and only the css). (I know that bootstrap has a bootstrap-loader, but now I'm asking for general solution, so please think about bootstrap 4 here as it could be any other css module that is available via npm).
I install bootstrap via npm: npm install bootstrap#4.0.0-alpha.4 --save
First I thought that it is enough to add import 'bootstrap/dist/css/bootstrap.css'; to the vendor.browser.ts file.
But it isn't.
What should I do to have a proper solution?
Solutions I'm NOT asking for:
"Copy the external css module to the assets folder, and use it from there"
I'm looking for a solution that works together with npm package.
"Use bootstrap-loader for webpack"
As I described above, I'm looking for a general solution, bootstrap is only an example here.
"Use another stack"
I'm looking for a solution in the exact starter pack that I've mentioned above.
It is possible by using #import '~bootstrap/dist/css/bootstrap.css'; on the styles.css file. (Note the ~)
Edit: How it works - The '~' is an alias set on the webpack config pointing to the assets folder... simple as that..
Edit 2: Example on how to configure webpack with the '~' alias...
this should go on the webpack config file (usually webpack.config.js)...
// look for the "resolve" property and add the following...
// you might need to require the asset like '~/bootsrap/...'
resolve: {
alias: {
'~': path.resolve('./node_modules')
}
}
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
So here is a way to import various CSS files using the angular-cli which I find the most convenient.
Basically, you can refer to the CSS files (order is important if you will be overriding them) in the config and angular-cli will take care of the rest. For instance, you might want to include a couple of styles from node-modules, which can be done as follows:
"styles": [
"../node_modules/font-awesome/css/font-awesome.min.css",
"../node_modules/primeng/resources/primeng.min.css",
"styles.css"
]
A sample full-config might look like this:
.angular-cli.json
{
"$schema": "./node_modules/#angular/cli/lib/config/schema.json",
"project": {
"name": "my-angular-app"
},
"apps": [
{
"root": "src",
"outDir": "dist",
"assets": [
"assets",
"favicon.ico"
],
"index": "index.html",
"main": "main.ts",
"polyfills": "polyfills.ts",
"test": "test.ts",
"tsconfig": "tsconfig.app.json",
"testTsconfig": "tsconfig.spec.json",
"prefix": "app",
"styles": [
"../node_modules/font-awesome/css/font-awesome.min.css",
"../node_modules/primeng/resources/primeng.min.css",
"styles.css"
],
"scripts": [],
"environmentSource": "environments/environment.ts",
"environments": {
"dev": "environments/environment.ts",
"prod": "environments/environment.prod.ts"
}
}
],
"e2e": {
"protractor": {
"config": "./protractor.conf.js"
}
},
"lint": [
{
"project": "src/tsconfig.app.json",
"exclude": "**/node_modules/**"
},
{
"project": "src/tsconfig.spec.json",
"exclude": "**/node_modules/**"
},
{
"project": "e2e/tsconfig.e2e.json",
"exclude": "**/node_modules/**"
}
],
"test": {
"karma": {
"config": "./karma.conf.js"
}
},
"defaults": {
"styleExt": "scss",
"component": {}
}
}

How to add css library to project generated with angular-cli#webpack

After creating new project and upgrading it to webpack version I wanted to add bootstrap's CSS.
I tried method descibed in docs [1] but it doesn't seem to work.
I cannot use the cdn version because my users may have to work without acces to external networks.
[1] https://github.com/angular/angular-cli#global-library-installation
"apps": [
{
"styles": [
"node_modules/bootstrap/dist/css/bootstrap.css"
],
...
.
$ ng --version
angular-cli: 1.0.0-beta.11-webpack.2
node: 5.4.1
os: linux x64
or maybe I just don't understand what should happen?
after ng build in dist dir there is no CSS file and there is nothing added to index.html
If you upgrade to 1.0.0-beta.11-webpack.3 or higher, you can use the apps[0].styles property of angular-cli.json to list external stylesheets for import. With this you don't have to add anything to index.html.
To upgrade from 1.0.0-beta.11-webpack.2 to 1.0.0-beta.11-webpack.3, run:
npm uninstall -g angular-cli
npm cache clean
npm install -g angular-cli#1.0.0-beta.11-webpack.3
Note: you may need to upgrade to Node.js 6 if you get SyntaxError: Unexpected token ... errors on running ng version. See https://github.com/angular/angular-cli/issues/1883 for details.
If you generate a new project and install Bootstrap, your angular-cli.json should look something like this:
{
"project": {
"version": "1.0.0-beta.11-webpack.3",
"name": "demo"
},
"apps": [
{
"root": "src",
"outDir": "dist",
"assets": "assets",
"index": "index.html",
"main": "main.ts",
"test": "test.ts",
"tsconfig": "tsconfig.json",
"prefix": "app",
"mobile": false,
"styles": [
"styles.css",
"../node_modules/bootstrap/dist/css/bootstrap.min.css"
],
"scripts": [],
"environments": {
"source": "environments/environment.ts",
"prod": "environments/environment.prod.ts",
"dev": "environments/environment.dev.ts"
}
}
],
"addons": [],
"packages": [],
"e2e": {
"protractor": {
"config": "./protractor.conf.js"
}
},
"test": {
"karma": {
"config": "./karma.conf.js"
}
},
"defaults": {
"styleExt": "css",
"prefixInterfaces": false,
"lazyRoutePrefix": "+"
}
}
I think that you have to add ../ front of the node_modules, because node_modules folder is one step up in the directory tree.
Like this:
"../node_modules/bootstrap/dist/css/bootstrap.css"
All your css files from apps[0].styles property of angular-cli.json during ng build are compiled into styles.bundle.js and this file is included in index.html. If you check this file you can found there all styles. So it works as intended.

Resources