How to Apply CSS and Styling to a React Component

How to apply CSS style to custom React component

Css styles are applied to JSX elements in react but not to the component

Wrong way of applying css styles but className is still a valid prop to the component. You can access this using this.props.className and pass to the div as className like I mentioned in right way example

<TakenFrame className="taken-frame" />

Right way of applying css styles

 class TakenFrame extends React.Component {
render(){
return(
<div className="taken-frame">

</div>
//OR
<div className={this.props.className}>

</div>
)
}
}

React.js inline style best practices

There aren't a lot of "Best Practices" yet. Those of us that are using inline-styles, for React components, are still very much experimenting.

There are a number of approaches that vary wildly: React inline-style lib comparison chart

All or nothing?

What we refer to as "style" actually includes quite a few concepts:

  • Layout — how an element/component looks in relationship to others
  • Appearance — the characteristics of an element/component
  • Behavior and state — how an element/component looks in a given state

Start with state-styles

React is already managing the state of your components, this makes styles of state and behavior a natural fit for colocation with your component logic.

Instead of building components to render with conditional state-classes, consider adding state-styles directly:

// Typical component with state-classes
<li
className={classnames({ 'todo-list__item': true, 'is-complete': item.complete })} />

// Using inline-styles for state
<li className='todo-list__item'
style={(item.complete) ? styles.complete : {}} />

Note that we're using a class to style appearance but no longer using any .is- prefixed class for state and behavior.

We can use Object.assign (ES6) or _.extend (underscore/lodash) to add support for multiple states:

// Supporting multiple-states with inline-styles
<li 'todo-list__item'
style={Object.assign({}, item.complete && styles.complete, item.due && styles.due )}>

Customization and reusability

Now that we're using Object.assign it becomes very simple to make our component reusable with different styles. If we want to override the default styles, we can do so at the call-site with props, like so: <TodoItem dueStyle={ fontWeight: "bold" } />. Implemented like this:

<li 'todo-list__item'
style={Object.assign({},
item.due && styles.due,
item.due && this.props.dueStyles)}>

Layout

Personally, I don't see compelling reason to inline layout styles. There are a number of great CSS layout systems out there. I'd just use one.

That said, don't add layout styles directly to your component. Wrap your components with layout components. Here's an example.

// This couples your component to the layout system
// It reduces the reusability of your component
<UserBadge
className="col-xs-12 col-sm-6 col-md-8"
firstName="Michael"
lastName="Chan" />

// This is much easier to maintain and change
<div class="col-xs-12 col-sm-6 col-md-8">
<UserBadge
firstName="Michael"
lastName="Chan" />
</div>

For layout support, I often try to design components to be 100% width and height.

Appearance

This is the most contentious area of the "inline-style" debate. Ultimately, it's up to the component your designing and the comfort of your team with JavaScript.

One thing is certain, you'll need the assistance of a library. Browser-states (:hover, :focus), and media-queries are painful in raw React.

I like Radium because the syntax for those hard parts is designed to model that of SASS.

Code organization

Often you'll see a style object outside of the module. For a todo-list component, it might look something like this:

var styles = {
root: {
display: "block"
},
item: {
color: "black"

complete: {
textDecoration: "line-through"
},

due: {
color: "red"
}
},
}

getter functions

Adding a bunch of style logic to your template can get a little messy (as seen above). I like to create getter functions to compute styles:

React.createClass({
getStyles: function () {
return Object.assign(
{},
item.props.complete && styles.complete,
item.props.due && styles.due,
item.props.due && this.props.dueStyles
);
},

render: function () {
return <li style={this.getStyles()}>{this.props.item}</li>
}
});

Further watching

I discussed all of these in more detail at React Europe earlier this year: Inline Styles and when it's best to 'just use CSS'.

I'm happy to help as you make new discoveries along the way :) Hit me up -> @chantastic

How can I css style a child react component?

Generally speaking you don't have to componentise every element when using React and Styled Components. Typically you only want to do this to take advantage of the extra features they bring to the table.

In your case, this would be:

   <Slider>
<section>Content A</section>
<section>Content B</section>
</Slider>

and thus you could style your sections using styled components like:

  const Slider = styled.div`
section {
//styling of the section
}
`;

If you did want to have the sections as components too, then you should be able to do the above still; I've added multiple forms of section to the example below. section being the HTML element, StyledSection being the styled component and SectionComponent is a functional component which returns a <section>.

Simple working example: https://codesandbox.io/s/react-fiddle-forked-5xt6p?file=/src/App.js

When working with CSS within your Styled Components, imagine that you're still working with ordinary CSS files and HTML elements. If your SectionComponent is a child of Slider and is a <section>. Then you can select it accordingly in the same manner you would CSS.

How to make React CSS import component-scoped?

It sounds like CSS Modules, or many of the other CSS-in-JS packages, does what you want. Others include Emotion (my current favorite), Styled Components, or many of the packages here.

A CSS Module is a CSS file in which all class names and animation names are scoped locally by default. All URLs (url(...)) and @imports are in module request format (./xxx and ../xxx means relative, xxx and xxx/yyy means in modules folder, i. e. in node_modules).

Here's a quick example:

Let's say we have a React component like:

import React from 'react';
import styles from './styles/button.css';

class Button extends React.Component {
render() {
return (
<button className={styles.button}>
Click Me
</button>
);
}
}
export default Button;

and some CSS in ./styles/button.css of:

.button {
border-radius: 3px;
background-color: green;
color: white;
}

After CSS Modules performs it's magic the generated CSS will be something like:

.button_3GjDE {
border-radius: 3px;
background-color: green;
color: white;
}

where the _3DjDE is a randomly generated hash - giving the CSS class a unique name.

An Alternative

A simpler alternative would be to avoid using generic selectors (like p, code, etc) and adopt a class-based naming convention for components and elements. Even a convention like BEM would help in preventing the conflicts you're encountering.

Applying this to your example, you might go with:

.aboutContainer {
# Some style
}

.aboutContainer__code {
# Some style
}

Essentially all elements you need to style would receive a unique classname.

Changing the CSS for a React component has effect on all other pages

If you want to localize CSS rules, then you would have to switch to modular stylesheets (works the same for sass stylesheets).

In your current structure, the component imports non-modular stylesheet and doesn't localize the changes with a unique identifier. Therfore added rules live in a global scope without a unique identifier that would localize them so that only selected components could understand them. That means that they are capable of easily overwriting the same-named rules which were previously established (import order matters here, because it would dictate how the bundler appends the output stylesheet).

So instead of holding component-related rules within ./style.scss file, rename it to ./index.module.scss and then you would utilize it within the component like so:

import React from 'react';
import styles from './index.module.scss';

const HomePage = () => {
return (
<div className={style.homepage}>
<h1 className={style.heading}>Landing page</h1>
</div>
);
};

export default HomePage;

and your stylesheet would look like:

.heading {
color: #f3f3f3;
font-family: "Cambria";
font-weight: normal;
font-size: 2rem;
}

disclaimer:

I've changed the styling convention from selecting elements by their tag, to selecting them by class, because targetting elements by tag is widely considered a bad practice [ref] , but if you want to maintain it, then you would have to provide a parent scope for such a rule (it already exists since the parent <div/> element has an assigned class.
In this case the implementation would look like:

import React from 'react';
import styles from './index.module.scss';

const HomePage = () => {
return (
<div className={style.homepage}>
<h1>Landing page</h1>
</div>
);
};

export default HomePage;

and styles:

.homepage {
h1 {
color: #f3f3f3;
font-family: "Cambria";
font-weight: normal;
font-size: 2rem;
}
}

Is there a way to style an element in React using the ID without using className?

Since you are using CSS Modules you need to access the styles slightly differently. You need to import styles from 'Component.module.css'; and then declare your styles by referencing this imported object styles.MyClass or in your case since you have hyphens you need to use bracket notation styles["top-bar"]

Here is a working sandbox

//MyComponent.js

import styles from "./MyComponent.module.css";

export default function MyComponent() {
return (
<div id={styles["top-bar"]}>
<h2>My Component</h2>
<InnerComponent id="inner" />
</div>
);
}

function InnerComponent({ id }) {
return (
<div id={styles[id]}>
<h3>Inner Component</h3>
<p id={styles.para}>Styled Paragraph</p>
</div>
);
}
//MyComponent.module.css

#top-bar {
width: 90vw;
margin: 1rem auto;
padding: 1rem;
text-align: center;
background-color: LightPink;
}

#inner {
background-color: LightBlue;
text-align: left;
}

#para {
color: red;
}

Here's a quick snippet showing it working with IDs.

function MyComponent() {
return (
<div id="top-bar">
<h2>My Component</h2>
<InnerComponent id="inner" />
</div>
)
}

function InnerComponent({id}) {
return (
<div id={id}>
<h3>Inner Component</h3>
</div>
)
}

ReactDOM.render(<MyComponent />, document.getElementById('App'));
#top-bar {
width: 90vw;
margin: 1rem auto;
padding: 1rem;
text-align:center;
background-color: LightPink;
}

#inner {
background-color: LightBlue;
text-align: left;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<div id="App"></div>


Related Topics



Leave a reply



Submit