I've just started playing with next js. so I want to use css as module and setup classname for nav, but in rendered DOM this classname doesn't exist. I can see generated styles by webpack in "head" tag, but I dont see classname on my nav tag.
import React from "react";
import styles from './NavigationContainer.module.scss';
type Props = {};
const NavigationContainer: React.FC<Props> = ({children}) => {
return <nav className={styles.mainNavigationContainer}>{children}</nav>
};
export default NavigationContainer;
In JS, we cannot use - as a variable name it is considered as a minus to do the math.
It is a good idea to rename the CSS selector to .mainNavigationContainer so that the Next Js can get the correct CSS styles.
The JS part will remain the same.
https://nextjs.org/docs/basic-features/built-in-css-support#adding-component-level-css
Related
I'm working on my own project by plan "from Zero to Hero" my friend told me about styled components and I've decided to replace my clear .css and move to styled components.
I know how it works in basic. <MyComponent> and than const MyComponent = styled.div css, css, css
Im strugling about these 2 situations
<div className={color ? 'header header-bg' : 'header'}> How to code it for styled components? Like <MyComponent={color ? 'header header-bg' : 'header'}> But than i dont know what else..
In clear styles I have many situations like
.class1, .class2, .class3 {
styles
}
How can I write it in styled components, please? For now, I have 3 times the same code for every class1-3, and that's not good. Also i tried something like const Class1, Class2 = styled.div but it doesn't work
you can pass the props in styled components instead of ternary operators, here the link you can see the example Add background color conditionally in styled components
and const Class1, Class2 = styled.div this will not work, you should have do like this
const Class1 = styled.div``
const Class2 = styled.div``
const Class3 = styled.div``
And you should learn about the styled components from this link
I have a React project which has two pages and each page has its own css file.
Page1.jsx -> Page1.css
Page2.jsx -> Page2.css
Each css file is only included in its corresponding jsx file. Both css files share similar class names (example: column, image-place, etc.). The problem is that Page1 is affected by Page2's CSS file.
I am not expert in front-end technologies. Any help will be appreciated.
Are you using create-react-app?
If so, use css-modules instead https://create-react-app.dev/docs/adding-a-css-modules-stylesheet/
CSS Modules allows the scoping of CSS by automatically creating a
unique classname
//Page1.jsx
import React from 'react';
import styles from './page1.module.css'; // Import css modules stylesheet as styles
export const Page1 = () => {
return (
<div className={styles.column}>page1</div>
)
}
/* page1.module.scss */
.column {
color: red
}
//Page2.jsx
import React from 'react';
import styles from './page2.module.css'; // Import css modules stylesheet as styles
export const Page2 = () => {
return (
<div className={styles.column}>page2</div>
)
}
/* page2.module.scss */
.column {
color: green
}
If you want to combine them with normal or external css class (bootstrap, tailwind, etc), try this:
<div className={`${styles.column} overflow-auto`}>page1</div>
A possible way to avoid conflicts is to use Sass. You can set it up by typing in your react app folder terminal:
npm i sass --save-dev
Then transform all .css files to .scss. Add a unique class on the top level wrapper of each page, for example :
retrun (<div className = "pageOne">
<img src = "/myImage" className = "image-place"/>
</div>)
And finally your styles will look like this :
.pageOne {
.image-place {
width:200px
}
.column {
width:200px
}
}
This way, you would have one unique class at the top level wrapper, and as many as class that have the same name in them.
I am trying to create a Design System using ReactJS and TailwindCSS.
I created a default Button component with basic styling as follow:
import React from "react";
import classNames from "classnames";
const Button = React.forwardRef(
({ children, className = "", onClick }, ref) => {
const buttonClasses = classNames(
className,
"w-24 py-3 bg-red-500 text-white font-bold rounded-full"
);
const commonProps = {
className: buttonClasses,
onClick,
ref
};
return React.createElement(
"button",
{ ...commonProps, type: "button" },
children
);
}
);
export default Button;
I then use the Button in my page like:
import Button from "../src/components/Button";
export default function IndexPage() {
return (
<div>
<Button onClick={() => console.log("TODO")}>Vanilla Button</Button>
<div className="h-2" />
<Button
className="w-6 py-2 bg-blue-500 rounded-sm"
onClick={() => console.log("TODO")}
>
Custom Button
</Button>
</div>
);
}
This is what is displayed:
Some attributes are overridden like the background-color but some aren't (the rest).
The reason is the classes provided by TailwindCSS are written in an order where bg-blue-500 is placed after bg-red-500, therefore overriding it. On the other hand, the other classes provided in the custom button are written before the classes on the base button, therefore not overriding the styles.
This behavior is happening with TailwindCSS but might occurs with any other styling approach as far as the class order can produce this scenario.
Do you have any workaround / solution to enable this kind of customisation?
Here is a full CodeSanbox if needed.
One approach is to extract classes from your component using Tailwind's #apply in your components layer.
/* main.css */
#layer components {
.base-button {
#apply w-24 py-3 bg-red-500 text-white font-bold rounded-full;
}
}
// Button.js
const Button = React.forwardRef(({ children, className = "", onClick }, ref) => {
const buttonClasses = classNames("base-button", className);
// ...
);
This will extract the styles into the new base-button class, meaning they can easily be overwritten by the utility classes you pass to the Button component.
Another approach to create reusable React components using Tailwind is as follows..
Read this gist
https://gist.github.com/RobinMalfait/490a0560a7cfde985d435ad93f8094c5
for an excellent example.
Avoid using className as a prop. Otherwise, it'd be difficult for you to know what state your component is in. If you want to add an extra class, you can easily extend.
You need a helper for combining classname strings conditionally. Robert, the writer of this gist, shared the helper function also with us:
export function classNames(...classes: (false | null | undefined | string)[]) {
return classes.filter(Boolean).join(" ");
}
To have Tailwind CSS override material theming (or something else for that matter) one could apply !important to all tailwind utilities with configuration to module.exports.
The important option lets you control whether or not Tailwind’s utilities should be marked with !important. This can be really useful when using Tailwind with existing CSS that has high specificity selectors.
To generate utilities as !important, set the important key in your configuration options to true:
tailwind.config.js
module.exports = {
important: true
}
https://tailwindcss.com/docs/configuration#important
To solve, I recommend doing what Bootstrap does. Use a default class for your default button like:
.button {
width: 2rem;
background-color: red;
border-radius: 0.25rem;
}
Then when customizing a button you should apply classes that either come after the button class in your CSS file, or come in a different CSS file that is called after your default CSS file, or use the !important declaration.
Old answer
Use your browser developer tools to observe how your browser is loading CSS styles on an element. For example, in Chrome, right-click on the custom button and select "Inspect". A DevTools window will open and the element will be highlighted in the DOM.
On the right, you should have a Styles pane. There, you'll see a list of all the CSS styles being applied to the element. Styles with strikethroughs are being overridden by styles called by other CSS classes or inline styles.
In your case, the custom button has both the "CommonProps" classes and the classes you're adding in IndexPage. For example, both class w-6 and class w-24.
Class w-24 is overriding class w-6 because of CSS precedence. Read more about CSS precedence here. Check out rule #3 in the accepted answer. I think that's what's happening to you.
To solve, you may want to remove some classes from commonProps. Or use the !important declaration on some classes. This is the part of your design system that you need to think through. Look at how other systems like Bootstrap have done it.
I seem to be having some issues in regards to styling the components without using a theme. I just want to change a couple of colors without needing to create a new theme per element.
In this case, I just want to change the color of the bar to a brownish color and right now I have an input class as follows:
import style from './style.scss'
const TextInput = (props) => {
<Input className={style.textInput} {...props} />
}
And in my style.scss file:
.textInput {
.bar {
background-color: #663300;
}
}
Any help would be appreciated.
ClassName doesn't work like that.
You can't pass a Css style to a className, that is wrong.
Either pass the class names you want to apply as a string (in your case I guess it would be className="textInput bar") or you can create a className with classNames library (in any case the final result will be a string).
Just make sure you're styles are included in the page that the component is going to render and react will be smart enough to render the correct css class for each component.
As you can check in here ClassName is a string
I'm learning how to use css modules with react, below is a working example of a checkbox here's what it looks like (pure HTML + CSS fiddle) without react.
import React from 'react'
import CSSModules from 'react-css-modules'
import styles from './checkbox.css'
export function Checkbox (props) {
return <div styleName="checkbox--container">
<input styleName="checkbox" type="checkbox" {...props}/>
<span styleName="checkbox--styled"></span>
</div>
}
export default CSSModules(Checkbox, styles)
This is great and all, but let's say my client comes back and wants me to change the checkbox color. Fine, seems easy enough? That fiddle above shows that there is a couple of hex-codes (#479ccf) for border and within the SVG background image. Ideally I'd be able to pass along a react prop that allows you to do something like this <Checkbox color="#666333"/> and blam! However I can't find any documentation / way to get information from the component to the CSS file.
What does this mean?
I know what the react community is going to say, that particular set of CSS isn't ideal. It can be written in javascript within the component and from there you can set the inline styles of the pieces of the checkbox to the prop color. I'm pretty sure this is possible. Is this necessary? I'd have to refactor the ::after code, question about that.
I started on making the SVG functions.
function SVGDash (color) {
return `data:image/svg+xml;charset=US-ASCII,<svg%20xmlns%3D"http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg"%20viewBox%3D"0%200%2012%2012"%20enable-background%3D"new%200%200%2012%2012"><style%20type%3D"text%2Fcss">circle%2Cellipse%2Cline%2Cpath%2Cpolygon%2Cpolyline%2Crect%2Ctext%7Bfill%3A%23${color}%20%21important%3B%20%7D<%2Fstyle><path%20d%3D"M6%200"%2F><path%20d%3D"M.8%207C.3%207%200%206.7%200%206.2v-.4c0-.5.3-.8.8-.8h10.5c.4%200%20.7.3.7.8v.5c0%20.4-.3.7-.8.7H.8z"%2F><%2Fsvg>`
}
function SVGCheck (color) {
return `data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20enable-background%3D%22new%200%200%2024%2024%22%3E%3Cstyle%20type%3D%22text%2Fcss%22%3Ecircle%2Cellipse%2Cline%2Cpath%2Cpolygon%2Cpolyline%2Crect%2Ctext%7Bfill%3A%23${color}%20%21important%3B%20%7D%3C%2Fstyle%3E%3Cpath%20d%3D%22M23.6%205L22%203.4c-.5-.4-1.2-.4-1.7%200L8.5%2015l-4.8-4.7c-.5-.4-1.2-.4-1.7%200L.3%2011.9c-.5.4-.5%201.2%200%201.6l7.3%207.1c.5.4%201.2.4%201.7%200l14.3-14c.5-.4.5-1.1%200-1.6z%22%2F%3E%3C%2Fsvg%3E`
}
You could create a different class composing the class you want to change the color:
.checkbox--styled-red {
composes: checkbox--styled;
background-image: url("data:image .... FF0000 ....");
}
And set it in the component when you get the matching props.color:
import React from 'react'
import CSSModules from 'react-css-modules'
import styles from './checkbox.css'
function getStyleNameForColor(color) {
colorToStyleName = {
red: 'checkbox--styled-red'
};
return colorToStyleName[color] || 'checkbox--styled';
}
export function Checkbox (props) {
return <div styleName="checkbox--container">
<input styleName="checkbox" type="checkbox" {...props}/>
<span styleName={getStyleNameForColor(props.color)}></span>
</div>
}
export default CSSModules(Checkbox, styles)
Better yet, use classnames instead of getStyleNameFor(color).