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;
Related
I want to implement a color option in my button components to use it in all my global components so I can change the text and color Dynamically
is it correct?
import React from 'react';
import './Button.css';
const Button = ({text, BtnVersion1}) => {
return (
{text}
)
}
export default Button;
<Button style={{color: "red"}} text="SHOP NOW" />
Your component code seems to be fully correct. But when using your component you have to pass props this way:
<Button text={"SHOP NOW"} BtnVersion1={"red"} />
This is where styled components can be very useful. Where you're declaring 'style' on the component, that is an inline style and would only exist on that instance of the button. You can pass a prop, say 'btnColor' to the button which is used by the styled component to change the color. See below.
import React from 'react';
import styled from 'styled-component';
import './Button.css';
const StyledButton = styled.a`
background-color: ${props => props.btnColor ? props.btnColor : 'red'};
`
const Button = ({
text,
btnColor
}) => {
return (
<StyledButton href="#" btnColor={btnColor} className="buy">{text}</StyledButton>
)
}
export default Button;
<Button btnColor='red' text="SHOP NOW" />
You can see above in the StyledButton that if we provide the btnColor prop than use that color, else default to 'red.'
For more information on styled components - https://styled-components.com/
You can have a more "dynamic" way of doing it (so your instance of <Button> doesn't change):
import React from 'react';
import './Button.css';
const Button = ({ text, style }) => {
return (
{text}
)
}
export default Button;
<Button style={{ color: "red" }} text="SHOP NOW" />
If you want to just control the color (or other properties) you can do something like:
import React from 'react';
import './Button.css';
const Button = ({ text, color }) => {
return (
{text}
)
}
export default Button;
<Button color="red" text="SHOP NOW" />
You might want to use your component this way:
The advantage here is that you can pass all your custom styles for every single one of your buttons.
const Button = ({text, style}) => {
return (
{text}
);
};
ReactDOM.render(<Button style={{color: "red"}} text="SHOP NOW" />, document.querySelector("#root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"></script>
<div id="root">
<!-- Your root container -->
</div>
Donot use anchor tag as a button in react , If you want to know the reason read this doc
https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/anchor-is-valid.md
I think best way to style a button is using styled component , I have given an example code in this sandbox , you can pass props for things only you want to change like for background, if no value is given it will take default color
try it
code :
import "./styles.css";
import styled from "styled-components";
const Button = styled.button`
font-family: "Work Sans", sans-serif;
font-size: 14px;
font-weight: 600;
color: #ffffff;
line-height: 16px;
background: ${(props) => (props.background ? props.background : "#00D2AD")};
transition: all 0.4s ease-out;
transition: all 0.4s ease-out;
padding: 14px 24px;
outline: none;
text-align: center;
display: inline-block;
border: none;
cursor: pointer;
border-radius: 4px;
`;
export default function App() {
return (
<div className="App">
<Button>Default Button </Button>
<br />
<br />
<Button background={"gray"}>Custom Button</Button>
</div>
);
}
Im new to React JS, working on my first soon-to-be live site. I have styled input in a form in a seperate component, then imported the styles to that component. After implementing routing, it seems that this
style is applied to forms across the site, whether or not i import them. Note, i was initially putting all
styles in index.css until I expanded the scope of the site, and this was no longer practical. It now seems
that the index.css styles remain, even after i removed the styles im trying to get rid of from index.css. Either that, or there is something wrong with my routing, importing, exporting, that im not seeing, which is causing this bug:
This style is being applied from a different component with its own imported stylesheet.
I want the sign up form to appear like a normal form input, but its hidden because of the styles
applied to BrowsePhotos.js. I am completely unsure why this happens.
here is my project directory tree
and here is some source code related to possible problem sources
src/components/auth/SignUp.js
import React, { useState } from 'react'
import './auth.css';
const SignUp = () => {
return(
<form onSubmit={handleSubmit} className="App-sign-up">
<label className="auth-field"> Email:
<input onChange={handleEmailChange} type="text"/>
{ !emailError && <div className="error">{emailError}</div>}
</label>
<label className="auth-field"> Password:
<input onChange={handlePasswordChange} type="password"/>
{ !passwordError && <div className="error">{passwordError}</div>}
{/* should also define errors for the other offenders- length, expected characters */}
</label>
{ password &&
<label className="auth-field"> Password:
<input onChange={handleConfirmPasswordChange} type="password"/>
{ !confirmPasswordError && <div className="error">{confirmPasswordError}</div>}
{ password !== confirmPassword && <div className="error">Password and Confirm Password must match</div> }
</label>
}
<button type="submit">Create Account</button>
<div>Already have an account? Sign In!</div>
</form>
)
}
export default SignUp;
src/components/photos/UploadForm.js
import React, { useState } from 'react';
import ProgressBar from './ProgressBar';
import './UploadForm.css'
// TODO: add a new controlled component for providing text to use
// as photo description/ alt text.
const UploadForm = () => {
//equivalent to setting state to '' in class based component
const [file, setFile] = useState(null);
// const [description, setDescription] = useState(null);
const [error, setError] = useState(null);
const handleChange = event => {
// reference to the selected file,
// and a list of allowable image types
const selected = event.target.files[0]
const types = ['image/png','image/jpeg']
if (selected && types.includes(selected.type)) {
setFile(selected);
setError('');
// if (event.target.type === 'textarea') {
// console.log("we got a description")
// }
} else {
setFile(null);
setError('Enter a valid photo type : jpg or png')
}
}
return (
<form>
<label>
<span>+</span>
<input onChange={handleChange} type="file"/>
{/* <div className="description">
<label className="inner-label">Description of the uploaded file</label>
<textarea cols="30" rows="10"
onChange={handleChange}
></textarea>
</div> */}
</label>
<div className="output">
{ error && <div className="error" >{ error }</div>}
{ file && <ProgressBar file={file} setFile={setFile}/>}
</div>
</form>
);
}
export default UploadForm;
src/components/photos/UploadForm.css
form{
margin: 30px auto 10px;
text-align: center;
}
label input{
height: 0;
width: 0;
opacity: 0;
}
label{
display: block;
width: 30px;
height: 30px;
border: 1px solid var(--primary);
border-radius: 50%;
margin: 10px auto;
line-height: 30px;
color: var(--primary);
font-weight: bold;
font-size: 24px;
}
label:hover{
background: var(--primary);
color: white;
}
.output{
height: 60px;
font-size: 0.8rem;
}
.error{
color: var(--error);
}
src/index.css
#import url('https://fonts.googleapis.com/css2?family=Noto+Serif:wght#400;700&display=swap');
:root{
--primary: #efb6b2;
--secondary: #4e4e4e;
--error: #ff4a4a;
}
/* base styles & title */
body{
font-family: "Noto Serif";
color: var(--secondary);
}
.App{
max-width: 960px;
margin: 0 auto;
}
.title h1{
color: var(--primary);
font-size: 1.2rem;
letter-spacing: 2px;
font-weight: normal;
}
src/components/general/title // note: home of routing, ive tried commenting out BrowsePhotos from routing. this is then imported to app.js
import React from 'react';
import { BrowserRouter as Router, Route, Link } from 'react-router-dom';
import './general.css'
import About from '../general/About';
import SignIn from '../auth/SignIn';
import SignUp from '../auth/SignUp';
import BrowsePhotos from '../photo/BrowsePhotos';
import BrowseProfiles from '../auth/BrowseProfiles';
const Title = () => {
return (
<div className="title">
<Router>
<nav style={{padding: "5px"}}>
<h1 className="title">Oral-History</h1>
<h1>
<Link to="/about">About</Link>
</h1>
<h1>
<Link to="/sign-in">Sign In</Link>
{/* becomes sign-out when user is signed in */}
</h1>
<h1>
<Link to="/sign-up">Sign Up</Link>
{/* sign-up becomes 'my profile' after sign in */}
</h1>
<h1>
<Link to="/profiles">Profiles</Link>
</h1>
<h1>
<Link to="/photos">All Photos</Link>
</h1>
</nav>
<Route exact path="/about" component={About}/>
<Route exact path="/sign-in" component={SignIn}/>
<Route exact path="/sign-up" component={SignUp}/>
<Route exact path="/profiles" component={BrowseProfiles}/>
<Route exact path="/photos" component={BrowsePhotos}/>
</Router>
</div>
)
}
export default Title;
I've also tried redefining the rule set for label and label input within SignUp.css, to set all the properties to default, or inherits: false, with no luck there.
It sounds like the CSS is not being imported scoped but globally. You could use a CSS-in-JS library like CSS-Modules or react-scoped-css to fix this.
Another way would be to give the html-elements classes and not style them directly. That is usually more scalable.
I'm working on React applications. I need a really very simple Cookie banner. The one that informs that the website uses cookies. There are various (theoretically simple) solutions in npm packages, but they all cause some problems in my projects. I have the impression that they are overdesigned, although they are supposed to be simple.
My projects mainly based on React with React Router.
OK. We have React and React Router (react-router-dom). And we need:
react-cookie npm install react-cookie
react-modal npm install react-modal
bootstrap npm install bootstrap
ModalCookies.js component:
import React from 'react';
import {
Link
} from 'react-router-dom';
import { useCookies } from "react-cookie";
import Modal from 'react-modal';
import '../modal.css';
function ModalCookies() {
const [cookies, setCookie] = useCookies(["allowcookies"]);
function handleCookie() {
setCookie("allowcookies", true, { path: "/", expires: new Date(Date.now() + (100 * 24 * 60 * 60 * 1000)) });
}
function closeModal() {
handleCookie();
}
return (
<Modal isOpen={cookies.allowcookies ? false : true} className="Modal" overlayClassName="Overlay">
<h6>PRIVACY & COOKIES POLICY</h6>
<p className="text-justify">
I use cookies to personalize content, ads and to analyze the traffic.
I also share information about your use of my website with my social media,
advertising and analytics partners who may combine it with other information that you have provided to them or that they have collected from your use of their services.
If you continue browsing, it means that you accept the use of cookies on this website.
</p>
<div className="text-right">
<button
className="btn btn-secondary mr-2 mb-2"
onClick={closeModal}>
OK
</button>
<Link to="/privacy"
className="btn btn-outline-secondary mb-2"
onClick={closeModal}>
Learn More
</Link>
</div>
</Modal>
);
}
export default ModalCookies;
modal.css file:
.Modal {
position: absolute;
top: auto;
left: 15%;
right: 15%;
bottom: 15%;
border: 1px solid rgb(100, 100, 100);
background: rgb(255, 255, 255);
outline: none;
padding: 40px;
z-index: 1;
}
.Overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(255, 255, 255, 0.60);
}
The file that manages the main view of the application with React Router (for example: Home.js or App.js)(excerpt):
//...
import ModalCookies from './ModalCookies';
//...
</Route>
</Switch>
<ModalCookies />
<Footer />
</Router>
//...
index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import { CookiesProvider } from 'react-cookie';
import Modal from 'react-modal';
import App from './App';
import 'bootstrap/dist/css/bootstrap.css';
Modal.setAppElement('#root');
ReactDOM.render(
<React.StrictMode>
<CookiesProvider>
<App />
</CookiesProvider>
</React.StrictMode>,
document.getElementById('root')
);
It works very well in my projects. Any comments or questions are welcome.
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}
I have an App Component that does all my routing for my project, where I import all the necessary components.
import React from "react";
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import './App.scss';
import Login from "../../login/Login";
import Overview from "../../overview/Overview";
import SubNav from "../../subnav/SubNav";
import ForgotPassword from "../../forgot-password/ForgotPassword";
const App = () => {
return (
<div className="App">
<Router>
<div className="App-container">
<Switch>
<Route path="/login" component={Login} exact />
<Route path="/forgotpassword" component={ForgotPassword} exact />
<Route path={"/"} component={SubNav} />
</Switch>
<Route exact path={"/"} component={Overview} />
<Route path={"/overview"} component={() => <Overview />} />
</div>
</Router>
</div>
);
}
export default App;
For example, in my Login component, I have the following imports...
import React from 'react';
import './Login.scss';
import LoginBenefits from './LoginBenefits';
import LoginFormContainer from './LoginFormContainer';
The issue I am having here with the import of the Login.scss
In this file I do imports of specific other scss files that are related to the Login Component. Say, for example, I had one that styled a class called .Tabs
#import "../../scss/_variables";
$Tabs-padding: 15px;
#import "../tabs/Tabs.scss";
.Login {....
Now for example, if in the ForgotPassword Component, if I were to add a div with a className of Tabs it would then style it correctly. This isn't what I want, it means that whatever is imported in the Login component gets loaded throughout the whole project, which means I cannot override any SASS variables without having to import the same SASS file again and makes the webpack bundled css file larger than it needs to be.
I guess my question is, how do I contain the Login.scss to only import when the Login component actually renders?
Or am I going about the whole imports in the wrong way?
What you have to understand is, when you import your scss files. They get converted to css and are rendered as 'internal styles' in the app. Basically they become global css rendered in the header. So unless you use scss properly and structure your css with a hierarchy you cannot achieve containment!
But what you have stumbled upon is an intriguing idea, which has
pushed the community to come up with a solution called css in js!
Look at this video!
The basic idea is to bring css into the React Component containing the styles inside the component. It is achieved using using template strings. This is groundbreaking because you now how the full power of javascript behind you to manipulate css!
This is an exhaustive list of frameworks that can help you with this. styled-components is the most widely adopted framework. But you can take a pick!
This is an example of how your code will look
import React from 'react';
import { render } from 'react-dom';
import styled from 'styled-components';
const Container = styled.div`
text-align: center;
`;
const Button = styled.button`
background-color: #ff0000;
width: 320px;
padding: 20px;
border-radius: 5px;
border: none;
outline: none;
&:hover {
color: #fff;
}
&:active {
position: relative;
top: 2px;
}
#media (max-width: 480px) {
width: 160px;
}
`;
const App = () => (
<Container>
<Button>Click me!</Button>
</Container>
);
render(<App />, document.getElementById('content'));
And styled components takes care of containing your css to the relevant component!
You need to bundle the all your scss file into single file. You can do this in webpack config file with use of ExtractTextPlugin
module: {
rules: [{
test: /\.scss$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: ['css-loader', 'sass-loader']
}),
},
{
test: /js$/,
exclude: /(node_modules)/,
loader: "babel-loader",
}
]
},
plugins: [
new ExtractTextPlugin({
filename: "dist/assets/css/style.bundle.css"
})
]