styled-components local variable - css

Coming from SCSS (SASS)
What would be the appropriate Styled-Components implementation of the below SCSS code?
SCSS:
.circle{
$size: 16px; // <-- SCSS FTW. use such a trick in styled-components
height: $size;
width: $size;
.. rest of properties...
}
Currently the styled-component (Circle) looks like this:
...lots of other styled exports
export const Circle = styled.div`
height: 16px;
width: 16px;
background: red;
border-radius: 50%;
`
...lots of other styled exports
Problem is, I want to keep that "meaningless" size variable in the same context where it's consumed (just like in SCSS) because nothing else cares or will ever care about it. I don't think dumping a variable somewhere and then using it with '${size}' is a "clean" way. such tactics are petty and promote messy code-base.

I have devised a neat trick to encapsulate variables only for a specific scope:
styled.h1(({size='4em', color='lime'}) => `
font-size: ${size};
color: ${color};
text-align: center;
`)
I've written a Medium post in the past which breaks down the explenation of this method

One way to solve this problem is to create a separate file with all the variables that you want to use later in your style files:
export const Variables = {
size: '16px',
bgColor: 'red',
}
then you can import it:
import { Variables } from './Variables'
export const Circle = styled.div`
height: ${Variables.size};
width: ${Variables.size};
background: ${Variables.bgColor};
border-radius: 50%;
`

You can use classic css properties (with IE11 polyfill in mind) like this:
--radioWidth: 42px;
.MuiRadio-root {
width: var(--radioWidth);
}
.conditionCollapse {
padding-left: var(--radioWidth);
}

Related

I am trying to use dynamic data to change and trigger classnames but it always only result to true despite data containing false. Any solution?

I am trying to dynamically change the styles based on ternary classnames.
I am trying to change the background to dark or light based on the input on the workWrapper in here:
The CSS:
.normColor{
background-color: #f3f3f3;
width: 100%;
height: 100vh;
margin: 0 auto;
}
.normColor .dark{
background-color: #232A4E;
width: 100%;
height: 100vh;
margin: 0 auto;
}
I already tried messing around with the component, searching for other similar issues to mine and trying to search youtube videos regarding it but I cannot find any solution.
You forget to de-structure your props.
try this :-
const WorkSection = ({workWrapper}) =>{
return(<div className={workWrapper?'normColor':'dark'}></div>)
}
And you checking props, if it is null or not. And it will always give you true, because components always have props

GatsbyJS export styled components

I have created a elementStyles.js file where I am storing some styled-components to later use within my GatsbyJS site: import { Wrapper, PageContent } from "../components/StyledElements/elementStyles"
However, for some reason it keeps giving me error:
"Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports."
My styled components .js file:
import styled from "styled-components"
export const Wrapper = styled.div`
margin: 0 auto;
max-width: 1920px;
padding: 0;
`
export const PageContent = styled.div`
background-color: #455260;
height: 100%;
padding: 50px 90px;
color: #eff1ef;
font-weight: 300;
`
If I remove PageContent and write export default Wrapper at the end it works without problems.
Therefore I've tried to export with different methods:
export default { Wrapper, PageContent }
Any clues on what I might be missing?

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.

I can set a multiple options on one variable in sass and use it?

Let me explain myself, i wanna do something like this in my code
$varible:{
display: inline-block;
width: 14px;
height: 14px;
}
.circle{
&:nth-child(1){
&::after{
$varible;
position:absolute;
...
}
}
}
Create a variable that contains a lot of attributes, and then use it as a global setting later, does anybody know if this is possible, or how I can perform an action like this?
Mixin is basically used to call a block of style but does not return any value unlike function in sass.
The #mixin directive lets you create CSS code that is to be reused throughout the website.
The #include directive is created to let you use (include) the mixin.
#mixin variable{
display: inline-block;
width: 14px;
height: 14px;
}
.circle{
&:nth-child(1){
&::after{
#include: variable;
position:absolute;
...
}
}}

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.

Resources