Duplicated styles on head and a lot of <style> elements - javascript

I'm quite happy with angular-material2 components but there are some weird behaviors that I don't understand and they don't have a proper documentation especially for teeming and customizing their components.
My project looks like:
.src
--app
--components
--login-component
login-component.html
login-component.scss
login-component.js
--login-component
home-component.html
home-component.scss
home-component.js
--and so on ...
app.component.html
app.component.scss
app.component.ts
app.module.ts
app.routing.ts
--assets
--environments
--scss
styles.scss
_material2-theme.scss
_variables-scss
_utilities.scss
_reset.scss
favicon
index.html
and so on ....
In angular-cli.json I have modified the styles to look at scss/style.scss
...
"styles": [
"scss/styles.scss"
]
...
the _material2-theme.scss looks like:
//////////////////////* THEMES */ Custom Blue Theme*/
#import '~#angular/material/theming';
#include mat-core();
$app-primary: mat-palette($mat-light-blue);
$app-accent: mat-palette($mat-light-blue, A200, A100, A400);
$app-theme: mat-light-theme($app-primary, $app-accent);
#include angular-material-theme($app-theme);
/*default palette forground/background*/
$light-foreground-palette: map-get($app-theme, foreground);
$light-background-palette: map-get($app-theme, background);
$primary: map-get($app-theme, primary);
$accent: map-get($app-theme, accent);
and inside of style.scss I am importing everything to be compiled with scss cli compiler
//////////////////////* CUSTOM */
#import "_material2-theme.scss";
#import "_reset.scss";
#import "_utilities.scss";
//////////////////////* COMPONENTS */
#import "~app/components/login/login.component.scss";
My question is after the scss is compiled we have in html head many style tags some of them duplicated and look like:
Everything seems to be compiled in one style that is added in head(tha one that has type attribute) and and after that each scss component splited in each css component with its separate style in head, and that is very weird. I am doing something wrong or is just tha way is working material2?

The behavior you're seeing is caused by ViewEncapsulation.Emulated defined for material components.
First, you don't need to add styles for components to the global styles "scss/styles.scss":
//////////////////////* COMPONENTS */
#import "~app/components/login/login.component.scss";
If you do that, besides your styles getting duplicated you will lose style encapsulation because styles added for components/login/login.component.scss will become global.
Now, to the question why there are many style elements. When you use ViewEncapsulation.Emulated, and it's a default view encapsulation mode, Angular will put each component's style into its own style tag and add attribute to elements inside a component template. In material all components use emulated encapsulation mode so for each component the style tag is added.
If you add #Component({..., encapsulation: ViewEncapsulation.Native }) for your components, you will see the style for your components will be removed.
Here is the logic that adds the style tag:
export class DomSharedStylesHost extends SharedStylesHost implements OnDestroy {
...
private _addStylesToHost(styles: Set<string>, host: Node): void {
styles.forEach((style: string) => {
const styleEl = this._doc.createElement('style'); <--- creates a style element
styleEl.textContent = style;
this._styleNodes.add(host.appendChild(styleEl));
});
}

In Material design for Angular the stylesheet is split into:
style - margins, paddings etcetera that is linked from the component
theme - mostly colors that is build using the theme scss
typography - fonts & font properties that is built using the typography scss
This causes similar selectors, but with different properties inside.
I think it is the live development server that comes with angular cli or webpack that loads css dynamically which causes duplication of style tags. I believe this is not happening in a production build.
PS. Strange of you to add _reset.scss after anything else.

I do not think it is due to having separate styles for each component.
This issue is similar to what's there in a ngularjs-material as well.
Angular-material includes some default theme css as a const variable in JavaScript.
You can read a more on this issue ,
https://stackoverflow.com/questions/33466779/how-to-get-rid-off-angular-material-extra-styles-and-css-linked-by-it-forcefull

In development, the angular cli or webpack compiles every css/scss files from each component to a style tag in the HTML page.
ie, in your case: login-component.scss, home-component.scss each will be loaded inside seperate style tags in the HTML page.
All these will be compiled into a single css file and will be linked in index.html in production conf.
So I too think its the way angular works!
Currently I see that there is only one file generated in production build ng build --prod .

There are multiple style tag in your head may be your every component is linked with some external different css Or you have written internal css at related HTML page.
If you want that there is only one style tag throughout application then in that case you have to write all style in single file.

Related

Can I use v-if with style tag to choose a different source file? Or is there a better alternative?

I tried doing the example below, but it would not work. The reason why I am trying to do this is is that I would have to add way too many modifiers (--tuned) to make this work. So I was trying to source the css file based on a condition. Why would this not work and does anyone know if there is a better alternative that a million modifiers ?
<style v-if="!isTuningActive" lang="scss" src="./normal-version.scss"></style>
<style
v-else
lang="scss"
src="./tuned-version.scss"
></style>
Why not separate into components? Each components with his own styling.
https://vuejs.org/guide/essentials/component-basics.html
You can compile your separate scss files into a single stylesheet (main.scss for example), then just import that main.scss file into your parent component (likely, App.vue).
This will allow you to simply switch the css class on your example above instead of trying to conditionally import stylesheets.
For example, lets say your new 'main.scss' file contains the following scss.
.tuned-version {
p { color: red }
}
.untuned-version {
p { color: blue }
}
Then you'll simply need to dynamically add the class depending on your isTuningActive property.
<div :class="isTuningActive ? 'tuned-version' : 'untuned-version">
<p>My content</p>
</div>
Helpful references:
Compiling scss in Vue: https://vue-loader.vuejs.org/guide/pre-processors.html#sass
Dynamic class binding: https://vuejs.org/guide/essentials/class-and-style.html#binding-html-classes

ReactJS - JSS - createUseStyles - how to generate inline style

I am using ReactJS/NextJS and
import { createUseStyles } from 'react-jss'
to generate CSS-in-JS. Is there a way to use react-jss to generate inline CSS?
I would like to add
const styles = ....
...
<Head><style>{styles}</style></Head>
to all my components.
Thank you.
EDIT:
I can see some potential here: https://cssinjs.org/react-jss?v=v10.7.1#server-side-rendering
But I am not sure how to use the SheetsRegistry with NextJs and serveless deployment. I tried adding it to the _app.js but did not work.
EDIT:
Following this: https://github.com/vercel/next.js/tree/canary/examples/with-react-jss/pages , I have been able to make progress.
The new problem is that now ALL OF THE CSS is in the HTML inline. I am using SSR, wouldn't it be possible to only add the CSS of the component involved in this page ?

can I "import" React CSS modules from a string?

I have a React project that uses CSS Modules by importing .css files. e.g. import styles from "./styles/MyComponent.css";
I find myself now in a situation where a component is receiving a customized snippet of CSS as a string in response to a dynamic call to the server.
Is it possible to take this string (which is unknown until runtime) and essentially do the same thing to it that import does to the .css file when it is compiled by webpack?
For example:
import styles from "./styles/MyComponent.css";
//later on in component...
moreStyle = "a string containing valid CSS";
//do *something* here to moreStyle string to do whatever importing does to a file.
myJSX = (
<div className={styles.someClass}>
This div content is styled by someClass
</div>
<div className={moreStyle.someOtherClass}>
This div content needs to be styled by someOtherClass, but obviously this isn't working
</div>
);
You can try this:
import styles from "./styles/MyComponent.js";
myJSX = (
<div style={styles.someClass}>
This div content is styled by someClass
</div>
<div style={styles.someOtherClass}>
This div content needs to be styled by someOtherClass, but obviously this isn't working
</div>
);
Consider creating a serialized object, instead.
// Filename: MyComponentStyle.js
//Example styles
export const styles = {
someClass: { height: 10 },
someOtherClass: {
backgroundColor: 'red',
}
};
React doesn't work like your typical HTML/CSS/JS app. The thing to note that JSX may look like HTML but it is not HTML.
In your code, className is being defined as a string, which is expected, however, there's possibly no CSS being referred to in this document. Try to console.log it and see what you get.
...
Another possible solution is to simply have your style within the same component file. A common design choice for component styling is inline styling. This is especially useful for projects of medium-large scale, where managing files can get difficult.
Helpful references:
https://reactjs.org/docs/dom-elements.html#style
https://codeburst.io/4-four-ways-to-style-react-components-ac6f323da822

Polymer `<custom-style>`: which line of code stops appending to DOM multiple imports of the same custom-style template module?

My project's upstream web components theme is implemented as <custom-style> elements link
I want to implement my document level overrides as a JS module (as in, avoid hardcoding into app index.html or equivalent), which on surface looks simple:
import '#vaadin/vaadin-lumo-styles/color.js';
const $template = document.createElement('template');
$template.innerHTML = `
<custom-style>
<style>
html,
:host {
--lumo-primary-color: red;
}
</style>
</custom-style>`;
document.head.appendChild($template.content);
QUESTION
Some web components used in the document also import original theme via import '#vaadin/vaadin-lumo-styles/color.js'.
I want my overrides to always cascade last (without !important hacks).
Do multiple later import '#vaadin/vaadin-lumo-styles/color.js'; calls have any potential to revert my CSS custom property overrides cascade?
Think:
original: --lumo-primary-color: hsl(214, 90%, 52%);
me: import original, override --lumo-primary-color: red;
later: can a later import of original "reset" cascade back to --lumo-primary-color: hsl(214, 90%, 52%);)?
ES6 import a file in multiple place, why the file loads once? seems to imply maybe not, but I'm struggling finding any documentation that explicitly states something one way or another about <custom-style>.
Perhaps https://github.com/Polymer/polymer/blob/v3.2.0/lib/elements/custom-style.js#L80 is the key?
GLITCH
https://glitch.com/edit/#!/roan-pizza?path=src/index.js seems to confirm repeated imports don't seem to cause a problem, but why? Is it purely due to ES6 module load caching, or is there something else to it?
EDIT drag-n-dropping <custom-style> elements around in browser inspector definitely has an effect on the cascade (colors change based on tag order), so at least loading order is confirmed to matter.
Tips: remove all for edit.
difference tags (of <custom-style>) by #id => <custom-style id="id01">.
save <custom-style> to edit => save(#id).
red (in "--lumo-primary-color") is a variable => var color = red.
remove all content of a <custom-style id="id01"> => remove_all(#id).
add a new content you need => as you did above.
I just hope that you will solve your problem. You are better than me so I will not write code.

ng2-ckeditor - how to customise the css loaded inside the editor itself?

I need to customise the ENTER key behaviour of ng2-ckeditor. I understand there is a config option as explained here.
However as that link explains, I should use custom css:
If you want to change it to control paragraph spacing, you should use
stylesheets instead. Edit the contents.css file and set up a suitable
margin value for <p> elements, for example:
p { margin: 0; }
According to this SO question I can load a custom CSS file using a config option, like this:
config.contentsCss = 'mystyles.css'
I tried adding a single file to my project and setting the config in angular 2 component, but the file does not appear to load.
private setConfig(): void {
this.ckConfig = {
height: '250',
extraPlugins: 'divarea',
contentsCss: '/theme/styles/ckeditor.css',
toolbar: [... toolbar configurations ...]
};
}
So how can I get ng2-ckeditor to load this file?
This breaks if you have the DIVAREA plugin activated
Edit (from comment):
This is because contentsCss does not load when using DIVAREA. Makes sense since the CSS would need to be scoped to inside the DIV (easy with iFrame).
Maybe new CSS layers could help here?
github.com/ckeditor/ckeditor4/issues/4640 github.com/ckeditor/ckeditor4/issues/4642

Categories