ReactJS - JSS - createUseStyles - how to generate inline style - javascript

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 ?

Related

React jquery .toggleClass() does only work after compiler reloading

I´m trying to build this sideboard for my react application:
https://codepen.io/illnino/pen/nwPBrQ . Anyways, I ran into a problem and I´m not able to solve this on my own.
So what is my exact problem ?
This code does NOT work if I try to hover on the sideboard icon as it should. After refreshing the page manually, it doesnt work either. But I noticed, if my react compiler reloads this application (after any change in my file) and I DON'T refresh the page manually, it works.
So .toggleClass() does only work, after my compiler reloads the code. After reloading the page on my own, it doesnt work again.
My Code
My css code is exact the same as on codepen. Of course the javascript and the html code are in the same file. The html code is also the same, so I´ll only give you my JS code (In fact I´m using typescript, but that shouldn't matter):
React.useEffect(() => {
$(".gn-icon-menu").hover(function () {
let e = $(".gn-menu-wrapper")
e.toggleClass("gn-open-part")
});
$(".gn-menu-wrapper").hover(function () {
$(this).toggleClass("gn-open-all")
});
}, []);
What have I tried ?
I really dont know, what to try. I´ll hope somebody maybe has a clue, what the error could be...
JQuery manipulates the DOM, React schedules updates to its own Virtual DOM. You should try to avoid using both. They don't get along with one another. If you write all the styles in a css sheet and then use those, you can achieve the same results.
.gn-menu-wrapper {
/* Base Styles */
}
.gn-menu-wrapper:hover {
/* Hover Styles here */
}
Also double check your style sheets are SCSS and not CSS. In this codepen example they are using the format: (&) this will not work in CSS.
&::placeholder{
color: $f-c;
}

How to use Bootstrap dropdown.js as standalone?

Is it possible to use the Bootstrap dropdown.js component without using the rest of the Bootstrap library? I've tried, but not managed to get it to work.
From the docs, I can see that the dropdown.js component requires Popper, and I can find the dropdown.js src file on GitHub.
But it seems that dropdown.js has a lot of dependencies:
import * as Popper from '#popperjs/core'
import {
defineJQueryPlugin,
getElement,
getElementFromSelector,
isDisabled,
isElement,
isVisible,
isRTL,
noop,
getNextActiveElement,
typeCheckConfig
} from './util/index'
import EventHandler from './dom/event-handler'
import Manipulator from './dom/manipulator'
import SelectorEngine from './dom/selector-engine'
import BaseComponent from './base-component'
And I'm not sure what to do about these. I've tried removing them, but I just get error messages that variables later on in the file are undefined.
You can use like this. Import Dropdown module and initialise it.
import { Dropdown } from "bootstrap";
var dropdownElementList = [].slice.call(document.querySelectorAll('.dropdown-toggle'))
var dropdownList = dropdownElementList.map(function (dropdownToggleEl) {
return new Dropdown(dropdownToggleEl)
})
It is not really possible. Dropdown.js is built using functions inside of popper.js and the bootstrap library.
If you are looking for something outside of bootstrap for a dropdown, I would recommend chosen.js which uses jQuery. If you download the source files you can modify the css to style it more to your liking.
Outside of that, you can also make your own vanilla javascript dropdown.
If you really love dropdown.js but need to have it standalone, you may use developer tools to reverse-engineer it and make your own.

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

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

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.

how to remove the style tags from the header section

I am using angular js and deployed a site, In the head part of my website there are a lot of style tags are coming in the console like the below image, I attached a snap of my website console. I don't know where those tags are coming from and how can I remove those style tags from the head of the website
As of my understanding, you are using Angular Material Design and it is responsible for adding the style tags in your head section. It all happens under the hood, you can follow this link to know more. I think you no need to worry about removing this style tags and all because it came as functionality. Angular Material Design dynamically inject this style tags for theming purpose.
Reference: https://material.angularjs.org/latest/Theming/05_under_the_hood
Thank you.
EDIT
If you don't want to generate themes by default then you can use
$mdThemingProvider.generateThemesOnDemand(true);
Example:
angular.module('myApp', ['ngMaterial'])
.config(function($mdThemingProvider, $provide) {
//disable theme generation
$mdThemingProvider.generateThemesOnDemand(true);
$provide.value('themeProvider', $mdThemingProvider);
})
.run(['themeProvider', '$mdTheming', function(themeProvider, $mdTheming) {
//create new theme
themeProvider.theme('default')
.primaryPalette('pink')
.accentPalette('orange')
.backgroundPalette('yellow');
//reload the theme
$mdTheming.generateTheme('default');
//optional - set the default to this new theme
themeProvider.setDefaultTheme('default');
}]);
Reference: https://material.angularjs.org/latest/Theming/04_multiple_themes
If you want to remove all the style tags :
var st = document.getElementsByTagName('style');
and add a loop to remove all of them.
for(i = 0 ; i < st.length ; i++){
st[i].parentNode.removeChild(st[i]);
}
Please Try with below JQuery code
$('style[md-theme-style]').remove();
Reason :
Angular-material includes some default theme css as a constant variable.
You can check here(angular-material.js).
When we load this library in the browser it adds lots of style tags dynamically into the <HEAD> section of the Page.
How to disable ?
You can override the constans.It will result in not adding theme classes on components.
angular(myApp, [ ngMaterial, myAppModules ]).constant("$MD_THEME_CSS","");
You can also look into the angular-material.js. This solution is also proposed in library itself.
Have you tried to disable theme generation before and then enable the one you want?
angular.module('myApp', ['ngMaterial'])
.config(function($mdThemingProvider) {
//disable theme generation
$mdThemingProvider.generateThemesOnDemand(true);
//themes are still defined in config, but the css is not generated
$mdThemingProvider.theme('altTheme')
.primaryPalette('purple')
.accentPalette('green');
//generate the predefined theme named altTheme
$mdTheming.generateTheme('altTheme');
});
When material.js loads into your browser this adds lots of css style tags dynamically to the page document. To disable them you will need to recompile angular-material yourself using the following commands:
git clone https://github.com/angular/material.git
Then install dependancies:
cd material
npm install
Then go to gulp/util.js and change line 53 from:
var jsProcess = series(jsBuildStream, themeBuildStream() )
to be:
var jsProcess = series(jsBuildStream)
Then run the build process:
gulp build

Categories