Overwriting styled component 3 times? - css

I'm using react-bootstrap and styled components on a project and am having issues with extending styles link to docs
For example, im importing and overriding a bootstrap button component:
import styled from 'styled-components';
import Button from 'react-bootstrap/Button';
export const PrimaryButton = styled(Button)`
background-color: ${props => props.theme.purple300};
font-size: 1.25rem;
font-weight: 700;
color: #FFFFFF;
padding: 5px 50px;
border: none;
border-radius: 30px;
box-shadow: 0 10px 28px rgba(0, 0, 0, 0.3);
`;
this is a good start, however, I want to override this in several locations as well, so something like:
import {Button} from './button.style'
const AuthButton = styled(Button)`
background-color: red;
`;
....
<AuthButton type='submit'>Sign In</AuthButton>
AuthButton should have 3 classes (bootstrap, the first styled component, and then the second), but I'm seeing everything except the AuthButton styles/class. I don't see the background-color: red; anywhere in the DOM. I've tried increasing specificity using &&& and still nothing.
Is this a limitation with styled components or am I doing something wrong?

I fixed this. It was due to not having a className prop in my Button component: https://www.styled-components.com/docs/basics#styling-any-component
EDIT: Since the mods are absolutely horrendous on SO, I will add an example:
function MyComponent({className}) { ... }

you need pass className as a props to your component

Related

React Component SCSS available for all Components

I just started learning ReactJS and I made a Project with .scss
For some reason when I add a style in a .scss file that style also changes other components' styles as well.
example:
I add a li style in the Home.scss, but it will change the style of the Footer component's li too. I didn't import it into the Footer.js or anything.
Does anyone know what is the reason why does it do it, and what is the solution?
Adding a className per component won't solve your problem, it will work as expected until you have any nested component.
Because if you add
#component-name {
li {
...
}
}
The CSS will be applied to any component inside of that component too.
To limit your CSS to a component in react, you have a few options :
CSS Modules
Create React App supports CSS Modules out of the box (as of version 2)
It works with SCSS too (YourComponent.module.scss)
YourComponent.js:
import styles from './YourComponent.module.css'
export const YourComponent () => {
<ul>
<li className={styles.yourLi}>
</ul>
}
YourComponent.module.scss:
.yourLi {
color: blue;
}
CSS-in-JS
With this method, as the name suggests, you can declare your CSS within your JS.
There are multiple libraries to implement this.
Styled-Components
Here is an example with styled components which is the one that seems to be the most used as of today:
const YourLi = styled.li`
display: inline-block;
border-radius: 3px;
padding: 0.5rem 0;
margin: 0.5rem 1rem;
width: 11rem;
background: transparent;
color: white;
border: 2px solid white;
`
render(
<div>
<ul>
<YourLi>
Your styled li
</YourLi>
</ul>
</div>
)
Add a class footer in the first div of footer component
sass allows nested defining of classes like
.footer{
li{
}
}
using that can help.
since it doesn't matter where you import scss in react. styles are imported globally by default.

Styling Material UI Button

Hi I just started using Material UI and am having a hard time styling the components. I am building a sign in page and would like my Submit button to be all the way to the bottom right. If someone can help me out that would be greatly appreciated because it seems to be inheriting styles from everywhere else but where I would like to!
I have tried adding
textAlign: 'right'
to buttonStyle and that does not work. I have also tried adding
text-align: right;
to my .form-button CSS.
The only thing that affects anything is removing the .App
Login.js
<div className='form-container'>
...
<Button
style={buttonStyle}
className='form-button'
variant='contained'>
Log-In
</Button>
</div>
...
const buttonStyle = {
backgroundColor: '#527354'
};
App.css
.App {
text-align: center;
}
.form-button {
width: 83px;
height: 36px;
box-shadow: 0px 1px 3px #00000033;
}
.MuiButton-label {
color: var(--primary-white);
font-family: 'Open Sans', sans-serif;
}
.form-container {
max-width: 400px;
margin: 2rem auto;
overflow: hidden;
padding: 0 2rem;
}
Another main goal would be to avoid inline styling because I do prefer keeping it within my style sheet. But if not possible or too overly difficult, I will inline style (as I did with the background-color).
As keikai has mentioned in the comment, you may check the Documentation in this link material-ui.com/styles/basics for overriding style.
For 'it seems to be inheriting styles from everywhere else'
I will suggest you to use styled-components instead of global css import, which mess up everywhere. Try this,
npm install --save styled-components
It creates a css class that only apply to the component.
Sample code:
import styled from 'styled-components'
const MyDiv = styled.div`// can be span, section, etc
// add your style here for the div
your div style(optional)
// your class css inside the div
.form-container {
max-width: 400px;
margin: 2rem auto;
overflow: hidden;
padding: 0 2rem;
}
// add more class if you have any
`
Then wrap your component with
// your newly created styled div
<MyDiv>
// component that needs your style
<MyComponent />
</MyDiv>
Your style will only be applied to MyDiv and MyComponent, and nothing else.
It may took awhile to get used to it, but it is extremely useful.

target first-child css styled-components

I am using styled-components and want to target the first child of Text, but am unable to do so.
const Text = styled.p`
font-size: 12px;
&:first-child {
margin-bottom: 20px;
}
`;
... component
return(
<div>
<p>I am just regular text</p>
<p>Me too</p>
<Text>Hello Joe</Text> // this should have the margin bottom
<Text>Goodbye</Text >
</div>
)
Finally, I got your issue. The styled component confuses with the first two native p tag (from my perspective) and that's the reason why the CSS is not applied.
I will use a workaround like this:
const Text = styled.p`
font-size: 12px;
color: blue;
&:nth-child(3) {
margin-bottom: 20px;
color: red !important;
}
`;
By doing this, you are selecting the third child (which include the first two p tag) for the CSS
OR, you can do something like this: Adding a class name for the tag and giving CSS for that class.
const Text = styled.p`
font-size: 12px;
color: blue;
&.colors {
margin-bottom: 20px;
color: red !important;
}
`;
<div>
<p>I am just regular text</p>
<p>Me too</p>
<Text className="colors">Hello Joe</Text>
<Text>Goodbye</Text>
</div>
Here is the demo
Hope it helps :)
Use like this
const Text = styled.p`
font-size: 12px;
> * {
&:first-child {
margin-bottom: 20px;
}
}
`;
There shouldn't be a space between the & and the :first-child
&:first-child {
margin-bottom: 20px;
}
it's better to use :last-of-type on certain styled component instead of using :nth-child and it works perfectly
export default styled.div`
:last-of-type {
background: red;
}`
const Text = styled.p`
font-size: 12px;
color: blue;
&:nth-child(3) {
margin-bottom: 20px;
color: red !important;
}
`;
This is possible, but probably not correct
This totally is possible, as we see with the other answers. The issue is that with first-child or nth-child solutions you tend to end up reaching down the DOM hierarchy, creating all sorts of specificity issues that can be difficult to untangle later.
The beauty of Styled Components is you typically apply styles to the element itself, meaning your styles stay tightly coupled to your components. Components become portable, and it's easy to find the line of CSS that might be causing an issue in a complex app.
for example, if I were to style the first <a> in a list item in a ul differently, I'd need to put :first-child further up the hierarchy, breaking encapsulation.
Treat your styles as a function
The simple solution to this is to recognise that the styled component is a function that can receive parameters:
<StyledListItem index={index} />
Then receive that parameter in the component:
export const StyledListItem = styled.li<{index?: number}>`
${
({index}) => {
if (index === 3) return `
color: red;
border: 2px dotted pink;
`
if (index === 0) return `
border-left: none
`
}
}
`
CSS in JS facilitates these kinds of programmatic solutions, and your life will be easier if you leverage them.

React Styled Component space between components

I have several styled components in a row with a image.
I just need to add a space between HeaderLinks.
I've tried following way but it doesn't work.
const HeaderLink = styled.a`
color: #000;
font-size: 1.5em;
`;
const Wrapper = styled.div`
HeaderLink + HeaderLink {
margin-left: 1em;
}
`;
HeaderLink1|HeaderLink2|Image|HeaderLink3|HeaderLink4
So I want to add margin between HeaderLink1&HeaderLink2 and HeaderLink3&HeaderLink4.
How can I use styled component in styled css?
Just used ${HeaderLink} instead of HeaderLink.

Styled-components: Interpolated function or component.extend?

In styled-component, how do you decide whether you should use interpolated function to modify component ( by passing props ) or extend the existing component. For example:
const Button = styled.button`
color: palevioletred;
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid palevioletred;
border-radius: 3px;
`;
// We're extending Button with some extra styles
const TomatoButton = Button.extend`
color: tomato;
border-color: tomato;
`;
render(
<div>
<Button>Normal Button</Button>
<TomatoButton>Tomato Button</TomatoButton>
</div>
);
We could have used interpolated function also. How do you decide between the two?
It different, by passing a props we can use it in other situation but if using extends we just use it as an extra style for a new component something like inherit. Example: for nav menu, if there is an active menu, you dont need to use extends. Just use active class using props.So you dont need to do extend or make new component.

Resources