I have created an application using webpack and reactjs.
So far I have created 2 pages. I have defined CSS styling for both the pages. But when I load page 2 after loading page 1, the styles from page 1 are interfering with those of page 2.
For example
Page 1
require('style1.css');
var Page1 = React.createClass({
render: function(){
return(
<div> <h1>This is Page1</h1> <span> hello from page1</span></div>
)
}
});
module.exports = Page1;
style1.css
span {
color : red
}
Page 2
require('style2.css');
var Page2 = React.createClass({
render: function(){
return(
<div> <h1>This is Page2</h1> <span> hello from page2</span></div>
)
}
});
module.exports = Page2;
style2.css
h1 {
color : blue
}
When page2 is loaded after page1, the color of span was red, which was loaded from page1's style. Is there any way to avoid such kind of interferences or am I doing something wrong here?
You can have local stylesheets for each React component.
So the style sheet itself will have something like this:
:local(.styles) {
.your-style{...}
}
You can store it in the same folder as your component code. You import the style like so:
/* component styles */
import { styles } from './styles.scss'
In the render function of your component you will have this:
return (
<div className={styles}>
...
</div>
)
Everything within that <div> will have the stylesheet applied.
Loader configuration for your Webpack:
loaders: [{
test: /\.scss$/,
loader: 'style!css?localIdentName=[path][name]--[local]!postcss-loader!sass',
}]
You can look at this awesome boilerplate app, that implements all of this very nicely.
Webpack is not going to fix the inherent problems with style sheets. If you want component level styling the simplest solution is to go with inline styles. You might also look at Radium. https://github.com/FormidableLabs/radium
Related
No fancy webpack, simple Vue custom element with some global css and some inline css for overrides.
I would like to use some styling library, like from getbootstrap.com and have it change styles inside custom element.
https://jsfiddle.net/Deele/6xk1atrn/25/
<div class="btn bg-info">Zero</div>
<test-widget id="One"></test-widget>
<test-widget id="Two"></test-widget>
const TestWidget = Vue.defineCustomElement({
props: {
id: String
},
data: () => {
return {
message: 'Test'
}
},
emits: {},
template: `<div class="btn bg-info">{{id}} {{message}}</div>`,
styles: [`div { color: green; }`]
})
customElements.define('test-widget', TestWidget)
.bg-info {
background-color: red!important;
}
Was expecting divs inside rendered elements would be styled as buttons, but it does not work!?
From what I have found in the internet, it has something to do with Shadow DOM not inheriting any global styles.
Please, tell me if there is a solution to this approach? I would like to create small widgets for my website using Vue.js, but this hurdle creates fatal limitation.
Custom elements defined using the Vue API always use a shadow DOM, so they are isolated from the parent document and any global styles in the app.
So to make it happen, You can inject the bootstrap styles or any global style url's in the styles option by using #import statement.
Live Demo :
const TestWidget = Vue.defineCustomElement({
props: {
id: String
},
data: () => {
return {
message: 'Test'
}
},
template: `<div class="btn bg-info">{{id}} {{message}}</div>`,
styles: [`#import url("https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-beta.2/css/bootstrap.css"); div { color: green; }`]
});
customElements.define('test-widget', TestWidget);
<script src="https://unpkg.com/vue#next"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-beta.2/css/bootstrap.css"/>
<div class="btn bg-info">Zero</div>
<test-widget id="One"></test-widget>
<test-widget id="Two"></test-widget>
I have to implement css modules for some older React code. But when I try to import CSS modules, I canĀ“t use this class in another files.
Do I have to refactor the code to React Components? Or is there another easier solution?
Code example:
import styles from "styles.module.css"
var Greeting = createReactClass({
render: function() {
return <h1>Hello</h1>;
}
});
Yes, module CSS is also supported in class-based components.
In the module CSS you have to use CSS as an object,
For Example, You have a CSS class for an alert component
.alert{
color:red
}
then you can use it in components like this:-
import styles from "styles.module.css"
var Alert = createReactClass({
render: function() {
return <h1 className={styles.alert}>Hello</h1>;
}
});
I am trying to change the background and text color of my navbar component depending on what page I am on in order to remove contrasting colors with the current pages background. Effectively wanting a light and dark theme variant for the TopNav component that is triggered by what page we are currently on.
My nav bar and page template is as below:
<template>
<v-app>
<TopNav /> ------> This is the navbar component whos css i want to alter
<v-content>
<router-view></router-view> -----> Depending on what the current page injected is.
</v-content>
<Footer />
</v-app>
</template>
Using <style> tags without the scoped attribute work on changing the navbar background but unfortunately it does not revert back after navigating to another page.
Changing state of a component from a sibling level or child level component is really an anti-pattern.
Your best bet is going to be using a well established pattern to get the functionality you're after.
One way to do this is to bring in Vuex, and place your light/dark mode in the Vuex store (shared application level state management)
Then, you could setup your TopNav component to bind to a value in Vuex state (this.$store.state.darkMode for example)
Then, from anywhere in the application, you could commit a mutation to specify light mode, dark mode, toggle, etc...
Or, if you want it to always be route-specific (kinda sounds like this is the case) then you can setup your route definition something like this:
const routes = [
{
path: '/light-component',
name: 'LightComponent',
component: () => LightComponent,
meta: {
darkMode: false,
},
},
{
path: '/dark-component',
name: 'DarkComponent',
component: () => DarkComponent,
meta: {
darkMode: true,
},
},
];
Then, in any component (your TopNav component for example) you could do something like:
<template>
<div :class="darkModeClass">
...
// inside <script> ...
computed: {
darkModeClass() {
return { dark: !!this.$route.meta?.darkMode };
}
}
...
<style scoped>
.dark {
/* css styles for dark mode */
}
</style>
I'm trying to create custom-element (web component) in svelte 3. I can't find any way to style nested components from css. Svelte removes styles before injecting them to <style> inside of ShadowDOM.
The problem is that I want to have nested components in my root element.
For example:
RootComponent (svelte custom-element)
(imports) FooComponent
(imports) BarComponent
As stated here: svelte-custom-element
All the components imported to custom-element must have compiler option set to <svelte:options tag="component-name" />.
With this option set nested components works as expected and are injected into root's element ShadowDOM. The problem is that styles defined in nested components are not being injected.
The workaround for this problem would be to inject them into root's element <style> as global styles within ShadowDom.
(Un)fortunately svelte automatically removes all unused styles during compilation when custom elements not yet exist.
My goal is to create web component with svelte and then use it outside of svelte as native web-component.
Here is REPL
Custom elements do not really work on REPL as Conduitry wrote:
The compiler options in the REPL don't actually affect the code that >is run, just the code that is displayed. So enabling customElement >doesn't mean you are building and running a web component
So it's more like a code example than working one.
I would like to know if there is another way to create svelte custom-element with nested component and proper styling.
Is there a way to disable removing of unused css?
https://imgur.com/a/zZia566
from <div class="nested"> starts Nested component imported from Nested.svelte.
<style> element should have .nested class injected but it is removed by svelte compiler.
This is because when customElement option is on, each style in a component is injected into the shadowRoot of the custom element.
class YourComponent extends SvelteElement {
constructor(options) {
super();
this.shadowRoot.innerHTML = `<style>.foo{color:red;}</style>`;
// continues
Thus, in order to make style appear, you must use svelte component as custom element, not as svelte component.
Your App.svelte should be like below.
<script>
import Foo from './Foo.svelte'
import Bar from './Bar.svelte'
</script>
<svelte:options tag="web-component" />
<foo-component/>
<bar-component/>
However, this neither solve the problems related with custom element.
:global selector is not transformed into actual global selector.
Every nested component will produce shadowRoot, whereas mostly you will want only top-level one.
Check out some issues below from svelte repository related to custom elements.
nested component in custom element does not inherit style #2605
:global(...) not working in custom elements #2969
It seems like svelte does not fully support style cascading in custom element yet, should be handled in future.
Checked in svelte v3.12.1.
Thanks to brunoalano for sending me this: svelte-custom-element-template. It solves the styling problem with custom build script.
You just have to prevent the compiler from removing unused CSS
Let's say we have a custom element : App.svelte
App.svelte imports a normal svelte component : ./components/Message.svelte
But when you do this, any styles inside Message.svelte will disappear.
Solution
Move all content in the <style> tag of Message.svelte into the <style> tag of App.svelte
Add this to script of App.svelte
let cssKeep: string = "";
Add this to body of App.svelte
<span style="display: none;" class={cssKeep}><span class={cssKeep} /> </span>
This will prevent the compiler from removing any styles
Example
src/components/Message.svelte
<script lang="ts">
export let content: string;
</script>
<p class="red"> {content} </p>
src/App.svelte
<svelte:options tag="my-element" />
<script lang="ts">
import Message from "./components/Message.svelte";
let cssKeep: string = "";
</script>
<Message content="hello" />
<span style="display: none;" class={cssKeep}><span class={cssKeep} /> </span>
<style>
.red {
color: red;
}
</style>
vite.config.ts
import { defineConfig } from 'vite'
import { svelte } from '#sveltejs/vite-plugin-svelte'
export default defineConfig({
build: {
lib: {
entry: './src/main.ts',
name: 'MyElement'
},
},
plugins: [
svelte(
{
compilerOptions: {
css: true,
},
exclude: "./src/App.svelte",
emitCss: true,
}
),
svelte(
{
compilerOptions: {
customElement: true,
css: true,
},
exclude: "./src/components/**",
emitCss: true,
}
),
],
})
// guide: https://www.thisdot.co/blog/web-components-with-svelte
This may answer:
How to export web component in Svelte with nested Svelte components
Use Svelte components with custom elements
Styles missing when Svelte component imported into custom web component / custom element
I have setup my own react project from some tutorials including my own webpack configuration. When I try to style elements it is able to apply style to generic html tags such as <body> or <p> but it fails when I try to style classes/ids.
I know my css file is being imported because it styles the generic tags.
Webpack Config
{
test: /\.css$/,
use: [
"style-loader",
{
loader:"css-loader",
options:{
modules:true
}
}
]
}
CSS
.oakResults {
font-size:20px;
}
#yoyoyo {
color:red;
}
p {
color:orange;
}
React
<div className='oakResults'>
<p id='yoyoyo'>Results</p>
</div>
In my example, the <p> is colored red, but .oakResults font does not change and when I comment out the <p> style it doesn't turn red.
I want it to be able to style to both generic tags and classes/ids.
I think the reason of this issue is you have enable the css modules in webpack but not referring the css correctly.
So if you don't need the css module, try to remove options:{ modules:true} from your webpack config. Then the css could be applied to the class name you set in ReactJS.
Or if you do need the css module, keep the Webpack config. But modify your ReactJS to something like this:
import React, { Component } from 'react';
import styles from 'path\to\file.css';
class foo extend Component {
render() {
return (<div classname={styles.oakResults}> This is the test component</div>)
}
}
Hope it helps.
You should try this,
{
test: /\.css$/,
use: ["style-loader", "css-loader"]
}
From the docs,
The modules option enables/disables the CSS Modules specification and setup basic behaviour.
Using false value increase performance because we avoid parsing CSS Modules features, it will be useful for developers who use vanilla css or use other technologies.
Refer more about CSS Modules.