React component's styles conflict with other component's styles - css

I have an app component like this:
const App = () => {
return (
<Router>
<Route exact path='/' component={Landing} />
<Route path='/login' component={Login} />
</Router>
)
}
Each component has its own directories and stylesheet. my folder structure is like this:
src
|
|
Landing|
| |
| Landing.js
| Landing.module.css
|
|
Login|
| |
| Login.js
| Login.module.css
|
app.js
index.js
My problem is that the stylesheets of Login and Landing components conflict with each other and the Landing page doesn't look good. for example, the login's background color applies on the Landing page and I don't want this.
I imported only on CSS file in each component like this:
import styles from './Landing.module.css'
and this is an example of how I'm using styles variable:
return (
<div className={styles.navBar}>
<Link to="/">
<img className={styles.logo} src="https://image.flaticon.com/icons/png/512/2039/2039175.png" />
</Link>
{loggedIn &&
<div>
<button onClick={logout}>log out</button>
<Link className={styles.navItem} to="/users">get users</Link>
</div>
}
{!loggedIn &&
<div>
<Link className={styles.navItem} to="/login">log in</Link>
<Link className={styles.navItem, styles.btn} to="/signup">signup</Link>
</div>
}
</div>
)
please help me.

Even if it's old, I'm going to answer for who comes after: the reason why it happens is that your CSS selectors have most likely the same specificity, hence it's the order of appearance that decides which style gets applied.
Login in your folder structure comes after Landing, so your bundler will make Login's styles appear last in your bundled CSS, which then will override your Landing's ones.
There are a lot of solutions to this problem:
you can increase the specificity of the selector that you want to win (e.g. by repeating twice the class in your CSS file)
you can decrease the specificity of the selector you want to lose (e.g. with :where())
now you can use Cascade Layers if you are ok with which browsers are supported (e.g. #layer)
etc...

Related

My Link with href doesn't scroll even though the link changes. Nextjs

I'm working on a react with nextjs project.
I'm using Link to scroll to a specific section on the same page.
Here is one of the components that use Link:
import styles from './section1.module.scss';
import Image from 'next/image';
import Button from '#material-ui/core/Button';
import tought_process from '../../../public/thought_process.png';
import Link from 'next/link';
const Section1 = () => {
return (
<div className={styles.container}>
<div className={styles.left}>
<div className={styles.leftContainer}>
<Link href='#enews'>
<div className={styles.buttonContainer}>
<Button className={styles.buttonstyle1}>Get started</Button>
</div>
</Link>
</div>
</div>
<div className={styles.right}>
<Image
src={tought_process}
className={styles.imageStyle}
alt='how to think about organizing'
layout='responsive'
priority
/>
</div>
</div>
);
};
export default Section1;
And here i mark the element with the id:
<div {...handlers} className={styles.bigBody}>
<NavBar open={menuOpen} toggle={setMenuOpen} scrollY={scrollY} />
<SideMenu open={menuOpen} toggle={setMenuOpen} scrollY={scrollY} />
<div className={styles.sections}>
<Section1 />
<Section2 />
<Section3 id='enews' />
<Section4 />
</div>
Can't figure out what i'm doing wrong.
Multiple clickable elements are wrapping each other. Remove the button and add the anchor element.
<Link href="#enews">
<a>Get started</a>
</Link>
<Link href="#enews">
<a className={styles.buttonContainer}>
<span className={styles.buttonstyle1}>Get started</span>
</a>
</Link>
I'd recommend updating the styles so you can remove the inner span element.
I use a custom link component that does a few things (not shown); one is smooth scroll to hash routes if the browser supports smooth scrolling (not Safari).
import NextLink, { LinkProps } from "next/link";
import { HTMLProps, MouseEvent, FC } from "react";
export const Link: FC<LinkProps & HTMLProps<HTMLAnchorElement>> = ({ as, children, href, replace, scroll, shallow, passHref, ...rest}) => {
const onClick = (event: MouseEvent<HTMLAnchorElement>) => {
if (href.startsWith("#")) {
event.preventDefault();
const destination = document.getElementById(href.substring(1));
if (destination) destination.scrollIntoView({ behavior: "smooth" });
}
};
return (
<NextLink as={as} href={href} passHref={passHref} replace={replace} scroll={scroll} shallow={shallow}>
<a href={href} {...rest} onClick={onClick}>
{children}
</a>
</NextLink>
);
};
I removed new lines to condense the code block
If you went with the above approach, don't include the anchor tag since it's automatically included.
import { Link } from "./custom/path/link"
<Link href="#enews">Get started</Link>
Two points here:
As per the nextjs, passHref has to be used if a custom element is used as a child of Link tag instead of an anchor tag.
As per the same docs value of href should be '/#enews' not '#enews'

React corousel of bootstrap is not styled as how it is supposed to be

Now i want to remove the previous and next and also I want to style the slider which is shown as if it is very old , it's not modern
Acutally i want it to look something like how the react-bootstrap claims their carousel looks like :
Like this:
My code snippet is as follows
<Carousel pause="hover">
{product.images &&
product.images.map((image) => (
<Carousel.Item key={image.public_id}>
<img
className="d-block w-100"
src={image.url}
alt={product.title}
/>
</Carousel.Item>
))}
</Carousel>
I think the problem comes from your css. Did you put the bootstrap one ?
{/* The following line can be included in your src/index.js or App.js file*/}
import 'bootstrap/dist/css/bootstrap.min.css';
and I suggest "antd" instead of bootstrap (https://ant.design/components/carousel/)

Importing scoped bootstrap css

If I import the full bootstrap css import 'bootstrap/dist/css/bootstrap.min.css';
Then it ruins the css for the rest of my webite so I want to scope it around the variables I need it included around (navbar stuff)
I followed the recommended answer here but it didn't seem to work.
First attempt I tried this:
.bootstrap {
#import 'bootstrap/dist/css/bootstrap.min.css'
}
And the second attempt I followed one of the comments that built a local stylesheet and then I did this
.bootstrap {
#import 'scoped-twbs.css'
}
Wihch didn't work either. (By didn't work, I mean the desired css changes were not visible)
I'm working in NextJS. I have a component that looks like this.
const Navbar2 = () => {
return (
<div className={style.bootstrap}>
<Navbar collapseOnSelect expand="lg" bg="dark" variant="dark">
<Container>
<Navbar.Brand href="#home">React-Bootstrap</Navbar.Brand>
<Navbar.Toggle aria-controls="responsive-navbar-nav" />
<Navbar.Collapse id="responsive-navbar-nav">
<Nav className="me-auto">
<Nav.Link href="#features">Features</Nav.Link>
<Nav.Link href="#pricing">Pricing</Nav.Link>
<NavDropdown title="Dropdown" id="collasible-nav-dropdown">
<NavDropdown.Item href="#action/3.1">Action</NavDropdown.Item>
<NavDropdown.Item href="#action/3.2">Another action</NavDropdown.Item>
<NavDropdown.Item href="#action/3.3">Something</NavDropdown.Item>
<NavDropdown.Divider />
<NavDropdown.Item href="#action/3.4">Separated link</NavDropdown.Item>
</NavDropdown>
</Nav>
<Nav>
<Nav.Link href="#deets">More deets</Nav.Link>
<Nav.Link eventKey={2} href="#memes">
Dank memes
</Nav.Link>
</Nav>
</Navbar.Collapse>
</Container>
</Navbar>
</div>
)
}
I'm not sure what I'm misunderstanding
Firsly, in CSS, #import rules must precede all other types of rules, except #charset rules. Hence you cannot nest them inside a selector. Also, in CSS, you cannot actually "nest" selectors. Refer: CSS #import inside a class
However, you can do so in some CSS preprocessor like SCSS that supports them, and is also supported out of box by Next.js itself. Refer: Sass Support | Next.js
Then you just need to do something like this:
// styles/foo.module.scss
.bootstrap :global {
#import "node_modules/bootstrap/dist/css/bootstrap";
}
// pages/index.jsx
import styles from "../styles/foo.module.scss";
const IndexPage = () => (
<div className={styles.bootstrap}>
...
</div>
);
export default IndexPage;
Note the :global switches to global scope for the current selector respective identifier. In easy words it means that without this your bootstrap classes were being hashed out. So unless they were applied like styles.navbar, they were useless. Refer: Exceptions | CSS Modules
Here is a sandbox.

How to correctly specify the path in Link, on the conditionally the same page

I have a link on a profile page that leads to another similar profile page. If you go to the address of the link directly - the page loads correctly. But if you follow the link from the page, only the address of the line changes, the content is not updated.
Link that does not work:
<Link to={`/project/2`} params={ 2 } ></Link>
This link is located on the page at:
<Link to={`/project/1`} params={ 1 } ></Link>
I mean that the fact is that we are actually already on page /project/x, and any change to x will not cause the content to be updated. How to get around this?
UPD:
Code for rendering profile page:
import React from 'react';
import {Link} from 'react-router-dom';
import './css/stl_style.css';
import './css/app_style.css';
import arrow from './images/arrow.png';
import { changeBg, loadProject, hoverText, nohover, TabForOpenNew, openTabNew} from './scripts/portfolio_script.js';
export class ProjectLayout extends React.Component{
constructor(props){
//constructor
}
componentDidMount(){
//componentDidMount
}
render(){
return(
<div id="page">
<span className="stl22 stl21 stl6" >Previous:<pre className="stl3 stl22 stl6 stl23 p5 p6" onMouseOver={(e)=>hoverText(e)} onMouseOut={(e)=>nohover(e)}><Link style={{color:'black', textDecoration:'none'}} to={`/project/ ${this.state.previous.ID}`} params={ this.state.previous.ID }>{`${this.state.previous.NameProject}`.toUpperCase()}</Link></pre></span>
<span className="stl22 stl21 stl6" >Next:<pre className="stl3 stl22 stl6 stl23 p5 p6" onMouseOver={(e)=>hoverText(e)} onMouseOut={(e)=>nohover(e)}><Link style={{color:'black', textDecoration:'none'}} to={`/project/ ${this.state.next.ID}`} params={ this.state.next.ID }>{`${this.state.next.NameProject}`.toUpperCase()}</Link></pre></span>
</div>
);
}
}
And Route in App.js
<Layout>
<Route path='/projectList' component={AllProjects} />
<Route path='/project/:projectId' component={ProjectLayout}/>
<Route path='/home' component = {Main} />
</Layout>
You need to use componentWillReceiveProps and inside that you need to compare old prop values with new prop values and update your state variables using setState, and it will work fine.

CSS Modules and React components, I feel like I am not using CSS modules correctly and my styles are clashing

So I have a search box component that is to be used in the Navigation bar on all pages of the site. I also want to use this component/html in other pages of the site hence I put it inside a component shown below
LocationSearchBox.js
import React, {PropTypes} from 'react'
import {Button,FormGroup, FormControl} from 'react-bootstrap'
import styles from '../scss/components/LocationSearchBox.scss'
export default function LocationSearchBox(props) {
return (
<FormGroup>
<FormControl type="text" placeholder="Search" />
<Button bsStyle="success" type="submit" className={styles.navbarSubmitButton}>Get Weather</Button>
</FormGroup>
)
}
I am using css modules with web pack to convert my scss into css and than generate random styles to use in classnames for the components.
LocationSearchBox.scss
.navbarSubmitButton {
margin-left: 20px;
}
This used inside the component just adds some space between the input and submit button.
This is the NavBar component again with the help of react-bootstrap.
MainNavBar.js
import React from 'react';
import {Navbar, NavbarHeader, NavbarBrand, NavbarCollapse} from 'react-bootstrap';
import {default as Search} from './LocationSearchBox'
import styles from '../scss/components/MainNavbar.scss'
export default function MainNavbar() {
return(
<Navbar fixedTop className={styles.navbarColour} >
<NavbarBrand pullLeft >
<a href='#' className={styles.Brand}>Weather-app</a>
</NavbarBrand>
<Navbar.Collapse>
<Navbar.Form pullRight>
<Search/>
</Navbar.Form>
</Navbar.Collapse>
</Navbar>
)
}
Now I have created a homepage component and I want to use the LocationSearchBox component inside it.
Home.js
import React from 'react'
import {default as Search} from '../components/LocationSearchBox'
import styles from '../scss/components/Home.scss'
export default function Home() {
return (
<div className={styles.center}>
<h2>Enter a city and state</h2>
<Search />
</div>
)
}
The search component inside Home.js, the button has the same margin-left property was the navigation bar so it is moved to the right a bit. I don't want that to happen. I want it only to be applied to the search box used inside the navigation bar but I am unsure of how to do that with CSS modules and React components without creating a separate search box for the navigation bar but I see that as pointless when it will have the exact same code.
I feel like I am not using CSS modules correctly at all, I am not using its philosophy and the point of CSS modules correctly.
It's hard to say what the best approach would be without understanding why it needs to be visually different in those locations but generally I would update <Search /> to accept a new prop to conditionally apply the extra margin.
It could be theme if those two styles are likely to be used many times:
<FormControl type="text" placeholder="Search" />
<Button bsStyle="success" type="submit" className={props.theme === 'foo' ? styles.navbarSubmitButton : null}>Get Weather</Button>
Or if it's more of an override you could provides a buttonClassName prop to add exceptional styles at specific call sites:
<FormControl type="text" placeholder="Search" />
<Button bsStyle="success" type="submit" className={`${styles.navbarSubmitButton} ${props.buttonClassName}`}>Get Weather</Button>

Resources