Produce css value based on boolean value from scss file - css

I have the following which works fine where I am using in line style to decide the percentage values based on a boolean value.
Is there a way I could prevent using inline styling and instead pass this styling to my scss file and still be able to perform this logic more elegantly?
Working copy with inline styling.
const MyPage = ({isSmall}) => {
return (
<div>
<div style={{flex: `0 0 ${isSmall ? '50%' : '33%'}`}}>
hello
</div>
</div>
);
};
export default MyPage;
Looking to be able to move my css to my scss file and use that as a className instead but still be able to toggle the percentage value based on the boolean isSmall prop value.
Move it to scss file.
.flexer {
flex: '0 0 33%' // some way to make the 33% be dynamic and not hard code like this to be able to switch its value between 50% and 33%
}
Then use this flexer class instead of inline css.
Is this possible? Or any better elegant way to achieve this instead of inline?

You can set boolean state and change class name depends on this state inside the className then you can modifiy it in css
const MyPage = ({isSmall}) => {
const [isSmall,setIsSmall] = useState(false);
return (
<div>
<div className={isBigClass `${isSmall} ? "isSmallClass" : ""}`} >
hello
</div>
</div>
);
};
export default MyPage;

Related

multiple conditions for styling with Css modules

I am trying to set multiple conditions with ternary operator to style an element using Css modules. I can't find the exact syntax. is it even possible?
there are some boxes that have 3 sizes , their default small size, the big size for the one that's hovered, and the medium size when at least one of them is hovered.
import style from './styles.module.sass'
const Slider =()=>{
const [hover,isHovered]=useState(false);
const [anyCardHovered,setAnyCardHovered]=useState(false)
return
<div className={`{ hover? ${style.hoveredBox}: anyCardHovered? ${style.smallBox}: style.box}`>
</div>
<div className={hover
? style.hoveredBox
: anyCardHovered
? style.smallBox
: style.box
}></div>
Another way:
/* Bits: hover, anyCardHovered */
const classNames = [
style.box, // 00
style.smallBox, // 01
style.hoveredBox, // 10
style.hoveredBox // 11
];
<div className={classNames[hover << 1 | anyCardHovered]}>
</div>
More details in: https://blog.uidrafter.com/bitwise-table-lookup
I would probably create a variable called classes and set its value and logic above your JSX return statement. Then you could simply set classname={classes} in your boxes.
let classes = 'small';
if(hover) {
classes = 'big'
} else if (anyCardHovered) {
classes = 'medium'
} else {
classes = 'small'
}

How to style a component "from the outside" with scoped css

I'm using scoped CSS with https://github.com/gaoxiaoliangz/react-scoped-css and am trying to follow the following rules (besides others):
Scoped component CSS should only include styles that manipulate the "inside" of the component. E.g. manipulating padding, background-color etc. is fine whilst I try to stay away from manipulating stuff like margin, width, flex etc. from within the component CSS
Manipulating the "outside" of a component (margin, width, flex etc.) should only be done by "consuming" or parent components
This is rule is somewhat derived from some of the ideas behind BEM (and probably other CSS methodologies as well) and allows for a rather modular system where components can be used without "touching their outside" but letting the parent decide how their internal layouts etc. works.
Whilst this is all fine in theory, I don't really know how to best manipulate the "outside styles" of a component from the consuming code which is best shown with an example:
search-field.scoped.css (the component)
.input-field {
background: lightcoral;
}
search-field.tsx (the component)
import './search-field.scoped.css';
type SearchFieldProps = {
className: string;
};
export const SearchField = (props: SearchFieldProps) => {
return <input className={`input-field ${props.className}`} placeholder="Search text" />;
};
sidebar.scoped.css (the consumer)
.sidebar-search-field {
margin: 16px;
}
sidebar.tsx (the consumer)
import './sidebar.scoped.css';
// ...
export const Sidebar = () => {
return (
<SearchField className="sidebar-search-field" />
(/* ... */)
);
};
In the above example, the CSS from the class sidebar-search-field in sidebar.scoped.css is not applied because the class passed to SearchField is scoped to the Sidebar and the final selector .sidebar-search-field[data-sidebarhash] simply doesn't match as the input element of the SearchField (obviously) doesn't have the data attribute data-sidebarhash but data-searchfieldhash.
ATM, I tend to create wrapper elements in situations like this which works but is rather cumbersome & clutters the markdown unnecessarily:
// ...
export const Sidebar = () => {
return (
<div className="sidebar-search-field">
<SearchField />
</div>
(/* ... */)
);
};
Question
Is there any way to "style scoped CSS component from the outside"?
Ps.: I'm not sure if all the above also applies to scoped styles in Vue. If not, please let me know how it works there so that I can create a feature request in https://github.com/gaoxiaoliangz/react-scoped-css.

How to use urls in React CSS inline styling without `$`?

Learning React and trying to cheat off this codepen. I do not understand 2 things.
What is the ... before largebox, flex, and other css classes?
return <div style={{...largebox, ...flex}} key={props.id}
What does the $ do in the css url param? Is it jQuery?
`url(${props.photo})
const FormCard = (props) => (
<div>
{
DATA.map((props) => {
return <div style={{...largebox, ...flex}} key={props.id}>
<div style={{...Photo,backgroundImage: `url(${props.photo})`}}></div>
<div>
<Author author={props.author}/>
<Something bio={props.bio}/>
<AdBox adpic={props.adpic} />
<IconBox />
</div>
</div>
})
}
</div>
)
The three dots '...' are called spread operator, see here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax
The $ sign is no Jquery but is actually referencing template literals: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals
Hopefully, the docs are enough as I currently can't find [the link] to [that tutorial] I remember...
Spread operator:
const styleA = { color: 'red' };
const styleB = { background: 'blue' };
const styleC = { ...styleA, ...styleB };
// styleC = {color: "red", background: "blue"}
String Template:
const user = 'Bob';
const greetings = `Hello ${user}`;
// greetings = 'Hello Bob'
for your first question we call it Spread Operator in a simple description for below line :
style={{...largebox, ...flex}}
this is mean copy all property of largebox and flex object into a new object and assing it to style.or this line means :
style={{...Photo,backgroundImage:"myurl}"}
create a new object for me with all property of Photo object and also add a property with name backgroundImage to it. so if Photo is equal to {name:'1.jpg'} the new object is equal to
{name:'1.jpg',backgroundImage:"myUrl"}
Now for your second question, this is template literal and allow you to write variables or call functions inside a string. think we have not this so we must write it like :
backgroundImage: "url(" + props.photo +")"
so as you see it is something like concating props.photo and other strings.but with template literals we can wrap string with backticks and then write variable or function of javascript between ${} like below
backgroundImage: `url(${props.photo})`
then ${props.photo} replace with its value.

How to get access to the children's css values from a styled component?

I am using a REACT BIG CALENDAR and I want to get access to the css values in one of my functions.
I created a style component and override the library
const StyledCalendar = styled(Calendar);
Now for example there is a div inside of the Calendar with the class = "hello",
How would I access the css values of "hello" in a function? Similar to property lookup say in stylus.
I have tried window.getComputedStyle(elem, null).getPropertyValue("width") but this gives the css of the parent component.
If you know the class name, you should be able to select that and give that element to getComputedStyle instead of giving it StyledCalendar. Something like:
const childElement = document.getElementsByClassName('hello')[0];
const childWidth = getComputedStyle(childElement).getPropertyValue('width');
(this assumes that there's only one element with the class 'hello' on the page, otherwise you'll have to figure out where the one you want is in the node list that's returned by getElementsByClassName)
You can do it using simple string interpolation, just need to be sure that className is being passed to Calendar's root element.
Like this:
const StyledCalendar = styled(Calendar)`
.hello {
color: red;
}
`
Calendar component
const Calendar = props => (
// I don't know exact how this library is structured
// but need to have this root element to be with className from props
// if it's possible to pass it like this then you can do it in this way
<div className={props.className}>
...
<span className="hello"> Hello </span>
...
</div>
)
See more here.

Assign two className to child

I have below code in my parent's component -
<Button className={'row1 column1'} value={'1'}/>
So I am sending two className to the child's component.
Then in my child component I have
render() {
var { value, className, ...other} = this.props;
return (
<button className={s[className]}> {value} </button>
)
}
}
export default withStyles(s)(Button);
usually I manually set className={s.something} and it works, but this is not. In rendered html it looks like - <button is="null"></button> Any idea?
Supposed you use react-with-style, withStyles will add a styles object to your props.
This object does not know any classNames, you just need to pass those styles to your button as inline styles.
e.g.:
render() {
var { value, className, style, ...other} = this.props;
return (
<button
className={ className }
style={ style }
>
{ value }
</button>
)
}
EDIT:
The advantage of withStyle is to use inline styles. And I suppose your s object does not have a key row1 column1 but rather row1 and column1, so you would need to manually split the classname.
But then again, why do you want the styles in the className?

Resources