Cant overwrite the custom stylesheet - css

I am trying to overwrite the CSS of react range slider.It uses the custom style sheet of which i need to add in the head section.My project is built on next.js
<link rel="stylesheet" href="https://unpkg.com/react-rangeslider/umd/rangeslider.min.css" />
Otherwise, the slider doesn't show anything if i don't add the link in head even though I installed the library. It's not even overwriting the CSS. I want to change the background color.This is my code:
import React, { Component } from 'react'
import 'react-rangeslider/lib/index.css';
import './slider.css';
import Slider from 'react-rangeslider'
class Horizontal extends Component {
constructor (props, context) {
super(props, context)
this.state = {
value: 850
}
}
handleChangeStart = () => {
console.log('Change event started')
};
handleChange = value => {
this.setState({
value: value
})
};
handleChangeComplete = () => {
console.log('Change event completed')
};
render () {
const { value } = this.state
return (
<div>
<div className='slider' style={{ marginTop:'165px',marginLeft:'319px',width:'700px',backgroundColor:'EF5350'}} >
<div style={{ textAlign:'center',color:'gray',fontSize:'35px',marginBottom:'82px'}}>
<p> What is the size of your property?</p>
</div>
<Slider
min={850}
max={5000}
value={value}
onChangeStart={this.handleChangeStart}
onChange={this.handleChange}
onChangeComplete={this.handleChangeComplete}
/>
<div className='value'>{value}</div>
</div>
</div>
)
}
}
export default Horizontal
I tried to change the background color in slider.css.
.rangeslider-horizontal .rangeslider__fill {
background-color: red;
}
The library needs to be installed first:
npm install react-rangeslider --save

It doesn't work as the slider stylesheet overwrite yours. Include the style like
// To include the default styles
import 'react-rangeslider/lib/index.css'
// import your css
import './style.css';
Demo

always make your own CSS stylesheet file the last file to import after any other CSS stylesheet files to make overwrite you need
otherwise, you can always use the console in the browser to auto-detect any error by pressing F12 in the browser then go to the tab called (console)
I think you can style element you want to live in the console to know the detail of how to nesting element
you also can open the CSS file in the editor and press Ctrl+F then find the line of code you want to style then copy its property and value to your own CSS file and then you can edit it so easy

Related

How to use Flatpickr in Stenciljs components?

Flatpickr input field is not showing up in the stencil component with proper css.
I added the flatpickr date input field in a newly created (using stencil cli) app. No other settings or configs are changed.
import { Component, h } from '#stencil/core';
import flatpickr from 'flatpickr';
#Component({
tag: 'my-component',
styleUrl: 'my-component.css',
shadow: true,
})
export class MyComponent {
private element: HTMLInputElement;
componentDidLoad() {
flatpickr(this.element, {
});
}
render() {
return (
<div>
<input ref={el => this.element = el} type="text" id="flatpickr" />
</div>
)
}
}
I'm guessing the problem is with the styling since the code you posted looks correct.
Flatpickr appends the calendar to the body element by default and since CSS is encapsulated when ShadowDOM is enabled (shadow: true) the styles in my-component.css won't affect it.
I see three options:
1. Append to different element
You can set a different parent for the calendar (your component or any element in it)
import { Component, Element, h } from '#stencil/core';
// ...
export class MyComponent {
#Element() el: HTMLElement;
private element: HTMLInputElement;
componentDidLoad() {
flatpickr(this.element, {
appendTo: this.el,
});
}
render() {
return (
<div>
<input ref={el => this.element = el} type="text" id="flatpickr" />
</div>
)
}
}
And import the styles in the CSS (my-component.css):
#import '~flatpickr/dist/flatpickr.min.css';
2. Include the Flatpickr CSS globally.
Include the CSS in your HTML head or any global CSS file.
3. Disable ShadowDOM
Set shadow: false to allow the styles in my-component.css to affect elements outside your component and import the CSS in my-component.css (same as in Option 1.).

Theme with React and Redux

i am trying to make a theme system on a react project that uses redux with a reducer that manages themes according to the user's local storage. But here my problem is that I used css files to define my styles on all of my components. However, I have all my logic with 2 javascript objects for light or dark mode. So I can't use js in css files unless I use css variables but I don't know how.
Here is my structure :
In my app.js I imported useSelector and useDispatch from react redux to access the global state :
import React from 'react';
import './App.css';
import Footer from './components/Footer';
import Header from './components/Header';
import Presentation from './components/Presentation';
import Projects from './components/Projects';
import Skills from './components/Skills';
import Timeline from './components/Timeline';
import { switchTheme } from './redux/themeActions';
import { useSelector, useDispatch } from 'react-redux';
import { lightTheme, darkTheme } from './redux/Themes';
function App() {
const theme = useSelector(state => state.themeReducer.theme);
const dispatch = useDispatch();
return (
<div className="App">
<Header />
<input type='checkbox' checked={theme.mode === 'light' ? true : false}
onChange={
() => {
if(theme.mode === 'light') {
dispatch(switchTheme(darkTheme))
} else {
dispatch(switchTheme(lightTheme))
}
}} />
<div className="top">
<div className="leftPart">
<Presentation />
<Skills />
</div>
<Timeline />
</div>
<Projects />
<Footer />
</div>
);
}
export default App;
and in themes.js I have my 2 objects which represent the themes :
export const darkTheme = {
mode: 'dark',
PRIMARY_BACKGROUND_COLOR: '#171933',
SECONDARY_BACKGROUND_COLOR: '#1e2144',
TERTIARY_BACKGROUND_COLOR: '#0a0c29',
PRIMARY_TEXT_COLOR: '#eee',
SECONDARY_TEXT_COLOR: '#ccc',
PRIMARY_BORDER_COLOR: '#aaa'
}
export const lightTheme = {
mode: 'light',
PRIMARY_BACKGROUND_COLOR: '#D3CEC8',
SECONDARY_BACKGROUND_COLOR: '#E5DFD9',
TERTIARY_BACKGROUND_COLOR: '#C1BFBC',
PRIMARY_TEXT_COLOR: '#222',
SECONDARY_TEXT_COLOR: '#333',
PRIMARY_BORDER_COLOR: '#555'
}
You can make use of data attributes.
I have done the same in one my project like so :-
[data-color-mode="light"] {
--color-focus-ring: #7daee2;
--color-link-hover: #0039bd;
--color-primary-bg: #eef6ff;
--color-primary-text: #212121;
--color-primary-border: #98b2c9;
--color-secondary-bg: #c3d7f0;
--color-secondary-text: #1a1a1a;
}
[data-color-mode="dark"] {
--color-focus-ring: #5355d4;
--color-link-hover: #4183c4;
--color-primary-bg: #080808;
--color-primary-text: #f1f1f1;
--color-primary-border: #525252;
--color-secondary-bg: #191919;
--color-secondary-text: #d8d5d5;
}
You can add the attribute to your top-level element (assuming div) like so:-
<div className="appContainer" data-color-mode="light" ref={appRef}> ></div>
Now use that appRef to change the data-color-mode attribute as well update the localstorage in one function. Updating the data-color-mode allows you to toggle between css variable colors easily. In my code, I have done this the following way:-
const toggleColorMode = () => {
const nextMode = mode === "light" ? "dark" : "light";
// container is appRef.current only
container?.setAttribute("data-color-mode", nextMode);
setMode(nextMode);
};
I am not using redux for this. Simply React Context API is being used by me but it's doable in your scenario as well.
You can take more reference from the repo - https://github.com/lapstjup/animeccha/tree/main/src
Note - I think there are other routes where people go with CSS-IN-JS but I haven't explored them yet. This solution is one of the pure css ways.
Fun fact - Github has implemented their newest dark mode in a similar way and that's where I got the idea as well. You can inspect their page to see the same attribute name :D.

i want to create a copy to clipboard using react js

I want to create copy to clip board using react js but i design like
textbox with in contain 'copy' word ,when i click this copy word it changed to be copied
and the textbox value will be copied
You can do this by using ref, document.execCommand('copy').
import React from 'react';
class CopyExample extends React.Component {
constructor(props) {
super(props);
this.state = { copySuccess: '' }
}
copyToClipboard = (e) => {
this.textArea.select();
document.execCommand('copy');
e.target.focus();
this.setState({ copySuccess: 'Copied!' });
};
render() {
return (
<div>
{
document.queryCommandSupported('copy') &&
<div>
<button onClick={this.copyToClipboard}>Copy</button>
{this.state.copySuccess}
</div>
}
<form>
<textarea
ref={(textarea) => this.textArea = textarea}
value='Some text to copy'
/>
</form>
</div>
);
}
}
export default CopyExample;
For clipboard interaction in React, I use clipboard-polyfil. It is nice because it provides polyfills to work on all browsers, which some of the native clipboard functions do not, such as document.execCommand("copy") and navigator.clipboard.write().
The easiest way to use this package with react is to make a custom component, pass in the string you would like to copy as a prop, and copy it using clipboard.writeText(this.props.stringValue);
Personally, I'm using react-copy-to-clipboard
1- install it using npm:
npm install --save react react-copy-to-clipboard
2- import it to your file:
import {CopyToClipboard} from 'react-copy-to-clipboard';
3- now you can wrap your component with <CopyToClipboard> component
it also provide onCopy optional callback function.
resources: CopyToClipboard repo on github

How to resolve FOUC in React.js

I have built react.js site from create-react-app.
But in production mode, there is FOUC because styles are loaded after html is rendered.
Is there any way to resolve this? I have been searching google for answers, but haven't found proper one yet.
FOUC
FOUC - so called Flash of Unstyled Content can be as very problematic as so many tries of solving this issue.
To the point
Let's consider following configuration of routing (react-router):
...
<PageLayout>
<Switch>
<Route exact path='/' component={Home} />
<Route exact path='/example' component={Example} />
<Switch>
</PageLayout>
...
where PageLayout is a simple hoc, containing div wrapper with page-layout class and returning it's children.
Now, let's focus on the component rendering based on route. Usually you would use as component prop a React Compoment. But in our case we need to get it dynamically, to apply feature which helps us to avoid FOUC. So our code will look like this:
import asyncRoute from './asyncRoute'
const Home = asyncRoute(() => import('./Home'))
const Example = asyncRoute(() => import('./Example'))
...
<PageLayout>
<Switch>
<Route exact path='/' component={Home} />
<Route exact path='/example' component={Example} />
<Switch>
</PageLayout>
...
to clarify let's also show how asyncRoute.js module looks like:
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import Loader from 'components/Loader'
class AsyncImport extends Component {
static propTypes = {
load: PropTypes.func.isRequired,
children: PropTypes.node.isRequired
}
state = {
component: null
}
toggleFoucClass () {
const root = document.getElementById('react-app')
if (root.hasClass('fouc')) {
root.removeClass('fouc')
} else {
root.addClass('fouc')
}
}
componentWillMount () {
this.toggleFoucClass()
}
componentDidMount () {
this.props.load()
.then((component) => {
setTimeout(() => this.toggleFoucClass(), 0)
this.setState(() => ({
component: component.default
}))
})
}
render () {
return this.props.children(this.state.component)
}
}
const asyncRoute = (importFunc) =>
(props) => (
<AsyncImport load={importFunc}>
{(Component) => {
return Component === null
? <Loader loading />
: <Component {...props} />
}}
</AsyncImport>
)
export default asyncRoute
hasClass, addClass, removeClass are polyfills which operates on DOM class attribute.
Loader is a custom component which shows spinner.
Why setTimeout?
Just because we need to remove fouc class in the second tick. Otherwise it would happen in the same as rendering the Component. So it won't work.
As you can see in the AsyncImport component we modify react root container by adding fouc class. So HTML for clarity:
<html lang="en">
<head></head>
<body>
<div id="react-app"></div>
</body>
</html>
and another piece of puzzle:
#react-app.fouc
.page-layout *
visibility: hidden
sass to apply when importing of specific component (ie.: Home, Example) takes place.
Why not display: none?
Because we want to have all components which rely on parent width, height or any other css rule to be properly rendered.
How it works?
The main assumption was to hide all elements until compoment gets ready to show us rendered content. First it fires asyncRoute function which shows us Loader until Component mounts and renders. In the meantime in AsyncImport we switch visibility of content by using a class fouc on react root DOM element. When everything loads, it's time to show everything up, so we remove that class.
Hope that helps!
Thanks to
This article, which idea of dynamic import has been taken (I think) from react-loadable.
Source
https://turkus.github.io/2018/06/06/fouc-react/

conditional css in create-react-app

I have default css file and separate css file that should be applied (to owerride default) only when certain conditions are met.
I am using create-react-app wit default import 'file.css' syntax.
What is the best way forward to decide whether to load or not load particular css file dynamically?
The require method only worked in development (as all the CSS is bundled upon build), and the import method did not work at all (using CRA version 3.3).
In our case, we have multiple themes, which cannot be bundled - so we solved this using React.lazy and React.Suspense.
We have the ThemeSelector, which loads the correct css conditionally.
import React from 'react';
/**
* The theme components only imports it's theme CSS-file. These components are lazy
* loaded, to enable "code splitting" (in order to avoid the themes being bundled together)
*/
const Theme1 = React.lazy(() => import('./Theme1'));
const Theme2 = React.lazy(() => import('./Theme2'));
const ThemeSelector: React.FC = ({ children }) => (
<>
{/* Conditionally render theme, based on the current client context */}
<React.Suspense fallback={() => null}>
{shouldRenderTheme1 && <Theme1 />}
{shouldRenderTheme2 && <Theme2 />}
</React.Suspense>
{/* Render children immediately! */}
{children}
</>
);
export default ThemeSelector;
The Theme component's only job, is to import the correct css file:
import * as React from 'react';
// 👇 Only important line - as this component should be lazy-loaded,
// to enable code - splitting for this CSS.
import 'theme1.css';
const Theme1: React.FC = () => <></>;
export default Theme1;
The ThemeSelector should wrap the App component, in the src/index.tsx:
import React from 'react';
import ReactDOM from 'react-dom';
import ThemeSelector from 'themes/ThemeSelector';
ReactDOM.render(
<ThemeSelector>
<App />
</ThemeSelector>,
document.getElementById('root')
);
As I understand, this forces each Theme to be split into separate bundles (effectively also splitting CSS).
As mentioned in the comments, this solution does not present an easy way of switching themes runtime. This solution focuses on splitting themes into separate bundles.
If you already got themes split into separate CSS files, and you want to swap themes runtime, you might want to look at a solution using ReactHelmet (illustrated by #Alexander Ladonin's answer below)
You can use require('file.css') syntax instead. This will allow you to put it inside of a conditional.
e.g.
if(someCondition) {
require('file.css');
}
Use React Helmet. It adds links, meta tags etc into document header dynamically.
Add it into any render method.
import {Component} from 'react';
import ReactHelmet from 'react-helmet';
class Example extends Component{
render(
<ReactHelmet link={
[{"rel": "stylesheet", type:"text/css", "href": "/style.css"}]
}/>);
}
}
You can rewrite it on next <ReactHelmet/> rendering.
One simple solution that I found that works in production is to use vercel's styled-jsx. First, install styled-jsx:
npm install --save styled-jsx
Or if you use Yarn:
yarn add styled-jsx
Now create strings from your css file, so for instance:
const style1 = `
div {
display: flex;
flex-direction: column;
align-items: center;
}
`
const style2 = `
div {
display: flex;
flex-direction: column;
align-items: center;
}
`
And then in your React Component, you can do something like this:
const MyComponent = () => {
return (
<div className='my-component'>
<style jsx>
{
conditionA ? style1: style2
}
</style>
</div>
)
}
Simply add <style jsx>{your_css_string}</style> to the component which you wish to add styling to and you can then to implement conditions just use different strings to import different css styling.
If you are here you most likely are trying to condition a CSS or SCSS import, probably to make some light/dark mode theme or something. The accepted answer works just on mount, after the second css is loaded they are both loaded and you dont have a way to unload them, or actually you have, keep reading...
The use of React lazy and suspense is awesome but in this case we need to help our selves from webpack, because is actually the guy that bundles stuff and can also unbundle stuff, which is what you need, a toggle of css imports basically
Adding webpack lazyStyleTag
Go to your webpack config file and add the following rules
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
// Probly you already have this rule, add this line
exclude: /\.lazy\.css$/i,
use: ["style-loader", "css-loader"],
},
// And add this rule
{
test: /\.lazy\.css$/i,
use: [
{ loader: "style-loader", options: { injectType: "lazyStyleTag" } },
"css-loader",
],
},
],
},
};
Now take your CSS files and change their name to the lazy named convention
You probably have this
styles.css
// or
styles.min.css
Now will be this:
styles.lazy.css
Then create your React theme Provider in a simple React context, this context will wrap your App so it will load the conditioned CSS everytime the context state changes. This context state is going to be availabe anywhere inside your app as well as the setter via a custom hook we will export from the same file, check this out:
import React, {
useEffect, createContext, useState, useContext,
} from 'react';
import { Nullable } from 'types';
// Import both files here like this:
// Import of CSS file number 1
import LightMode from './theme/styles.lazy.css';
// Import of CSS file number 2
import DarkMode from './theme/styles.lazy.css';
interface IContext {
theme: Nullable<string>
toggleTheme: () => void
}
const Context = createContext<IContext>({
theme: null,
toggleTheme: () => { },
});
// Your Provider component that returns the Context.Provider
// Let's also play with the sessionStorage, so this state doesn't
// brake with browser refresh or logouts
const ThemeProvider: React.FC = ({ children }) => {
// Im initialazing here the state with any existing value in the
//sessionStorage, or not...
const [theme, setTheme] = useState<Nullable<string>>(sessionStorage.getItem('themeMode') || 'dark');
// this setter Fn we can pass down to anywhere
const toggleTheme = () => {
const newThemeValue = theme === 'dark' ? 'light' : 'dark';
setTheme(newThemeValue);
sessionStorage.setItem('themeMode', newThemeValue);
};
// Now the magic, this lazy css files you can use or unuse
// This is exactly what you need, import the CSS but also unimport
// the one you had imported before. An actual toggle of import in a
// dynamic way.. brought to you by webpack
useEffect(() => {
if (theme === 'light') {
DarkMode.unuse();
LightMode.use();
} else if (theme == 'dark') {
LightMode.unuse();
DarkMode.use();
}
}, [theme]);
return (
<Context.Provider value={{ theme, toggleTheme }}>
{children}
</Context.Provider>
);
};
export default ThemeProvider;
// This useTheme hook will give you the context anywhere to set the state of // theme and this will toggle the styles imported
export const useTheme = () => useContext(Context);
Remember to put this state on the sessionStorage like in this example so your user has the state available every time it comes back or refreshes the page
Don't forget to wrap the friking App with the Provider:
import ThemeProvider from './ThemeProvider'
const App = () => {
return (
<ThemeProvider>
<App />
</ThemeProvider>
)
}
Now just toggle the CSS imports of your application using your cool useTheme hook
import { useTheme } from './yourContextFile';
// inside your component
const AnyComponentDownTheTree = () => {
const { theme, toggleTheme } = useTheme()
// use the toggleTheme function to toggle and the theme actual value
// for your components, you might need disable something or set active a
// switch, etc, etc
}
Other solution does not work for me. After one day of the search, I obtain bellow solution. In my issue, I have two CSS files for RTL or LTR like app.rtl.css or app.ltr.css
Create a functional component Style like this:
import React, { useState } from "react";
export default function Style(props) {
const [stylePath, setStylePath] = useState(props.path);
return (
<div>
<link rel="stylesheet" type="text/css" href={stylePath} />
</div>
);
}
And then you can call it, for example in App.js:
function App() {
...
return (
<Style path={`/css/app.${direction}.css`} />
)}
direction param contains rtl or ltr and determine which file should be loaded.
I tested some alternatives available in some tutorials and the best for me was to use only classes in css.
One of the problems I encountered when using
require: did not override on some occasions
import: delay generated to load css
The best way for me was to actually put a class switch
.default-sidebar {
--side-text-icon:rgba(255,255,255,.9) !important;
--side-text-section: rgb(255,255,255,.8) !important;
--side-separator-section:#ff944d !important;
}
.dark-sidebar {
--side-text-icon:rgba(255,255,255,.9) !important;
--side-text-section: rgb(255,255,255,.8) !important;
--side-separator-section:#262626 !important;
}
'
<div className={`root-sidebar ${condition?'default-sidebar':'dark-sidebar'}`}></div>

Resources