Using bootstrap in web components shadowDOM - css

What's the easiest way to use a large css library (like bootstrap) in web components / shadowDOM app using LitElement?
Tried the following:
Use the link tag within the component. Works, but creates FOUC (flash of unstyled content).
Render everything to Light DOM (I'm using LitElement and they have a createRenderRoot() override. Works as well, but as the app gets more complex, maintaining component document isolation would be nice.
Looking for the simplest way to just use boostrap in this setting.

LitElement's recommended way to add styles to components is via the styles property. Loading external .css files this way is not straightforward, but there are some solutions.
The import way
If your definition of "simplest way" comprises using transpilers or module bundlers then you can use non-js inlined imports to accomplish something like the following:
import bootstrap from './path/to/bootstrap.css';
// ...
class MyElement extends LitElement {
static styles = bootstrap; // If your build system already converted
// the stylesheet to a CSSResult
static styles = unsafeCss(bootstrap); // If bootstrap is plain text
}
There are many plugins dedicated to this: see for example babel-plugin-inline-import, rollup-plugin-lit-css, rollup-plugin-postcss-lit, webpack-lit-loader.
The wrapper way
If you want to keep things (almost) buildless you can write a simple postinstall script that generates a .js file that exports the lit-ified styles:
// bootstrap.css.js
import {css} from 'lit-element';
export const bootstrap = css`
<bootstrap here>
`;
// my-element.js
import {bootstrap} from './bootstrap.css.js';
class MyElement extends LitElement {
static styles = bootstrap;
}
About Shadow DOM
If you want to use Shadow DOM you'll have to import the library in every component that needs to use it, even nested ones. This is not as onerous as it seems thanks to Constructable Stylesheets, used by Lit under the hood; think of it as a way for components to join style contexts more than a replication of identical stylesheets. Also, to keep things organized you can create a "base" component that imports bootstrap and extend it wherever needed:
import bootstrap from 'path/to/bootstrap.css';
export class BaseElement extends LitElement {
static styles = bootstrap;
}
class MyElement extends BaseElement {
render() {
// Bootstrap is ready to use here!
return html``;
}
}
Lit documentation about style sharing: https://lit.dev/docs/components/styles/#sharing-styles

Related

How to use external scss or css file with material UI? (react)

I am facing problem with external css files on my react project. I am using material UI components. In the react components folder I created css file for each components but they are not loading when i hard reload the site.
I wanted to use external css rather than styled components or material ui style syntax.
Just import the css / scss file in your component and make sure you've added the classes for the elements.
If you are looking a more generic option you can import your style.css file in your main App.jsx (if you call it "App.jsx") file. Then you just use the className and will have access to your css.
App.jsx file
import './style.css'; // Your path to your style.css
function App() {
return (
<div>React app</div>
);
}
export default App;

Why are the styles of my scss module being applied to the wrong component?

I'm building a website with gatsby and I have set up the gatsby scss plugin. Everything seemed to be working fine until I realized my styles from home.module.scss were also being applied to my navigation component that only imports navbar.module.scss.
I have a style for my buttons in each of these modules that looks like this...
button {
// different styles in the different modules
}
Both of these modules import a global scss file at the top like this...
#import '../styles/global.scss';
The react components only import their respective modules. In my main index component I import global styles like this import './global.scss'
Am I misunderstanding how scss modules work in React or is this is a bug?
from my understanding
In react importing SCSS or CSS in any component will be global.
So it will affect all other components as similar to the component where you imported the SCSS file.
use different class names

Reference global class names from within a css module

Picture a more traditional web application that is slowly introducing a React component in one page that is complex enough to need it.
We're developing this new UI with Webpack, and we're using css modules for all the new css that the new UI needs. But we still need to reuse some css that's global and provided in the app via a traditional css stylesheet linked in the html.
Therefore we need in our css modules to occasionally write rules that refer to a css class in the global namespace, not a class that's locally scoped to it and therefore converted to a more gem-like long css class name when the app is run:
.container {
// rules for container
}
.container.pull-right {
// rules for when the container element also has the pull-right class
}
In the above example, container is meant to be a css class that the css module will contextualize to the particular component using this module.
But pull-right is a class that exist in a css file available in the page, but not processed by css modules or Webpack. Therefore we need a way (a syntax probably) to tell css modules "hey, leave pull-right as is in your output. Do not mess with it or try to BEM the s**t out of it".
I imagine something like this should exist, but I haven't been able to find it so far by googling around.
To refer to a globally declared class name inside :local scoped css modules you should use :global switch:
.container {
// rules for container
}
.container:global(.pull-right) {
// rules for when the container element also has the pull-right class
}
More detailed explanation in css-modules documentation.

React - Child componet stylesheet overwriting other child's stylesheet

I'm trying to apply separate styleSheets for every child component by importing different styleSheets in different components but fails to achieve this as styles are being overwritten.
Sample Code: Stackblitz
childa.jsx:
import React from 'react';
import "./childa.css"
export default () => <h1>Child A!</h1>;
childa.css:
h1 {
color: blue;
}
childb.jsx:
import React from 'react';
import "./childb.css"
export default () => <h1>Child B!</h1>;
childb.css:
h1 {
color: red;
}
This is just a sample code. Need solution for a project having large styleSheets.
Based on your clarification in one of your comments:
The thing is I'm converting a project from angular to react and all
the css is already written so I can't use inline style. Is there any
way in which I don't have to rename all the css classes in all the
stylesheets?
Short ans: You can't achieve that as of now.
This article explains all the different ways to style react components. In your case, the best that you can do is use css modules and rename generic classes like h1 to .h1.
Check this great article about css modules: Modular CSS with React.
Note: css modules are not available in create-react-app. If you must use it here's an
article on how to use CSS Modules with create-react-app.
I think this is caused by ther order of the imports.
In your parent component you have something like
import React from 'react'
import ChildA from './ChildA'
import ChildB from './ChildB'
This means that in the compiled code you'll have the two stylesheets imported one after the other, and the second h1 rule will overwrite the first
You should use classes for your components, or use inline style
Importing a css does not wrap it in the scope of the component is just a straight import into the DOM. In order to mantain a separation of components styles you have to approach with another solution, as styled-components.
This may not work for your entire application, but I fixed it by applying a class to the element (.childA and .childB). This solved the problem.
export default () => <h1 className='childB'>Child B!</h1>;

How to use Stylesheets on React Server Side Rendererd App?

I am trying to convert my ReactJS application to Universal App with server-side rendering, but there is something that I don't understand. What is the best way to use and import styles to my components? Can I just import external stylesheet in HTML and use this all over my components? or import specific stylesheet to every component and use it as separate variables like this :
import s from './about.css';
export default class About extends Component {
render() {
return (
<div>
<div className={`${s.divone} row`}>
<span>Hello world</span>
</div>
<div className={s.divtwo}>
<span>bye world</span>
</div>
</div>
);
}
}
with the second approach, I have noticed that every time I do refresh my page, the styles are kinda too slow to load, and for one second I see my page without any CSS, and then I see my full page with CSS. There is any way to bypass that without external and global stylesheet? Like for example, Airbnb does. Maybe with some way to wait until all styles are loaded?
Also after I moved my app to server-side render, I get some strange warnings like this :
You can use classnames, a simple and small JS library to import and use css in your react components:
import styles from './css/yourcss.css'
import classnames from 'classnames/bind'
const cx = classnames.bind(styles)
// use in react component
<div className={cx('mydiv')}></div>
cx can have any JS expression inside it or just plain class name from css you have imported styles from.

Resources