How to add multiple css property with same name in react? - reactjs

I am using react and came across a situation where I needed a fallback CSS property.
Normal CSS code:
.grid{
position:sticky;
position: -webkit-sticky;
}
Currently, I am getting it done by using two different classes and adding both the classes to the component (using classnames library).
Like this:
<Grid className={classnames(c1,c2)}/>
where c1 and c2 both have position property but with different values.
My question being that am I doing it in the right manner? If not, Is there any workaround?

.c1{
position:sticky;
}
.c2{
position:-webkit-sticky;
}
The browser will apply what it suports. I never worked with React, but I'm pretty sure there'd a better way to write the fall-back properties.

Related

Customizing children components' styles through parent with JSS

I'm currently working on a project which has all of its styles declared in JSS. One of the "benefits" highlighted on many articles and the library docs is that it encapsulates styles. However I really am having a hard time customizing them, specially when it comes to styling that depends on the component's surrounding context (by context I mean parent elements, siblings, etc.).
Consider the following styles exported along a component called FieldDescriptor via the withStyles HOC:
info: {
fontFamily: theme.typography.fontFamily.light,
fontSize: "12px",
padding: "0 24px 8px 24px",
letterSpacing: 0.3,
},
This class will be found as FieldDescriptor-info-xxx on the element having that class. Now suppose that this component is child to another one that attempts to target the error class. You could target that class with something like [class*=FieldDescriptor-error] (personally I already consider this a very unclean approach) and it will work only on a development environment.
On production, classes will become unique (e.g. jss-xxx) and selectors like the one above will no longer be useful. My question is, what is the cleanest or "correct" approach to customizing component styles like this in JSS? I am either missing something really obvious or perhaps facing the limitations of JSS.
I am looking forward to solutions that do not require more tooling or code bloating, that would really miss the purpose of adopting JSS in the first place.
You can find an example using both withStyles and useStyles here
Try to think of a component as of a black box that intentionally hides implementation details from the outside world.
With this model, only component itself is responsible for it's presentation, so you need to ask that component to change something. In React world you do that most of the time by passing props to that component.
Inside of that component you can go multiple ways, combining the predefined classes depending on the props (preferred because static) or using function rules/values which let you access the props and define the styles per component instance.

Large react app with styled components performance problems

I'm a developer of a fairly large react application. A part of the application is a detail form that is loaded dynamically and can consist of about 100 input fields of different data types (different components).
The initial render of this form takes about 500ms on my laptop and i'd like to make it faster. I'm not quite sure what causes this render time but i share with you what i have:
This is a screenshot of the react profiler. As you can see there are some commits happening but one (orange) stands out. This is where the actual form is rendered. The form is a hierarchy of composed layouting boxes, other containers and the field container with the label and the data-type component inside. A single component does not take too long to render, but added up is why I end up with 500ms.
if we take a closer look at a small part of this screenshot above we can see this:
This is a small section inside a date edit field that gets rendered because we have a field of data type date. The first element is a styled component
const StyledDateAbstractWrapper = styled.div`
&& {
align-items: center;
cursor: ${props => props.immutable ? 'not-allowed' : 'default'};
display: flex;
input {
display: ${props => props.immutable ? 'none' : 'block'}
&:last-of-type {
display: ${props => props.immutable ? 'block' : 'none'}
}
}
}
`
as you see, nothing fancy. But it takes 2.3ms to render. And inside a styled button that takes 5 ms. Let's say i have a couple of these and that's how i end up with 500ms.
At this point i really think styled-components is the problem because i have some components take a couple of milliseconds as expected and many many small styled-component wrappers that each take more than a millisecond.
So my question... is there something i can further investigate? Or are there clear no-goes for styled components that are rendered many times such as element selectors?
Im using styled-components 5.0.1
Another approach would be using something like https://github.com/bvaughn/react-window but i dont have a list really. more some composed components.
Providing a running application is a bit tricky at the moment.
thank you for any suggestions
You are right, Styled Components is slowing down your application. It's easy to reason when you think about what each styled object does:
parses the injected props;
generates the actual CSS code;
generates an unique class identifier;
applies the unique identifier to the className of the underlying React object;
injects the generated CSS at the end of the <head>, under the unique class identifier.
Only then the browser renderer will apply the CSS onto the DOM elements.
Remember: this is done for each styled object you create. With many elements, it's easy to see how this blows up, because it doesn't scale up well.
My suggestion is to move away from Styled Components and adopt SCSS modules. You'll end up with a plain static CSS file, and unique class names generated at buildtime, and nothing done at runtime. Can't go faster than that.
Foo.module.scss
.myTitle {
font-size: 3em;
}
Foo.tsx
import css from './Foo.module.scss';
function Foo() {
return <div className={css.myTitle}>Hello</div>;
}
export default Foo;
The cons are that you'll need separate .scss files, and injected values will have to be reworked into class names with the SCSS preprocessor. But there are advantages too: you can have all built-in SCSS features, wich are great.
I can't say much without seeing the proper implementation on this case, but from what I can think of you have a few options.
1 - Instead of having components with display: none you can simply remove them from the DOM with { !immutable && <Component /> }, this way the component won't take space in the VirtualDOM
2 - Second problem could be the Form library you are using, here is a performance overview of some of them. Performance Comparison. Maybe changing the lib you are using also helps.
First and foremost: usability wise, 100 form elements is insane! No user would ever go through the hell of filling this many (or even a quarter) of these elements. I suggest going back to your designer/product people and telling them to come up with a better way to model the business flow.
Really, forget about performance. No user will ever fill this form and it is better to realize and fix it now than in hindsight.
As for performance: 100 form elements is a lot! A desktop browser can surely handle that HTML, but rendering it all in React has its overhead in JS/DOM land. I'd say that half a second is quite good, considering the amount of work the browser has to carry out. And with styled-components in the mix, you're also straining the CSSOM.
There are additional optimizations and techniques which can be applied, though they won't be necessary once you restructure the app to not render so many DOM elements which your users won't be able to handle anyway.

How to exclude global styles in a React App?

I am using Material UI for building my React Project.
However there is a component which has to be embedded to a different site. Meaning, I am providing the production build of this component to embed it to a different site.
My React app's css is getting overridden by the global styles defined in that website.
I don't want this behaviour. Is there any way I can isolate the css of my react app and the global css of the other website.
I saw this question but the solutions didn't help me.
If iframes and Web Components are out of the question, the only remaining option is CSS resets.
Create a CSS class and a series of rules that reset the styles of any elements that occur inside that class.
.my-reset {
/* Global resets (e.g. font family) */
}
.my-reset p {
/* Reset paragraph styles */
}
.my-reset label {
/* Reset label styles */
}
/* etc. */
Apply that class to the root-level component:
function MyApp() {
<div className="my-reset">
{ /* app goes here */ }
</div>
}
There are plenty of CSS reset libraries out there. Since you have no control over global styles, you're going to have to be heavy handed with the resets. So if it's at all possible, make your component embeddable as an iframe.
I see multiple solutions to this problem
Use !important in those styles possible.
Use id to give styling instead of class, as id has higher presidence.
If you give more specific styling to the elements then the build file css will override the outer site's css, i.e like if we write our css like .parent#child this is more specific styling and it will override the wrapper site's css.
Check this out https://stuffandnonsense.co.uk/archives/css_specificity_wars.html
There's another sort of scrappy solution that you could use in the case where you don't need the old table style and the new Material-UI tables on the same HTML page.
If you own the site that you are trying to embed the React app in (i.e., you have control over the new environment's CSS), another thing you could do to reset the CSS styles for the components in your app is to remove the classes that are overwriting your styles.
For example, if you're using Material-UI tables and your existing table styles are affecting the render, you could put the existing table styles into a separate CSS file that you only import when you render your existing tables, on another HTML page.

Office UI Fabric - How to apply css styles to existing components

I'm using the provided components and every time I need to change a component style I wonder what's the proper way to do it.
Lets say I need to change the IconButton background color when it's disabled.
https://codepen.io/elsl/pen/KrQQdV
If I provide a theme, how am I supposed to know which palette/semanticColor is used by that component?
const iconsTheme = Fabric.createTheme({
semanticColors: {
disabledBackground: "#ff9933"
}
});
<Fabric.IconButton
iconProps={{iconName:'ChevronRight'}}
disabled
theme={iconsTheme}
/>
If I provide an IButtonStyles, how am I supposed to know that the property name is "rootDisabled.backgroundColor"?
const iconButtonStyles: IButtonStyles = {
rootDisabled: {
backgroundColor: "#ff0000",
}
};
<Fabric.IconButton
iconProps={{iconName:'CalculatorEqualTo'}}
disabled
styles={iconButtonStyles}
/>
For both these options, I had to dig into the component's source code on github to find out.
Is this the expected/correct way?
If so, between creating a Theme or an IStyle which would be the ideal/best practice?
Theme vs IStyles
I would say, use a Theme if you want all Fabric components to have the same customization.
Use the styles property if you just want to customize that specific component (or that one specific instance of the component).
How to discover the styling hooks if using IStyles
There are four ways that comes to mind.
Look at the documentation (e.g. https://developer.microsoft.com/en-us/fabric#/components/dropdown, look at the IDropdownStyles interface)
(screenshot)
Utilize IntelliSense if you're using an editor like Visual Studio Code, which automatically enumerates the IComponentStyles and provides documentation if any.
Inspecting the DOM often provides hints (the hook areas usually look like {area}-{number} so root-33 for instance where the "area" name is root.
Read the source code.
Unfortunately for option 1 and option 2, Fabric React isn't super consistent with the IComponentStyles documentation so not all components have equally descriptive comments and in those cases, you may need to fallback to option 3 and option 4.

Keep classnames with CSS loader or organize code in React?

How can I use my own class names when using CSS and Style loaders? I'm using React and i often get confused with all the class names and the related components. If it is not recommended to keep the class names, how can I organize my code in a manner that it don't get messy?
You can use normal classNames and then import the relative .css file that has the style for those classes. Something like this:
MyComponent.js
...
import '/path/to/css/style.css'
...
render() {
return(<div className="MyComponent">Hello</div>);
}
...
style.css
...
.MyComponent {
width: 100px;
background-color: red;
...
}
...
And this would work just fine, with this approach though you are in charge of naming your classes and making sure there are no collisions and everything is named properly (you can then follow BEM techinque or others as you prefer).
Otherwise there are other approaches that I am not gonna explain into details because the relative docs are great and don't need any addition.
You can use Css Modules or Styled Components. There is also this article that has a good overview of these methods and can help you out make a final decision.

Resources