CSS architecture with React that also can be themed - css

I'm currently building out a large React app. Css, has never been my strong point. But now CSS has sass / cssNext / inline styles with React. I've been using BEM with sass, but as my other applications have grown huge even that starts to break down. Especially when you had on the ability to "re-skin" or "theme" the pages outside of the primary color schemes etc..
so -- can someone point me to a proven way to create css with react that can scale very well, and allows for custome theme'ing when people want to borrow my components. For instance,
<MyComponent />
// this component has its styles but lets say Joe Schmoe wants be import
// it? But, Joe wants to overlay his custom styles?
// Is there a new paradigm that allows for an overlay or reskin within the component?
Or even the idea of the whole application being skinnable some time down the line. I know this is sorta a very base question, but whenever I build out projects my pain points also seem to be the CSS - so I want to know what really works.

This was, until recently, not a solved problem in the React world.
I'm one of the maintainers of ElementalUI, a React component library, and we've been trying out all the different ways of styling for the past 6-12 months. (!) You name it, we've tried it. (I talked about my experiences with some of the most popular libraries during my ReactNL keynote and where they break down)
The issue is that none of the current styling libraries have built-in support for theming at all. You can do it with most of them in a very hacky, non user-friendly way, but that's not what you want when you distribute a component, right?
That's why we built styled-components. styled-components has a bunch of interesting properties, and one of them is that theming is directly built into the library, making it the perfect choice for building distributable components!
Here is the short explanation, though I encourage you to go through our documentation which explains everything!
This is what the basic usage of styled-components looks like:
import React from 'react';
import styled from 'styled-components';
// Create a <Wrapper> react component that renders a <section> with
// some padding and a papayawhip background
const Wrapper = styled.section`
padding: 4em;
background: papayawhip;
`;
This variable, Wrapper, is now React components you can render:
// Use them like any other React component – except they're styled!
<Wrapper>
<Title>Hello World, this is my first styled component!</Title>
</Wrapper>
(if you click on the image you'll get a live playground)
When you pass an interpolated function into the tagged template literal, we pass you the properties passed to the component. This means you can adapt to the props:
import styled from 'styled-components';
const Button = styled.button`
/* Adapt the colors based on primary prop */
background: ${props => props.primary ? 'palevioletred' : 'white'};
color: ${props => props.primary ? 'white' : 'palevioletred'};
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid palevioletred;
border-radius: 3px;
`;
Here, we've created a Button component that you can make primary like any other React component:
<Button>Normal</Button>
<Button primary>Primary</Button>
Now comes the theming aspect. We export a component called ThemeProvider that you can pass a theme to and wrap your app (or parts of the app) in:
import { ThemeProvider } from 'styled-components';
const theme = {
main: 'mediumseagreen',
};
ReactDOM.render(
<ThemeProvider theme={theme}>
<MyApp />
</ThemeProvider>,
myElem
);
Now any styled component within that ThemeProvider, no matter how deep thanks to context, will get this theme injected into the props.
This is what a themable Button would look like:
import styled from 'styled-components';
const Button = styled.button`
/* Color the background and border with theme.main */
background: ${props => props.theme.main};
border: 2px solid ${props => props.theme.main};
/* …more styles here… */
`;
Now your Button will take the theme it gets passed and change it's styling based on that! (you can also provide defaults via defaultProps)
That's the gist of styled-components and how it helps to build distributable components!
We have a currently WIP doc about writing third-party component libraries which I'd encourage you to check out, and of course the normal documentation is a good read too. We've tried to cover all the bases, so if you see anything you dislike or that you think is missing please immediately let us know and we'll discuss!
If you have any other questions about styled-components feel free to reply here or reach out on Twitter. (#mxstbr)

I don't know what is the best way. I think it's more like a personal preference. I will just share the tools that I'm using. What I'm using is css-modules with postcss.
css-modules gives you the power to create a local-scoped identifier with a global unique name for each of your CSS classes and also enable a modular and reusable CSS! You can also use postcss-modules-values to create a global settings file which contains all the settings variables. So that you can change the theme for your website.
Here's how I structure the components. Each of my component will have one css file which is very easy to maintain or make changes.
Here's the code for the Button component.
function Button(props) {
const className = props.className ? `${styles.button} ${props.className}` : styles.button;
return (
<button disabled={props.disabled} className={`${className}`} type="button" onClick={props.onClick}>
{Children.toArray(props.children)}
</button>
);
}
Notice that I have a className for the component which allows other component to pass in the class for the button component. So that when someone borrow your component they can extend or override your button styles.
If you need to create a customisable website, I will also recommend to use Less.js which provides the live preview of the customised website.

Related

Import style dictionary into styled components

I'm currently deciding which technologies to use in a project. I always liked sass, and the main reasons are the nesting of css and the possibility of creating dicionaty classes to hold all design information, such as pallet, margins, etc. Such as below:
$primary-color: #fff;
$seconady-color: #eee;
And then, in the actual .scss file I can import this dictionary and have easy access to pallete, thus achieving standartization and facilitating the creation of style sheets:
#import "dictionary.scss";
Styled components are a great thing, and I totally agree with their website stated advatanged. However, I do not like the idea of losing this dictionary functionality I have with sass. I know I can pass data to styled components from state and props, but that also means that, in some point, I will have to pass those props or state from somewhere. Like:
<Foo primaryColor="#fff" secondaryColor="#eee"/>
Is there a way I can conciliate this dictionary functionality I have with sass with styled components? Someway to import a dictionary.sass into my styledComponent.js file or even a .json or something. A way to import static pallet, fonts, margins data that is not React props or state.
You can declare the variables in plain Javascript in a file and import them where you style components.
Dictionary file would look something like this:
export const primaryColor = '#fff';
export const seconadyColor = '#eee';
Then interpolate them when you apply styling:
import { primaryColor } from './variables.js';
const Button = styled.button`
border-radius: 3px;
border: none;
color: ${primaryColor};
`
You can also import Sass variables to JS: https://til.hashrocket.com/posts/sxbrscjuqu-share-scss-variables-with-javascript

Combing global class names with component specific style

I'm building a design system where I put emphasis on the architecture - I want it to be a good developer experience.
Bootstrap is used in this system but also together with component-specific styles. I'm thinking I want CSS-in-JS because I like to write style in the actual component, not in a different CSS file.
I have an idea, something like this:
const componentSpecificStyle = `margin-bottom: 0rem;`
const globalBootstrapClass = ['card', 'card-body']
return <div someArgument={componentSpecificStyle + globalBootstrapClass} />
This way it would be standard, two types of classes, one argument on the element, less confusion for coming developers.
What I've tried
Looked into Styled-Components and Emotion, from what I can tell they don't help me achieve this. It's possible to do
const Component = styled.div`margin-bottom: 0rem;`
return <Component className={'card card-body'}
But it seems a bit clumsy to me.
React-Bootstrap would be a solution for this but I think I usually end up adding extra classnames anyway, so I won't abstract that away...
ex.
import { Card } from 'react-bootstrap'
const componentSpecificStyle = `margin-bottom: 0rem;`
return <Card.body style={{componentSpecificStyle}} />
or something similar... but as I said, what if I want to add another classname on top of this? then we are styling in three different ways, react-bootstrap, inline-ish style and className.
Question
Am I making it unnecessarily complex?
Any suggestions or thoughts on the matter are highly appreciated!
If you want to define CSS inside your components, you're going to need CSS-in-JS indeed.
Theoretically, you're allowed define inline styles like so:
const style = {
marginBottom: '0rem',
};
return <div style={style} />
but this doesn't scale well, all styles are inlined, and you don't get all the benefits of CSS-in-JS, like ability to use props, themes, style inheritance, and having your styles autoprefixed.
Example of what you've tried in pt 1 actually makes a lot of sense.
Maybe it isn't the absolute best idea to mix global class names with styled-components, so if you want to go all-in with styled-components, you could define some set of styles in styled-components only, and inherit them one in another, like so:
const Card = styled.div`
/* Your card styles go here */
`;
const CardBody = styled(Card)`
/* Your card body styles go here */
/* (in your example you apply card and card-body to the same element, */
/* so I assume card-body is a "variant" of card) */
`;
const Component = styled(CardBody)`
margin-bottom: 0rem;
`;
return <Component />
This way, you have all your styles managed by styled-components, and you don't need to worry about global styles overwriting something you wrote in styled-components - because Component styles will be more important than CardBody styles, and CardBody styles will be more important than Card styles.
The best solution I've come up with so far is using Emotion and their css-prop on elements. https://emotion.sh/docs/css-prop
This way I can write code like it's inline-css but the end result is a class on the element, which I think is neat.
Here's an example:
const styleEmployeeBox = css`border-right: black solid 1px;`
const bstyleCard = 'card';
...
return <div css={styleEmployeeBox} className={bstyleCard}>
Inspecting the element shows me:
<div class="card css-nrnevs-ComponentName">
Writing this kind of css-in-js is something I'm choosing to go with because I see a lot of developers in my team writing inlined style on the style prop -- probably because they are lazy and don't want to add a css-classes for small specific fixes.
If they are reasons to why I shouldn't go ahead with this solution, I'd be HAPPY to hear about it. :)

Why does CSS styling disappear in React when directly changing route in browser URI?

I have a simple front-end React app created using npx create-react-app. The app is using react-router-dom routes. When I directly change the URI in the browser from say, localhost:3000/ to localhost:3000/search it will navigate to the <Route>but with no CSS rendered; just HTML from the component.
How can I make sure CSS is rendered in the new route when directly navigating in the browser? My future goal is to be able to copy and paste a route in a new tab and navigate to the correct page and display results from an API.
Css style sheets will need to be imported either at the root level or within the file itself.
style sheets need to be imported when used and then the corresponding classname will need to be used within the component or tag.
Another useful way to set react css without style sheets is by using in line styles
e.g
<div style ={{float: "right", textAlign : "center"}}> </div>
EDIT
A really easy way to get styles going within a react project is install bootstrap.
then buttons and stuff can be assigned classNames such as
<div className = "jumbotron"></>
this will leave a grey box around the items.
<div className = "btn btn-primary"></>
this will give you a blue styled button.
Any more information or help within your application let me know and provide some code snippets.
You can use styled-components. styled-components are widely used in ReactJs and React Native and it's a perfect choice.
styled-component : https://www.npmjs.com/package/styled-components
I realized that react apps created using npx create-react-app allow you to import a css module for components.
Given the component, Button.jsx, you can simply create a css module with the convention, [module-name].module.css. For the case of Button.jsx, create a file named Button.module.css, import "styles" from the module. Styles will be an object containing all the CSS styles.
I if I had a folder named "components" with all my components, I could make a folder within "components", say called "compStyles", and create all the [module-name].module.css files in there.
Button.module.css:
/* class names must be camelCased */
.myButton {
margin: 0 auto;
}
span {
fontSize: 20px;
}
If I had the above mentioned file structure, I could import and use like so:
import React from 'react';
import styles from './styles/Button.module.css';
const Button = () => {
return (
<div className={styles.myButton}>
<button><span>Some Button</span></button>
</div>
)
}
export default Button;
Styles for the span will be automatically applied, and any other class will be referenced by styles.className. Create one file for every component, and each component's CSS will take care of itself and not break like it would if it was in the public folder.

How to stylize web compoenent inside react app?

I have my react app inside which i want to use vaadin-date-picker (v. 4.0.5).
I want to change some of the date pickers in a way that they would be above my modal by changing z-index to 1100 (for example)
and some to stay at 200.
In some examples, people put <style> tag inside
<vaadin-date-picker></vaadin-date-picker>
But react is not recognizing <style> attribute inside render function.
I can set class for
<vaadin-date-picker class='my-class'>
but it only changes control itself and not the backdrop part. Is there a way to change styles of some web components inside react app?
Make sure you are importing the file correctly
import './yourcssfile.css'; // if in same directory
also in react classes are applied using className keyword
<vaadin-date-picker className="my-class">
and lastly you have to follow the documentation vaadin. you can't add your own styles if the vaadin-date-picker doesn't support it.
Here in their documentation it says Vaadin Date Picker comes with both Lumo and Material design themes, and it can be customized to fit your application.
The cleanest way to use styles in my opinion is to use CSS files, so
import './classname.css';
Would be my default answer. However, if you want to set styles explicitly in your Component, these are two examples, how you can do it:
class Example extends Component {
getStyle1 = () => {
return {
fontWeight: 'bold'
};
}
render () {
return (
<div><div style={this.getStyle1()}>style1</div>
<div style={style2}>style2</div></div>
)
}
}
const style2 = {
fontStyle: 'italic'
}
Remember that it's JavaScript objects that you return with your styles, so you don't use CSS syntax with dashes (e.g. you type backgroundColor instead of background-color) and all values must be put in quotes.

Why CSS Modules styling is not working on my elements, RMWC?

I am following the tutorial below on react material web components (RMWC) and got confused with the styling and theming chapters.
https://jamesmfriedman.github.io/rmwc/styling-theming
In this chapter, the author tries to explain differences between using standard CSS and CSS Modules, but I am unable to understand this. What are the differences between the two and why do we use CSS modules and how is it different from standard CSS?
I am also trying to apply CSS using CSS modules, but CSS is not getting applied over the elements. Am I doing something wrong here?
I am using Create-React-App.
My code (style is not getting applied):
index.js
import React from 'react'
import ReactDom from 'react-dom'
import styles from './index.css'
import Button from '#material-ui/core/Button'
class App extends React.Component {
render() {
return (
<div>
<Button className={styles.button}>
CSS Modules
</Button>
</div>
)
}
}
ReactDom.render(<App />, document.getElementById('root'))
index.css
.button {
background: linear-gradient(45deg, #fe6b8b 30%, #ff8e53 90%);
border-radius: 3px;
border: 0;
color: white;
height: 48px;
padding: 0 30px;
box-shadow: 0 3px 5px 2px rgba(255, 105, 135, .3);
}
Even though by doing it in below way , it is working fine.
import React from 'react'
import ReactDom from 'react-dom'
import styles from './index.css'
import Button from '#material-ui/core/Button'
class App extends React.Component {
render() {
return (
<div>
<Button className="button">
CSS Modules
</Button>
</div>
)
}
}
ReactDom.render(<App />, document.getElementById('root'))
Your code is fine except for one small detail you might have missed. Using create-react-app allows you to use css modules if you follow their guidelines. Your file name needs to be index.module.css for it to work as a css module.
Reference:
This project supports CSS Modules alongside regular stylesheets using the [name].module.css file naming convention.
If you think about programming best practice, using global variable is bad.
Because you will run to collision of variable eventually. For worst case, there's no any warn and you're just confused when the value of variable is changed.
In css, sharing class or any selector might help you save time to write css. but eventually you will get some problem (especially in medium-large code base) finding that element is styled by unintentionally class or selector or you want to change style of some element but it affect other element that you don't want.
I suggest you reading this link for further detail.
https://css-tricks.com/css-modules-part-1-need/
for you case, you need to setup babel plugin to use css modules in react
https://github.com/gajus/babel-plugin-react-css-modules
if you create project by create-react-app, you should look at #Keno Clayton 's answer
You can get the answer what different among standart css with css module, when you make more than one page. You will use some css to different page and sometimes you will use same css class name. Same class name will make css overwrite your style. CSS Module comes to fix that problem.

Resources