I am dealing with 2 components:
header.js and footer.js.
I also have 2 css files:
header.module.css and footer.module.css.
Both of them use different styling for the a tag.
I import the respective CSS files within each js file, but the a styling in footer.module.css seems to overtake the styling in header.js even though it wasn't imported.
Here is the code:
header.js
import React from "react"
import { Link } from "gatsby"
import "../styles/header.module.css";
const ListLink = props => (
<li style={{display: `inline-block`, marginRight: `1rem`, fontSize: '1.15rem', fontWeight: 'bold'}}>
<Link className="link" to={props.to}>{props.children}</Link>
</li>
)
footer.js
import React from "react"
import "../styles/footer.module.css";
const FooterLink = props => (
<li style={{ display: `inline-block`, marginRight: `1rem`, marginBottom:'0rem', fontSize: '1.05rem', fontWeight: 'bold'}}>
{props.children}
</li>
)
header.module.css
a {
color: var(--textLink);
text-shadow: var(--textShadow);
transition:.2s;
background-image: var(--bgimage);
}
a:hover {
color: #da1e11;
background-image: none;
}
footer.module.css
a{
color: var(--textLink);
text-shadow: var(--textShadow);
transition:.2s;
background-image: none;
}
a:hover {
color: #da1e11;
background-image: none;
}
The background-image property from footer overtakes the one specified in header.
If you are using Gatsby's default <Layout>, it shares <Header> and <Footer> components so, both are loading each CSS in each page as you can see here:
return (
<>
<Header siteTitle={data.site.siteMetadata.title} />
<div>
<main>{children}</main>
<Footer>
© {new Date().getFullYear()}, Built with
{` `}
Gatsby
</Footer>
</div>
</>
)
}
The easiest solution is to wrap the each component in a class to make the CSS only available inside that class, something like this:
import React from "react"
import { Link } from "gatsby"
import "../styles/header.module.css";
const ListLink = props => (
<li className="list__item">
<Link className="link" to={props.to}>{props.children}</Link>
</li>
)
Note: you can even wrap the <Link> inside a <div> for example.
I would suggest removing inline styles if you are using CSS modules to avoid mixing styles and improve readability.
The same applies for the <Footer> component.
According to the documentation it's import something from './something.module.css' and then <Component className={something.error}
Related
I am trying to apply CSS on a component called Cards. I want to apply the CSS on the #image_div div. My code is as follows:
team.module.css:
.grid_container{
display: grid;
grid-template-columns: repeat(3,auto);
}
.image #image_div{
border-radius:100%;
margin: 30vh;
}
index.js:
import Image from "next/image";
import Div from "../../components/Div";
import Cards from "../../components/Cards";
import styles from "../../styles/team.module.css";
import xyz from "../../public/xyz.jpeg"
export default function Team(){
return (
<Div>
<div className={`${styles.grid_container}`}>
<Cards url={xyz} title={"XYZ"} className={styles.image}></Cards>
</div>
</Div>
);
}
Cards.js:
import Image from "next/image";
import { Card } from "react-bootstrap";
import styles from "../styles/components/Card.module.css";
export default function Cards({title,url,width,height,alt,description,className}) {
return (
<Card className={`card col-xs-12 col-sm-4 ${styles.Card} ${className?className:null}`}>
<div className="d-flex justify-content-center" id="image_div">
<Image
variant="top"
src={url}
width={width}
height={height}
alt={alt}
className="img-card"
/>
</div>
<Card.Body className="card-content">
<Card.Title className="card-title text-center">{title}</Card.Title>
<Card.Text className="text-center">{description}</Card.Text>
</Card.Body>
</Card>
);
}
But when I inspected the #image_div the CSS is not applied to it. What am I doing wrong here? I want to apply the CSS defined in the team.module.css without defining the same CSS in the Card.module.css file (which contains CSS for Cards.js).
Just like the class selectors, the #image_div selector also gets namespaced by CSS Modules.
You have to use :global() on the selector to switch to global scope and properly target #image_div.
.image :global(#image_div) {
border-radius:100%;
margin: 30vh;
}
I am currently developing a website utilizing Next.js and Ant Design and I have found a Chrome only issue that I am unable to fix. Whenever the user leaves the page or leaves the chrome window and returns, there is a brief flash of black on every page of the website. Furthermore, it seems that CSS styles are not being loaded fast enough, because when the website is reloaded, it is possible to see an enlarged version of my SVG logo before it is properly resized, which is very distracting. These issues only persist on Chrome to my knowledge as I have tested it with Safari and Firefox and have been unable to reproduce this issue. I have looked around for a solution, but they all use styled-components as well as a _document.js file in their project to solve the issue, but I have neither currently. Any help would be great on this, the relevant code will be below, if anything else is needed I can provide more. (Not every bit is used, I did use a tutorial to set learn how next.js worked so there are remnants of that).
EDIT: I want to add that the css flash/black flash happens on refresh of the page or when the window is deselected or minimized. I am still unsure if this is a problem with Next.js or if it is a problem with my implementation of the global css file with Ant Design.
EDIT 2: This problem is still an issue and I have been still unable to fix it...It's not too serious but it is annoying for chrome users I have found when doing alpha testing.
_app.js
import '../styles/global.css'
import React from 'react'
import App from 'next/app'
import Head from 'next/head'
import { Provider } from '../contexts/countryContext'
//There is a chrome only issue where the CSS Elements flash for like half a second when the page is loaded, not sure how to fix.
export default class MyApp extends App {
render() {
const { Component, pageProps } = this.props;
return (
<div>
<Head>
</Head>
<Provider>
<Component {...pageProps} />
</Provider>
</div>
)
}
}
global.css
#import '~antd/dist/antd.css';
:root {
--primary-color: #8497f5;
--light-secondary: #A0AAEC;
--light-tertiary: #5467DE;
--dark-secondary: #474C69;
--dark-tertiary: #4554B5;
}
html,
body {
padding: 0;
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu,
Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
line-height: 1.6;
font-size: 18px;
}
* {
box-sizing: border-box;
}
a {
color: #0070f3;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
img {
max-width: 100%;
display: block;
}
index.js
import {Layout, Row, Spin, Divider} from 'antd'
import {Component, useState, useContext} from 'react'
import Link from 'next/link'
import {Context} from '../contexts/countryContext'
import layout from '../styles/layout.module.css'
import utils from '../styles/utils.module.css'
import SiteHeader from '../components/siteHeader'
import CalculationCard from '../components/CalculationCard'
import CookieHeader from '../components/CookieHeader'
const { Header, Content, Sider, Footer } = Layout;
const Main = () => {
const context = useContext(Context)
return (
<Layout style={{backgroundColor:"white"}}>
<SiteHeader/>
<Content className={layout.container}>
<header className={layout.header}>
<Link href="countrySelector">
<img src={context.flag + ".png"} className={layout.headerImage}/>
</Link>
<h1 className={utils.heading2Xl}>{context.name}</h1>
</header>
<CookieHeader/>
</Content>
<Content>
<Row gutter={16}>
<Divider orientation="left" style={{fontSize: "1.15rem", lineHeight: 0}}>Economic</Divider>
<CalculationCard name={"Maintenance"} desc={"Land and Naval Mintenance"} img={"local_reg_cost_icon"} link="maintenance"/>
<CalculationCard name={"Development Cost"} desc={"Mana Costs for Development"} img={"dev_cost"}/>
</Row>
</Content>
{/* <Footer style={{height: "100%"}}>
Indev
</Footer> */}
</Layout>
);
}
export default Main;
I'm new to styling in React. I tried CSS modules and styled components but I'm not able to change layout and styles.
The goal is to have a group of buttons to display as flex on the main page and as an inline with different style attributes in another page by re-using the HomeButtons.js component.
HomeButtons.js is the home page and it has a map() function looping through a button called ButtonCategory.js.
HomeButtons.js renders the map() inside a styled using CSS modules file. ButtonCategory is styled with a CSS modules file as well.
HomeButtons.js is then returned inside a in another class Component called CardsCategory.js. It is in this component that I'm trying to change the display and styl... With a styled Component on the I can show a border but the display attribute doesn't works.With CardsCategory.module.css I can't change the display either...
Not sure what to do... How to change the layout of the re-used component and the style of its nested button component ?
Any feedback is welcome!
HomeButtons.js
import React, { Component } from 'react'
import classes from './HomeButtons.module.css';
import ButtonCategory from '../../components/ButtonCategory/ButtonCategory'
class HomeButtons extends Component {
handleClick = (buttonValue) => {
buttonValue = buttonValue.slice(0, 3).toLowerCase();
this.props.history.push("/" + buttonValue);
};
render() {
const allCategoriesButtons = ["Physics", "Chemistry", "Medicine", "Literature", "Peace", "Economics"];
const allCatMap = allCategoriesButtons.map(button =>
< ButtonCategory
key={button.toString()}
value={button}
name={button}
onClick={e => this.handleClick(e.target.value)}
/>
)
return (
<div>
<div className={classes.container__section}>
{allCatMap}
</div >
</div>
)
}
}
export default HomeButtons;
HomeButtons.module.css
.container__section {
display: flex;
flex-flow: row wrap;
margin: auto;
align-items: center;
justify-content: space-around;
}
ButtonCategory
import React from 'react'
import classes from './ButtonCategory.module.css';
function buttonCategory(props) {
return (
<button
className={classes.b}
name={props.name}
onClick={props.onClick}
value={props.value}
>
{props.name}
</button>
)
}
export default buttonCategory;
ButtonCategory.module.css
opacity: 0.5;
color: red;
font-size: 2em;
margin: 10px 20px 10px 20px;
flex: 1 400px;
height: 3em;
}
CardsCategory
import React, { Component } from 'react';
import axios from 'axios';
import classes from './CardsCategory.module.css';
import HomeButtons from "../HomeButtons/HomeButtons"
import styled from 'styled-components';
const StyledDiv = styled.div`
border: 10px solid orange;
//display: inline; //NOT working
`
class Cards extends Component {
render() {
return (
<div>
<StyledDiv>
<HomeButtons className={classes.test}/>
</StyledDiv>
</div>
)
}
}
export default Cards;
CardsCategory.module.css
.test {
display: inline;
}
You can send styles thru the props and in the component set them as your styles ex.
<MyComponent textAlign='center' ...>
in MyComponent component
<div style={{textAlign: this.props.textAlign}}>
...
</div>
or send whole styles as objects ex.
render(){
const stl = {textAlign: 'center',width:'500px'};
return(
<MyComponent wholeStyle={stl}/>
)
}
and in MyComponent
<div style={this.props.wholeStyle}>
...
</div>
They are 3 ways you can style through props
You can pass an entire style object
Eg:
<MappedComponent style={'display':'flex','alignItems':'center'} />
In the mapped component
Function MappedComponent ({style}){
return (
What's popaining !
);
}
You can style by passing in the specific style you want
Eg:
<MappedComponent textAlign={'center'} />
In the mapped component
Function MappedComponent ({textAlign}){
return (
What's popaining !
);
}
The third way you can style is by defining styles in a CSS file and just passing in the class name
Eg:
<MappedComponent className={''flex-button-style'} />
In the mapped component
Function MappedComponent ({className}){
return (
What's popaining !
);
}
Pick what works best for you and stay consistent with it :) .
First: I know there are already a couple of questions about this error, but they had a different source (I think). Here's my code:
<BrowserRouter>
<React.Fragment>
<Navbar className='navbar_all'>
<Navbar.Header>
<Navbar.Brand>
<Link className='navbar_brand' id='home' to='/'>
<img alt='ZdajTo' src="assets/images/new_logo.png" style={{height: '30px'}}/>
</Link>
</Navbar.Brand>
</Navbar.Header>
<Nav className='float_right'>
<Link to='/homepage' style={{textDecoration: 'none'}}>
{/*^^^^^^^^^^^^ This line throws an error*/}
<button style={{
backgroundColor: '#F16049',
border: '4px solid #F16049',
borderRadius: '4px',
padding: '10px',
marginBottom: '5px',
color: '#fff'
}}>
DLA ROZWIĄZUJĄCYCH
</button>
</Link>
</Nav>
</Navbar>
</React.Fragment>
</BrowserRouter>
The error I'm getting is this:
Warning: React does not recognize the activeKey prop on a DOM element. If you intentionally want it to appear in the DOM as a custom attribute, spell it as lowercase activekey instead. If you accidentally passed it from a parent component, remove it from the DOM element.
The problem is, I believe in the nesting, but I have no idea what can be wrong here.
Any ideas?
The issue is that you should not nest DOM elements directly under Nav component, instead use NavItem. Problem with such approach is that NavItem is anchor and nesting Link under it will throw another error, since Link is also an anchor.
Solution is to use LinkContainer from react-router-bootstrap like this.
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import { Nav, NavItem, Navbar } from 'react-bootstrap';
import { LinkContainer } from 'react-router-bootstrap';
const app = (
<BrowserRouter>
<Navbar>
<Nav>
<LinkContainer to="/somewhere">
<NavItem>somewhere</NavItem>
</LinkContainer>
</Nav>
</Navbar>
</BrowserRouter>
);
ReactDOM.render(app, document.getElementById('root'));
In react-router v3 we had activeStyle and activeClassName to style active Link
we could do something like this
<div id="tags-container">
{tags.map(t =>
<Link
className="tags"
activeStyle={{ color: 'red' }}
to={t.path}
>
{t.title}
</Link>
)}
</div>
I wanna know how can I do same thing in v4?
Use NavLink instead Link. Its not documented, but its work as you expect.
https://github.com/ReactTraining/react-router/issues/4318
UPDATE 17.05.2017:
https://reacttraining.com/react-router/web/api/NavLink
You can do it with NavLink in react-router v4
<div id="tags-container">
{tags.map(t =>
<NavLink
className="tags"
activeStyle={{ color: 'red' }}
to={t.path}
>
{t.title}
</NavLink>
)}
</div>
If you are encountering an issue where your Nav menu works except it's not updating properly when you click links and the route changes, but it works fine if you press F5, you can do this:
This is probably occurring because you are using Redux which has a shouldComponentUpdate Lifecycle method on its connect function. You probably have your Nav component wrapped in connect. This is all good. shouldComponentUpdate is what is ruining your life.
To fix, just bring the router into your mapStateToProps function:
// This lets shouldComponentUpdate know that the route changed,
// which allows the Nav to re-render properly when the route changes, woot!
const mapStateToProps = (state) => {
return {
router: state.router,
}
}
// or, if you prefer pro style destructure shorthand:
const mapStateToProps = ({ router }) => ({ router })
If you aren't quite sure where state.router comes from, it comes from the file you combine your reducers in, and you will see something like this:
import { combineReducers } from 'redux'
import { routerReducer } from 'react-router-redux'
import authReducer from './components/auth/auth_reducer'
export default combineReducers({
router: routerReducer,
auth: authReducer,
})
Here is some HTML and CSS for a pretty baller Nav Link:
HTML
<ul id="Nav_menu">
<li>
<NavLink
to="/home"
className="Nav_link"
activeClassName="activeRoute"
activeStyle={{ color: 'teal' }}
>
HOME
</NavLink>
</li>
<li>
<NavLink
to="/products"
className="Nav_link"
activeClassName="activeRoute"
activeStyle={{ color: 'teal' }}
>
PRODUCTS
</NavLink>
</li>
</ul>
NOTE: If you are linking to "/", put exact prop on NavLink.
CSS
#Nav_menu {
display: flex;
flex-direction: row;
width: 100%;
height: 100%;
list-style-type: none;
margin: 0;
padding: 0;
}
.Nav_link:link {
color: #fff;
font-size: 1.6rem;
line-height: 1.6rem;
text-decoration: none;
}
.Nav_link:visited {
color: #fff;
}
.Nav_link:hover {
color: yellow;
}
.Nav_link:active {
color: teal;
}
.activeRoute {
background-color: yellow;
border-bottom: 0.4rem solid teal;
cursor: not-allowed;
}
Notice activeStyle in the HTML markup. This was the only way I could change the color of the text on the active route/link. It didn't work when I put color: teal; in the activeRoute CSS Class. Open this in another tab: https://github.com/ReactTraining/react-router/blob/master/packages/react-router-dom/docs/api/NavLink.md
If you don't know why I used rem instead of px. This is a great opportunity for you to research web accessibility and base font-size: 10px;.
Stay fit and have fun.
React Router v6:
Source: Active NavLink Classes with React Router
I know this was a question for v4 but since v6 is released we can accomplish this now by using className property which now accepts a function and passes an isActive boolean property, like this:
<NavLink
to="users"
className={({ isActive }) => (isActive ? 'active' : 'inactive')}
>
Users
</NavLink>
You can also add multiple classes too, since v6 is out:
<NavLink
to="users"
className={({ isActive }) =>
isActive ? 'bg-green-500 font-bold' : 'bg-red-500 font-thin'
}
>
Users
</NavLink>
Demo: Active NavLink Classes with React Router
All still works the same. However, react-router-dom v4 replace Link with NavLink
import { NavLink as Link } from 'react-router-dom'; is also fine. Note: Navlinks by default is active so you can style a:active or activeStyle={{color: 'red'}}
Expanding on #agm1984's answer:
The solution of NavLinks is not updating styles correctly, which was using routerReducer from react-router-redux, has not worked for me. Instead, I found out that the issue was that connect wrapper uses shouldComponentUpdate and prevented rerendering of the component containing NavLinks.
Correct solution in my situation was to pass options object to connect as 4th parameter as shown below:
export default connect(mapStateToProps, null, null, { pure: false })(NavItems);
This example from the react-router v4 custom link documentation will help you to accomplish it:
const OldSchoolMenuLink = ({ label, to, activeOnlyWhenExact }) => (
<Route path={to} exact={activeOnlyWhenExact} children={({ match }) => (
<div className={match ? 'active' : ''}>
{match ? '> ' : ''}<Link to={to}>{label}</Link>
</div>
)}/>
);
So in your case you could create following component:
const CustomLink = ({ activeStyle, children, className, to, activeOnlyWhenExact }) => (
<Route path={to} exact={activeOnlyWhenExact} children={({ match }) => (
<Link to={to} className={className} style={match && activeStyle}>{children}</Link>
)}/>
);
And then use it like:
<div id="tags-container">
{tags.map(t =>
<CustomLink
className="tags"
activeStyle={{ color: 'red' }}
to={t.path}
>
{t.title}
</CustomLink>
)}
</div>