Prevent a style (accidently loaded globally) from applying to a control - css

I'm trying to use TextField of Fluent UI.
import React from 'react';
import { TextField } from '#fluentui/react';
class Try extends React.Component {
render() {
return (
<TextField label="With auto" multiline autoAdjustHeight/>
);
}
}
export default Try;
Then, I realize that there is no space between the label and the text area. I check the CSS and understand that it is due to a label { margin-bottom: 5px; height: 22px } defined in index.css of another component XXX. Many tags and classes are defined in XXX/index.css such as form, label, input, button. Because I have import ./index.css in the component XXX and import ../XXX/index.css in several other components, XXX/index.css is loaded globally. And this XXX/index.css disturbs label of TextField of Fluent UI inside Try.
Does anyone know what I could do to Try component such that its TextField is not disturbed by XXX/index.css?

You may do this.
create another css file and load that css globally or just change that particular css only this the following.
label:not(#dont-apply-label *) { margin-bottom: 5px; height: 22px }
Now when you call the Fluent-Ui component, give a id
<TextField id="dont-apply-label" label="With auto" multiline autoAdjustHeight/>
This might not be best solution out of the box. But worth trying.
Another way can be triggering with class name like the following but not sure gonna work.
label:not(.ms-TextField *) { margin-bottom: 5px; height: 22px }

Related

Override margin in Separator Component of Fluent UI using React

I'm trying to override the margin attribute of a Separator component using Microsoft's Fluent UI using React. The top-margin appears to default to 15px and I would like it to be less than that.
Here's a screenshot:
The beige color section above is defaulting to 15px and I'd like to shrink it but I can't seem to find the correct css to do so.
Here's the code I have thus far:
const separatorStyles = {
root: [
{
margin: 0,
padding: 0,
selectors: {
'::before': {
background: 'black',
top: '0px'
}
}
}
]
};
export default class Home extends Component {
render() {
return (
<Stack verticalAlign="center" verticalFill gap={15}>
<Component1/>
<Separator styles={separatorStyles} />
<Component2 />
</Stack>
);
}
}
I've tried placing the margin: 0 where it currently is at the root level and also nested below the ::before but neither have worked.
The only other potential clue I have comes from an inspection of the styles in Chrome's DevTools which yields:
Any ideas would truly be appreciated!
Thanks for your time!
The 15px actually came from the gap prop that was passed to the Stack component. It takes care of adding that css class to children elements to ensure the proper margins exist.
I believe removing it altogether should solve your concern, such as in this example (link to working code):
<Stack verticalAlign="center" verticalFill>
<button>Button1</button>
<Separator>no margin</Separator>
<button>Button2</button>
<Separator />
<button>Button3</button>
</Stack>
However, it is worth noting that the Separator expects to render some text, so you might have trouble getting it to be the exact height you want (as font-size is a concern for the Separator). If that's the case, you might be better off just making your own control to render a 1px line with a simple div or span.
Also you can you use this approach with styled-component:
import React from 'react'
import {Separator} from '#fluentui/react'
import styled from 'styled-components'
const StyledSeparator = styled(Separator)`
&::before {
margin-top: 15px;
}
div {
//any styles for separator-content
}
`
export const Divider = ({children}) => {
return <StyledSeparator>{children}</StyledSeparator>
}

Applying CSS stylesheet only to active component

I'm working on a ReactJS app that has a header at the top, a menu on the left, and the "frame" in the middle is where routes and their corresponding components are loaded. I want to be able to apply a CSS stylesheet to specific components only when they are loaded. I also don't want them applied all the time or to the top header or left menu.
My expectation was that adding import 'custom.css'; to a specific component would only apply the stylesheet's styles to that component and it's children when the route is active. Instead, it applies it to the entire page even when the route/component are not loaded.
I understand that an alternative approach is styled components, but, for my use-case, a design company is supplying a stylesheet (which should remain unchanged) that we need to consume only for the sub-module I'm working on and I don't want its styles to affect the rest of the app.
How can I have a stylesheet only applied to my active route/component?
Use simple CSS technique. Suppose you have two components with different css files (say about.css and contact.css). Now consider your both CSS file have one common class with different style properties, like:
about.css
.container{
max-width: 400px;
}
contact.css
.container{
max-width: 500px;
}
Yes in ReactJS both the CSS files will load at the same time and will override any one of the style. so to solve this problem add class to differentiate this styles, like:
about.css
.about-component.container{
max-width: 400px;
}
contact.css
.contact-component.container{
max-width: 500px;
}
If you want apply only when the component is mounted, you can use the lifecycle.
The follow example is based in the idea you are using sass, React, sass-node and have the loaders into webpack.
<pre>
import React from 'react';
import './styles.scss';
class MyComponent {
constructor(props) {
super(props);
this.state = { className: '' }
}
componentDidMount() {
this.setState({
className: 'myOwnClass'
});
}
render(){
return (
<div className={this.state.className}>This is a example</div>
);
}
}
export default myComponent;
</pre>
To be able to only call that specific CSS when you need it you can use CSS Modules. You may need to update your version of react.
When saving your CSS file save it with a ".module.css" eg. "styles.module.css". The CSS in these files can only be used and accessed by hte components where are they are imported. As stated in a tutorial from W3Schools.
Let's say this is your CSS code in styles.module.css:
.container {
color: white;
}
.cont-child {
background-color: red;
}
Then in your JS file you can import the CSS file like this if the JS and CSS files are in the same directory. Make sure you point to the correct path.
import styles from './styles.module.css'
Then in your HTML section you can use it like this:
class Home extends React.Component {
render() {
return(
<main className={ styles.container } >
<div className={ styles["cont-child"]} >
Some div text about something...
</div>
</main>
);
}
}
I currently use both ways to access the selectors, since the styles variable acts like an object. I placed both of them here because the second option is capable of fetching selectors named like "btn-active". Which comes in handy in some situations. Camelcasing is considered cleaner though.
Please note: I originally posted this answer as a reply to a similar question here React CSS - how to apply CSS to specific pages only
I want to be able to apply a CSS stylesheet to specific components
only when they are loaded.
Why not apply the styles inline via React.js?
Step 1. Create the style object for the component:
var componentOneStyle = {
color: 'white',
backgroundColor: 'red'
};
Step 2. Populate the component's style attribute with the style object:
ReactDOM.render(<div style={componentOneStyle}>This is Component One</div>, mountNode);

CSS Specificity with CSS Module

First, let me say I understand that I have a custom component "Card" that I use in one of my routes, "Home".
Card.js
import s from 'Card.css';
class Card {
...
render(){
return (<div className={cx(className, s.card)}>
{this.props.children}
</div>);
}
}
Card.css
.card {
display: block;
}
Home.js
<Card className={s.testCard}>
...
</Card>
Home.css
.testCard { display: none; }
A problem I faced here, is that the card remained visible even though I set the display to none, because of seemingly random CSS ordering in the browser. This ordering did not change even if Javascript was disabled.
To get .testCard to correctly load after .card, I used "composes:":
Home.css
.testCard {
composes: card from 'components/Card.css';
display: none;
}
Apparently this causes css-loader to recognize that .testCard should load after .card. Except, if I disable Javascript, the page reverts back to the old behavior: the .card is loaded after .testCard and it becomes visible again.
What is the recommended way to get our page to prioritize .testCard over card that behaves consistently with or without Javascript enabled?
As I'm using CSS modules, charlietfl solution wouldn't really work as is. .card is automatically mangled to a name like .Card-card-l2hne by the css-loader, so referencing it from a different component wouldn't work. If I import it into the CSS file of Home.css, that also doesn't work, because it creates a new class with a name like .Home-card-lnfq, instead of referring to .Card-card-l2hna.
I don't really think there's a great way to fix this so I've resorted to being more specific using a parent class instead.
As an example, Home.js:
import s from 'Home.css';
import Card from './components/Card';
class Home {
...
render(){
return (
<div className={s.root}>
<Card className={s.testCard}>Hi</Card>
</div>
);
}
}
Home.css
.root {
margin: 10px;
}
.root > .testCard {
display: none;
}
This way, we don't need to know what class names component Card is using internally, especially since in cases like CSS Modules or styled components, the class name is some unique generated name.
I don't think I would have come to this solution if it wasn't for charlieftl's solution, so thank you very much for that.
Just make the testCard rule more specific by combining classes
.card {display: block;}
.card.testCard { display: none; }

Component is briefly rendering without styles on first render

When I open my react app, the component below flashes with width:100%, probably because it inherits it from the material-ui card.
In my react app there are a lot of these components being rendered, each with their own width which are based on the parent component's data. I set the width with an inline style based on the props.
As I understand, the component has the inline style as it is created and there should be no delay to apply it. However I see all the SceneThumb components with 100% width for a a fraction of a second, before they apply the given inline style.
If I change the css of scene-thumb-parent to include some width, say 10% for example, then I'll see them all with 10% for a fraction of a second, before the inline style is applied. That makes me think there is a delay in applying inline css, but it really puzzles me..
Is this to be expected of react? Or of html in general? Is there any way to reduce this inline style application delay? Maybe it's something to do with the dev hot reloading setup I get from create-react-app?
SceneThumb.js (code that is irrelevant to the question has been omitted):
import React, { Component } from 'react';
import './scene-thumb.css';
import Card from 'material-ui/Card';
class SceneThumb extends Component {
render() {
return (
<div
className='scene-thumb-parent'
style={{width:this.props.width, left:this.props.left}}
>
<Card
className={this.props.selected?'scene-thumb-selected':'scene-thumb'}
>
<span>
Hello world!
</span>
</Card>
</div>
);
}
}
export default SceneThumb;
scene-thumb.css:
.scene-thumb-parent {
position:relative;
text-overflow:clip;
white-space:nowrap;
overflow:hidden;
min-width: 12px;
}
.scene-thumb-selected {
border: 2px solid red;
border-radius: 5px;
}
.scene-thumb,.scene-thumb-selected {
padding: 2px;
margin:2px;
position:relative;
}
The width prop is initially null or some other value. A moment later, the prop is updated which triggers another render. This is why you're seeing the flash you're talking about.
You can test this by adding the following to your render() function:
console.log(this.props.width)
You'll probably see it logging at least twice with different values.
There are many ways you can fix this. What makes most sense would depend on the rest of the application, and your personal preference. Regardless, here's one way:
render() {
if(!this.props.width) return null; //if it's null, render nothing.
return (
<div className='scene-thumb-parent' style={{width:this.props.width, left:this.props.left}}>
<Card className={this.props.selected?'scene-thumb-selected':'scene-thumb'}>
<span>Hello world!</span>
</Card>
</div>
);
}

CSS Modules, React and Overriding CSS Classes

I am using a React component library (React Toolbox), which is outputting this class in their Tab component using CSS Modules and Webpack: label___1nGy active___1Jur tab___Le7N The tab is a className prop I am passing down. The label and active classes are coming from the library. I want to apply a different set of styles on active, something like .tab.active where tab is referring to the styles I have created and active matches the generated selector the library has created but cannot figure out how to do this with css-modules. I need to override this dynamically selector: .label___1nGy.active___1Jur.
[]]2
[]3
Old post but still relevant, so adding an answer to help those with similar issue
While not inherently possible in CSS modules alone, the author of the react-toolbox library has actually solved this particular problem very nicely
Read their github docs which are more in depth on the subject at https://github.com/react-toolbox/react-toolbox#customizing-components
A list of the themeable classes for a particular component is given on the component demo page on their site too
In your case as well as passing a className for tab, you would also create a theme with classes that overrides that desired parts of the default theme and pass that as the theme prop. For example something alog the lines of...
MyComponentWithTabs.css
.tab {
color: white;
}
MyTabTheme.css
.active {
color: hotpink;
}
MyComponentWithTabs.js
import styles from './MyComponentWithTabs.css'
import tabTheme from './MyTabTheme.css'
// blah blah...
return <Tab key={index} className={styles.tab} theme={tabTheme} />
Under the surface this uses a decorator they have abstracted into separate library react-css-themr, I recommend giving that a read too as it explains how the defaults are composed with your overrides in much greater depth, including the different merging strategies they use
I had a similar case, and I solved it like so:
import classNames from 'classnames';
...
const activeClassName = {};
activeClassName[`${styles.active}`] = this.props.isActive;
const elementClassNames = classNames(styles.element, activeClassName);
return <div className={elementClassNames} />
I'm using the classnames package to dynamically add the active class based off of the isActive prop. Instead of an isActive prop you can provide any boolean value.
A more terse way of doing this may be:
const elementClassNames = classNames(styles.element, {[styles.active]: this.props.isActive});
CSS modules won't allow you to safely override the active className (largely by design). Really it should be exposed via an API, e.g. 'activeClassName'.
If the maintainers disagree or you need this quick then you can quite easily add your own active className because your implementing component is managing the index state:
import {Tab, Tabs} from 'react-toolbox';
import styles from './MyTabs.css';
class MyTabs extends React.Component {
state = {
index: 1
};
handleTabChange(index) {
this.setState({ index });
}
render() {
const { index } = this.state;
return (
<Tabs index={index} onChange={this.handleTabChange}>
<Tab label="Tab0" className={index === 0 ? styles.active : null}>
Tab 0 content
</Tab>
<Tab label="Tab1" className={index === 1 ? styles.active : null}>
Tab 1 content
</Tab>
</Tabs>
);
}
}
Disclaimer: Code is untested.
Group style loader
You can use the group-style-lader to override the style of the components. This loader gives you an easy and intuitive way of override the style of the components.
Configure the loader
Install the loader
npm install --save-dev group-style-loader
Configure the loader in your webpack settings
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
'group-style-loader',
'style-loader',
{
loader: "css-loader",
options: {
modules: true
}
}
]
}
]
}
};
You only need to put it, before the style-loader or the mini-css-extract-plugin loader.
Override the style of the components
The next example show as you can to override the style of the Card component from the App component.
You can define the style of your component as you are used to.
card.css
.container {
width: 300px;
height: 400px;
border-radius: 8px;
}
.title {
font-weight: bold;
font-size: 24px;
}
.summary {
margin-top: 24px;
font-size: 20px;
}
The unique difference is that in the Card component, you going to use the mergeStyle function to merge the custom style with the default style of the component.
card.jsx
import React from 'react';
import { mergeStyle } from './card.css';
export function Card({ customStyle }) {
const style = mergeStyle(customStyle);
return (
<div className={style.container}>
<div className={style.title}>Title</div>
<div className={style.summary}>
Lorem ipsum dolor sit amet, consectetur
adipiscing elit, sed do eiusmod tempor.
</div>
</div>
)
}
Then, in the App component, to override the style of the Card component you need to define the custom style of the Card component using the separator _. All the classes using this separator going to be grouped in the card property of the style object.
app.jsx
.title {
font-size: 32px;
font-weight: bold;
margin: 44px;
}
.list {
display: flex;
}
.card_title {
color: blue;
}
.card_summary {
color: green;
}
Finally, you only need to pass the custom style of the Card component through the customStyle property of it.
app.jsx
import React from 'react';
import { Card } from './card';
import { style } from './app.css';
export function App() {
return (
<div>
<h1 className={style.title}>Group style</h1>
<div className={style.list}>
<Card/>
<Card customStyle={style.card}/>
</div>
</div>
);
}
In the previous example, you have two Cards components, the first uses its default style, and the second uses the customs tyle that we have defined.
You can see a full explanation of how to use the group-style-loader in its repository.
Using :global(.classname) you can override the external classnames.
Even 3rd party library css can be override.
:global(.active) {
color: hotpink;
}
trick in fileName.css
add className-active after declaring className
.className{
background: white;
}
.className-active{
background: black;
}
<div className={'className className-active'} />
<div className={'className-active className'} />
divs always will be black

Resources