import css using webpack in react - javascript

I was from angularjs, now picking up react. Even I was using angular 1.x which is already component based, but it still has template. But in react the file structure and the way we use to code front end has changed, like instead of spiting files by pages, u make files by component now. It promotes reusability but does that means how we apply the css also changed?
I saw this import { navBar } from 'styles/navbar.css' in navBar.jsx. Hmm how does css work together with JSX? doest navBar css load that file? What webpack plugin is needed for that? does it come from default? I'm using react-create-app by facebook so I didn't know much about config.

You use css-loader and style-loader to include CSS files in your webpack bundle. By default it generates some JavaScript code that creates a style element with the contents of the imported CSS file and appends it to the head element in your index.html.
So you can definitely use external CSS files to style your React components, just make sure that every CSS class is properly namespaced to avoid naming conflicts with the classes of other components.
For example you could adopt the BEM naming scheme. If your component is called NavBar, then the root element of that component might have a className of x-nav-bar (the x prefix is there to avoid clashing with frameworks like bootstrap), and all child elements, if they need to be styled, will then have class names like x-nav-bar__${childName}.

This kind of import { navBar } from 'styles/navbar.css' is not relevant to JSX but to css-loader. This is a webpack loader that handles css, and it supports cssModules, that allows you to encapsulate selector names in order to avoid css leaks.
So, shortly, that import exposes an object with mapping between your selector to unique string (usually an a hash).
For example:
// styles.css
.foo {
color: red;
}
.bar {
color: green;
}
// Component.jsx
import styles from './styles.css';
console.log(styles);
/* This will print something like
{
foo: '_h234jh',
bar: '_234m23'
}
*/

Related

Why does React randomly chose a different Stylesheet instead the one I imported?

I have a React App with the following folder structure.
All my "pages" have their own Folder with a .jsx file and a .css to style the page.
I imported the CSS in the HomePage.jsx like:
import '../HomePage/HomePageStyles.css'; //HomePage.jsx
So far, everything is working just fine. Then I created the ChampionDetailPage.css and imported it in the ChampionDetailpage.jsx like that.
import '../ChampionDetailPage/ChampionDetailPageStyles.css'; //ChampionDetailPage.jsx
Now things start to get funny. The HomePages.jsx suddenly start to use styles from ChampionDetailpage.css that have the same class names without any obvious reason.
The goes vice versa, so the ChampionDetailPage.jsx uses classes from the HomePageStyles.css as well.
For example, I have the class .content-right in both .css files
.content-right{ /* HomePage.css */
width: 55%;
}
.content-right{ /* ChampionDetailStyles.css */
display: flex;
padding-right: 20px;
flex-grow: 100;
flex-direction: column;
}
In this case, React somehow styles my Homepage.jsx with the ChampionDetailPages.css which is also visible in the Chrome dev tools.
Why does that happen and how do I fix it?
Things I tried already:
Changing the import eg. import './ChampionDetailPageStyles.css';
Throwing the CSS into its own directory
in both cases, the problem remains the same!
Thanks for your help in advance.
You can't have stylesheets with classes that overlap eachothers.
Then, the class that is taken in consideration is the one that was in the css that was loaded the last. This is why you have each of the two classes that are picked up randomly.
What you must know When you import a css this way:
Its content is not scoped for your file that imports this css.
It will be imported globally, and then, classes that are defined inside will be shared to every dom content of your aplication during its whole lifecycle.
You have no control on the order of importation of your css over the time.
To summarize, the stylesheet is not actually picked up randomly, it is the one that happens to be loaded the last that overrides every class that was already defined in the previously loaded css.
Something to know, all the css that you import in your client application are ALL loaded at the bootstrap.
A better way to manage styles with React is to use Emotion. A framework that permits to handle css with your program, and also to be able to scope your styles to your component, or to share it with several components.

Change theme of angular library when imported

I'm trying to do something specific but can't find any information about it.
What I'm trying to do is make a common angular library with my styled components (size, font, ..) and then import this library in 2 different projects, so far so good.
But now I want the 2 projects to have different color/font/icon themes.
So I need a way to define the theme in the parent projects, and then gets applied to the styling of the library components.
This way al my components in the library can stay the same (single code base) and it can be used in different applications with there house style.
Is there a way to do this?
Kind regards,
P90K
Create an Angular Library
To create a Angular library you can follow the guide here. You've to publish it on npm and install on your projects.
Style your Library
1. Change Style Encapulation with ViewEncapsulation
Read More
Defines template and style encapsulation options available for Component’s Component. By using ViewEncapsulation.None you are exposing your styles to outer components.
import { Component, ViewEncapsulation } from '#angular/core';
#Component({
...
encapsulation: ViewEncapsulation.None,
...
})
Note: This can help to override any component CSS but be sure to use proper selectors
2. Use :host
Read More
The host can help to override CSS without touching the view encapsulations.
CSS pseudo-class function selects the shadow host of the shadow
DOM containing the CSS it is used inside
Lib in your parent template
<your-component class="custom-component-cls"></your-component>
Lib style in your parent style
:host{
::ng-deep .custom-component-cls{
color: white;
}
}

Importing CSS in one component is adding CSS affect to other Components. How and Why?

I am from Angular Background and as far as I know. Each component has its own beauty and till we import a CSS file inside itthose CSS classes should not be applied even if we add to HTML Elements to the component in case we have not added or imported any CSS files for classes used inside this new/2nd component.
What I did in React was made 2 components - Home1.js and Home2.js. When I am importing a css file named Home.css to Home1 Component and NOT to Home2.js component - How in the world is those CSS classes affect being applied even too Home2 Component. This is sheer absurd.
That's why I am importing someFile.css **specifically** to the component where I want its affect to be there. This provided a kind of encapsulation affect, which I am seeing is failing. Now, someone can explain me how in the world, wherever I am not importing someFile.css, there also the classes are having affect?
Home1.js
import React, { Component } from 'react';
import './home.css';
class Home1 extends Component {
render() {
return (
<div>
<div className="red">1...</div>
<div className="green">2...</div>
<button>click</button>
</div>
)
}
}
export default Home1;
Home2.js
import React, {useState} from 'react';
const Home2 = () => {
return (
<div>
<div className="red">1..</div>
<div className="green">2...</div>
<button>click</button>
</div>
)
}
export default Home2;
Result:
Angular does it through viewEncapsulation, but this notion does not exists in react. You either need to scope your css manually by adding a main class on the top node of your component, or use a library that can do it for you (haven't tried it, you can refer to #Abdelrhman Arnos comment).
In React, like someone already had commented, you need the CSS modules to handle your problem. Actually, it's already included in the css-loader, which is a very basic module you need for webpack to handle the CSS files in the bundling process. I am not sure if you build your React app from the ground up, but I am quite sure you already had this module in your project.
{
loader: 'css-loader',
...
options: {
// Automatically enable css modules for files satisfying `/\.module\.\w+$/i` RegExp.
modules: { auto: true },
},
},
I believe you are an experienced web app programmer, and just complaining about the design of the React, but I would like to provide a little basic knowledge of browser rendering mechanism here for whom just start learning web programming and thinking about the same question.
The basic of the rendering engine in the browser is interpreting the HTML, XML documents. After loading assets by such as <script>, <style>. There are a couple of steps to complete the rendering. The step to apply CSS rules on pixels is Style calculations.
What browser does is very simple, it takes the CSS files, applies the rules, something about the scope of the styles really rely on the practice of library/framework, you can imagine that the best they can do is preprocessing the CSS files and add some unique properties to each CSS rules corresponding to the specific class names it can find in your code.
Where to import the CSS file is just for readability and maintainability. In the old times, when people still program web app with jQuery or pure JS, you just include the CSS file in the .html file, maybe it forces you to care about the naming of the classes and styles earlier, but actually we also have the same problems when you try to separate it for bigger projects.

AngularJS custom bootstrap CSS not working at component level

I decided to convert a landing page to an AngularJS website, because I needed to add an admin section. To separate the website section from the admin section, I created two modules: website and admin.
The original website has been made with Bootstrap 3, and has a style.css that is custom CSS for all the Bootstrap and the website in general.
On the Angular version, I can load the website properly after I installed Bootstrap 3, and in the root-level style.css I do the following :
#import './app/website/assets/css/style.css';
The issue is that I don't want this CSS to be loaded for the full website (website + admin). With this configuration, the admin section is also affected by the CSS.
The import only works if it is in style.css. If I move the import to the website module in the root component.css styles won't load at all.
I know it must have something to do something with style scoping and ng-deep.
EDIT: The only way I can have the website load properly with the CSS imports within its own module is :
encapsulation: ViewEncapsulation.None
As of right now, there is no way to import css at the module level. Global styles are applied globally, and the default ViewEncapsulation makes it so that component specific styles don't bleed out to the rest of the app.
If I move the import to the website module in the root component.css
styles won't load at all.
Importing that css at the modules root component only applies the styles to that one component. I also wouldnt look too hard at ng-deep as it is / will be deprecated https://angular.io/guide/component-styles#deprecated-deep--and-ng-deep
Without knowing how many components are in WebsiteModule or what styles.css looks like, I'll present two options.
1) Rename styles.css (could get confusing since it's not going to be global anymore), import it in each of the components in WebsiteModule.
If that turns out to be too tedious (one bazillion components in WebsiteModule), then
2) I would take a good hard look at the styles.css in question, and see what styles should be applied globally.
Turning off ViewEncapsulation should be a last resort IMO.

Removing imported CSS on component end

I have many components that import hosted css files as follows:
<style scoped>
#import 'https://test.com/path/to/my-stylesheets/styles.css';
</style>
What I am wanting is a way to remove these imported stylesheets on an end lifecycle hook such as beforeDestroy.
Is this possible?
What you're trying to do depends on vue-loader (if you're using webpack) and it looks like a counter intuitive. So, there's no reason for styles to be removed from document. What you can do is to define your CSS classes in stylesheets or as a data variable in viewmodel and assign/remove those classes during Vue component's lifecycle like beforeCreate/beforeDestroy etc. if you like.

Categories

Resources