Can you overwrite styles in Material UI using css/scss? - reactjs

At the moment I'm using SCSS, as it is easy to use with NextJS. I really like how this system works, using the SCSS modules, and so I would also like to use it when using Material-UI. Material-UI uses JSS, which is a lot of boilerplate to write every time. Additionally, I prefer not to work with two ways of styling (SCSS modules and JSS). I already changed the order of CSS injection, so that I can use my SCSS modules on Material-UI components. However, I'm wondering if there is a way to overwrite styles of Material-UI components using SCSS modules? I have tried the following and a few similar things, but nothing seemed to work:
import styles from "./Login.module.scss";
import Button from "#material-ui/core/Button";
function Login() {
return (
<section>
<Button className={styles.button} variant="contained" color="primary">
Verify
</Button>
</section>
);
}
export default Login;
.button {
padding: 10px;
margin-bottom: 10px;
.MuiButton-containedPrimary {
border: 2px solid red;
background-color: red;
}
}

Below is the correct syntax:
.button {
padding: 10px;
margin-bottom: 10px;
&:global(.MuiButton-containedPrimary) {
border: 2px solid red;
background-color: red;
}
}
The example above has two key changes:
Using :global(.MuiButton-containedPrimary). Without using :global, CSS modules will transform the MuiButton-containedPrimary into a class name unique to this module and then it won't match what Material-UI puts on the button.
Adding the & in front effectively creates a selector like .button.MuiButton-containedPrimary matching an element with both classes on it. Your original syntax would treat .MuiButton-containedPrimary as a descendant selector and only match elements with that class that are a descendant of the button rather than the button itself.

You can use makeStyles of #material-ui. And pass to classes to override CSS default of material-ui.
import { makeStyles } from "#material-ui/styles";
const useStyle = makeStyles(() => ({
root: {
padding: "10px",
marginBottom: "10px",
},
containedPrimary: {
border: "2px solid red",
backgroundColor: "red"
}
}))
function Login() {
const classes = useStyle();
return (
<section>
<Button classes={classes} variant="contained" color="primary">
Verify
</Button>
</section>
);
}

Related

React CSS module not putting in class names even though they exist

I have a React component where I'm trying to style a button for my web app. I've done this countless times with other components the exact same way. For some reason, the class names are not being used in the rendered page. I use parceljs to bundle my scripts and have checked the source in the browser, the css classes exist. I have tried for hours changing things around to get it to work with no luck, so I'm reaching out to the community for ideas.
Button.tsx
import * as React from 'react'
import styles from './Button.module.css'
import cx from 'classnames'
type ButtonProps = {
color?: 'default' | 'primary' | 'alert' | 'success'
value: string
onClick?: () => void
}
export const Button: React.FC<ButtonProps> = (props) => {
const { color = 'default' } = props;
return (
<div className={styles.buttonContainer}> {/* part of my testing, tried wrapping everything in a div to see if the style would work */}
<button className={cx(styles.buttonContainer, styles[color])} onClick={props.onClick}>
<div className={styles.value}>{props.value}</div>
</button>
</div>
)
}
Button.module.css
.buttonContainer {
color: black;
}
.default {
background: white;
color: var(--colorBlack100);
}
.primary {
background: var(--colorBlue80);
color: white;
}
.alert {
background: var(--colorAlert);
color: white;
}
.success {
background: var(--colorSuccess);
color: white;
}
.buttonContainer .value {
color: inherit;
}
index.ts - used to group all components together
...
export { Button } from './Button/Button'
...
Index.tsx - page to display it
import * as React from 'react'
import { Button } from '../Components'
const Index: React.FC = () => {
return (
<div>
<Button value="Default" onClick={() => console.log("test")} color="primary" />
</div>
)
}
export default Index
Here is the Button div that gets rendered
<div><button class=""><div>Default</div></button></div>
Here is the css from parcel that I pull from source using Chrome dev tools, the classes exist so I know parcel is picking it up
._9p9acG_buttonContainer {
color: #000;
}
._9p9acG_default {
color: var(--colorBlack100);
background: #fff;
}
._9p9acG_primary {
background: var(--colorBlue80);
color: #fff;
}
._9p9acG_alert {
background: var(--colorAlert);
color: #fff;
}
._9p9acG_success {
background: var(--colorSuccess);
color: #fff;
}
._9p9acG_buttonContainer ._9p9acG_value {
color: inherit;
}
As mentioned, I've done this successfully with many other components, this is the only one acting funny and I'm at a loss.
Thank you in advance for your help.
I don't know why, but after deleting the files and adding each line 1 at a time and testing until it no longer worked, I found that it was the CSS class name .default that made it not work. Is this some kind of reserved word? My only other guess is that it's a bug in either parceljs or react-css-modules.

Overwriting MUI with scss

I'm working on a React project that uses MUI and Sass. Currently there are multiple scss-files full of !important to overwrite the MUI styles with sass. I tried to fix this by removing the !important's and adding:
import { StyledEngineProvider } from '#mui/material/styles';
import CssBaseline from '#mui/material/CssBaseline'
<CssBaseline />
<StyledEngineProvider injectFirst>
*** component tree here ***
</StyledEngineProvider>
as suggested here: Issue with #Mui and modularized scss competing intermittently. How to consistently override #mui default styling with scss modules?
Which seemed to work at first but stops working when you focus on a component. For example this button turns white with a blue border when hovered over:
scss
.button {
width: 250px;
height: 50px;
border: 1px solid grey;
border-radius: 15px;
text-transform: none;
}
.go-button {
#extend .button;
background-color: grey;
color: whitesmoke;
}
reactjs
<Button
className="go-button"
variant="outlined"
onClick={handleClick}
>
Go
</Button>
We are not using modules or makeStyles. What would be the best way to overwrite MUI without the !important's?
The default styles for many MUI components will include some styles for specific states like :hover, .Mui-focused that have a higher specificity than the styles of the default state. When overriding those styles you need to use the same specificity.
For instance, Button has default styles specific to hover, so you will need to specify style overrides for the hover state.
For example, here's one possible way to define your button styles:
.button {
width: 250px;
height: 50px;
border: 1px solid grey;
border-radius: 15px;
text-transform: none;
}
.go-button {
#extend .button;
background-color: grey;
color: whitesmoke;
}
.go-button:hover {
#extend .go-button;
background-color: #999;
}
According to my knowledge experience, you must use styled-components with MUI because they have a better pair rather then SCSS, with better pair you have better performance of the website & with styled-components you can easily modify the changes of MUI.
Visit this link for advanced usage

Using ThemeProvider on Styled-Components UI Library

I'm creating a UI library which uses Styled-components and i have a component like this
const Title = styled('div')`
color: ${({ theme }) => theme.sender.color};
font-size: 0.9rem;
padding: 0.5rem 0.3rem 0.5rem;
span {
color: ${({ theme }) => theme.sender.color};
background: ${({ theme }) => theme.sender.botBackground};
border-radius: 0.2rem;
padding: 0.2rem 0.4rem;
text-transform: uppercase;
}
`;
I need to implement in another project, importing the component from my UI Library. I've done all the process to build the library and set it up to be used as a library using rollup and babel.
<ThemeProvider theme={customTheme}>
<Title />
</ThemeProvider>
however when i try to use the ThemeProvider in the project, the theme prop is not being passed down and i'm getting an error because it's trying to get sender from undefined
Any ideas of why this is happening?
A cleaner implementation might look something like this:
const Title = styled('div')`
color: ${ props => props.sender.color};
`;
<ThemeProvider theme={defaultMessageBubbleTheme}>
<Title />
</ThemeProvider>

Apply external custom css to a reactstrap input

I have an issue applying a custom css from an external css module to an Input from Reactstrap.
So I have the following code:
<Input
className={'border-0 p-0'}
style={{
width: '150px',
height: '100px',
fontSize: '18px',
overflow: 'hidden',
resize: 'none',
backgroundColor: 'ffffff',
boxShadow: 'none',
marginTop: '-10px',
marginBottom: '10px'
}}
innerRef={register}
type={'textarea'}
readOnly
/>
It is working now with inline styling, but there are too many properties and I want to put them in an scss external module, but it's not working.
I've tried style={styles.customCss} and it's not working, my custom styles are not applied. I've also tried to put className={'border-0 p-0' && styles.customCss} and still not working.
Any ideas?
In my Css external file I have
.customCss {
width: '150px';
height: '100px';
font-size: '18px';
overflow: 'hidden';
resize: 'none';
background-color: 'ffffff';
box-shadow: 'none';
margin-top: '-10px';
margin-bottom: '10px'
}
and in my component I have
import React from 'react';
import { useForm } from 'react-hook-form';
import {
Container,
Row,
Col,
Label,
Input,
Button,
FormText
} from 'reactstrap';
import classnames from 'classnames/bind';
import styles from './styles.module.scss';
const cx = classnames.bind(styles);
const customComponent = props => {
const { register, handleSubmit } = useForm();
return (
<div className={styles.container}>
<div className={styles.heading}>
<span className={styles.label}>
{heading}
</span>
</div>
<form>
<Col className={'p-0'}>
<Input
className={cx(styles.customCss, 'border-0 p-0')}
id="customer"
name="customer"
defaultValue={lot}
innerRef={register}
type={'textarea'}
readOnly
/>
</Col>
</form>
</div>
);
};
export default customComponent;
I'd assume that you're working with CSS modules when importing the styles, i.e. you have an import styles from './styles.module.scss' at the top of your file.
styles.customCss would contain the actual CSS class name, not the full style object itself. So addressing your attempt in using style={styles.customCss}, that won't work. See CRA's page on CSS modules.
Now for your other attempt in using className={'border-0 p-0' && styles.customCss}, I get the idea that you're trying to concatenate the class name from your custom CSS and Bootstrap's classes. What the code actually does is perform a short-circuit evaluation on 'border-0 p-0' && styles.customCss, which will only evaluate to styles.customCss. For combining CSS classes in the className prop, usually a library like clsx is helpful.
UPDATE
Looks like your CSS file is wrong. You're working with CSS, i.e. the values don't have quotes. That means, your styling would be something like this:
.customCss {
width: 150px;
height: 100px;
font-size: 18px;
overflow: hidden;
resize: none;
background-color: #ffffff;
box-shadow: none;
margin-top: -10px;
margin-bottom: 10px;
}
Working example in sandbox demo

utility classes in styled component react

hi I am using styled componant in react
const H4 = styled.h4`
font-size: 15px;
letter-spacing: 0.38px;
line-height: 1.33;
color: red;
padding: 20px;
`;
<H4>Small header</H4>
it will give exsact style in H4 tag. but how can I override this padding with utility classes like m-b-10 it will give margin-bottom:10px
something like this <H4 m-b-10>small header</H4>
same time I need to use this utility class whereever I want. in css I can simply write
m-b-10{margin-bottom:10px !important};
how can achieve this things on styled componenet?
One of the best solutions is to use https://styled-system.com/, it plays well with Styled Components and other libraries like Emotion and it offers what you need, to use utility-classes in the component definition.
Example:
import styled from 'styled-components'
import { color, space, fontSize } from 'styled-system'
// Set default styles and add styled-system functions to your component
const Box = styled.div`
/*defaut styles */
color: white;
font-size: 25px;
padding: 20px;
/* configurable properties */;
${color};
${space};
${fontSize};
`;
And to use it:
<Box bg="black" >
Lorem Ipsum
</Box>
<Box bg="black" color="green" fontSize="12px" p="10px">
Lorem Ipsum
</Box>
That code, will render this:
It also supports Media-Querys, Themes etc..
You can play with this CodeAndSandbox where it is been used with Styled Components https://codesandbox.io/s/styled-components-with-styled-system-njr17
You can use variables like
const m-b-10 = '20px';
const H4 = styled.h4`
padding: ${m-b-10};
`;
You can define such variables in a separate file and import them to styles components
You can define utility classes in the top component of your React tree. The example uses Gatsby.js, but you can easily adapt it for other React framework.
// src/components/layout.js
const GlobalStyles = createGlobalStyles`
html {
/* Put your CSS variables here*/
}
.m-b-10 {
margin-bottom: 10px;
}
`
Then make whatever defined in createGlobalStyles available for access in child components.
// src/components/layout.js
export default function Layout({ children }) {
return (
<React.Fragment>
<GlobalStyle />
{children}
</React.Fragment>
)
}
// src/pages.index.js
import Layout from "../components/layout"
const H4 = styled.h4`
font-size: 15px;
letter-spacing: 0.38px;
line-height: 1.33;
color: red;
padding: 20px;
`;
const IndexPage = () => {
return (
<Layout>
<H4 className="m-b-10" />
</Layout>
)
}

Resources