Ways to style a React Component
React Js components have become building blocks of UI these days. If your an absolute beginner to React like me, have you ever wondered how to style an React component, then this article if for you. Having the same question on my mind, I started exploring all possible ways of styling an React component. In this article, we will go through the various ways of styling a React component by developing an ToDoApp.
By the end of the article, we will be developing an ToDoApp using React js . First we should plan our project like how many components our app should have, what are all the elements that should be there in each component. I will skip how to create an React App.
If you want know about how to create an React App, go through my previous article : Getting started with React — for Beginners.
Let’s have a look of our ToDoApp, we will get finally.
To see the live version of our ToDoApp, follow this link- Link for the live version of ToDoApp.
Strictly for PC’s, bcoz i haven’t used any bootstrap or media queries to make it align for small screen devices. You can play around it :)
Let’s get started. Initially, i have divided our ToDoApp in two main components. One for navbar and another component for handling Tasks. Our react project directory looks somewhat like this.
Now create a folder named components in the src folder. These components folder will hold all of our app components in it. In that components folder create two folders namely Navbar and Tasks. And those two folders should also contain and .js and .css files with any name you like. I will go with our Component name. It is the best practice to go with component name, so that you won’t get confused with those files while handling complex projects. Now our project looks like this.
First we will develop an logic for our ToDoApp and then we will style our app by going through all ways of styling an React component.
Our Navbar should contain only the name of our app. Let’s start coding it in Navbar.js in Navbar component. We will style it next section of this article.
// path: src/components/Navbar/Navbar.js
import React, { Component } from 'react';import './Navbar.css';class Navbar extends Component { render() { return( <header> <h1> ToDoApp </h1> </header> ) }}export default Navbar;
Importing our Navbar component, into App.js and viewing it after it is being rendered.
// path: src/App.jsimport React, { Component } from 'react';import Navbar from './components/Navbar/Navbar';import './App.css';class App extends Component { render() {
return(
<div>
<Navbar />
</div>
)
}
}export default App;
Start the development server using this command:
npm start
You will get output some thing like this in the browser after our Navbar component being rendered in the App.js.
Now, let’s jump to our Tasks component. Create an another component TaskAdd, with .js and .css in it and also Tasks.js and Task.js along with .css files in the Tasks component. Our Tasks component looks some what like this.
I have designed our Tasks component, in such a way that our App.js passes an reference of array that contains tasks remaining to Tasks.js which in turn maps every task in the array to Task.js, where Task.js is a functional component which will display every individual task.
TaskAdd component will holds elements like input field and also an button, where we can get the value of the task and add it to tasks remain array after clicking that button. Let’s start coding TaskAdd.js component.
//path: src/components/Tasks/TaskAdd/TaskAdd.jsimport React, { Component } from 'react';import './TaskAdd.css';class TaskAdd extends Component {render() {
return(
<div> <h1>Add your task here</h1>
<input type="text"placeholder="Enter Task here..!!"> <button> Add </button> </div>
)};}export default TaskAdd;
Now we will be importing our TaskAdd component into our App.js. Also we will be adding an button in App.js after the Navbar, by which we will be handling the Night Mode and Light Mode of our ToDoApp.
// path: src/App.jsimport React, { Component } from 'react';import Navbar from './components/Navbar/Navbar';import TaskAdd from './components/Tasks/TaskAdd/TaskAdd';import './App.css';class App extends Component {render() {
return(
<div>
<Navbar /> <button> Mode </button> <TaskAdd /> </div>
)
}
}export default App;
The preview of our ToDoApp looks some what like this when rendered in App.js component.
Let’s create a state in App component, where it contains addTask which will be used to store the value that was inputed by the input field, tasksRemain is an array that holds the values of tasks remaining and darkMode contains boolean value true or false, that will be triggered using Mode button.
// path: src/App.jsstate = { tasksRemain: ['Project - X bugs', 'Shopping'], addTask: '', darkMode: false};
Here,I am hardcoding two tasks in taskRemain array. You can leave it empty if you want. To catch the value that was typed in the input field, we will now create a function in the App component, that handles the catching of the value that was typed.
// path: src/App.js
// Assigns Value in the Input fieldonChangeHandler = (event) => { this.setState({ addTask: event.target.value });
}
By triggering an event, we are assigning the task to addTask variable of the state. Now we will write a function that will push the addTask value to taskRemain array. This function will we triggered after clicking only Add button.
// path: src/App.js
// Adds Task to the arrayaddTaskHandler = () => { this.setState({ tasksRemain: [...this.state.tasksRemain, this.state.addTask], addTask: '' });}
Now pass these two functions reference to the TaskAdd component. So that we will trigger them when an event occurs in the TaskAdd component.
// path: src/App.js<TaskAdd changed={this.onChangeHandler} clicked={this.addTaskHandler} />
Now using props in TaskAdd component we will assign the references of these two persons to the events. addTaskHandler() will be triggered when an onClick event occurs in the button element. onChangeHandler() will be triggered when an onChange event occurs in the input field.
//path: src/components/Tasks/TaskAdd/TaskAdd.jsimport React, { Component } from 'react';import './TaskAdd.css';class TaskAdd extends Component {render() {
return(
<div> <h1>Add your task here</h1> <input
type="text"
onChange={this.props.changed}
placeholder="Enter Task here..!!"></input>
<button
onClick={this.props.clicked}>
Add
</button> </div>
)};}export default TaskAdd;
To display all the the tasks, that are pushed into the tasksRemain array. Now we will pass the reference of tasksRemain array to Tasks component. In Tasks component we will access every task in the array and pass them as individual elements to the Task component, where we will display every task. We are now writing an removeTaskHandler(), in App component which takes index value of an element as a parameter and then removes that task from the list.
// path: src/App.js
// Removes tasks from the tasks array removeTaskHandler = index => {
const beforeTasks = this.state.tasksRemain.slice(0, index);
const afterTasks = this.state.tasksRemain.slice(index+1);
const tasks = [...beforeTasks, ...afterTasks];
//console.log(tasks);
this.setState({ tasksRemain: tasks });
}
Now we are coding our Tasks component that will displays elements in the remaining tasks array.
// path: src/components/Tasks/Tasks.jsimport React from 'react';
import Task from './Task';
import './Tasks.css'; const Tasks=(props)=> {
return (
<div>
<h1>
Tasks to be completed
</h1>
<ul>
{
props.tasks.map((task, index) => {
return (
<Task
remove={()=>props.remove(index)}
task={task}
key={index} />
)
})
}
</ul>
</div>
) }; export default Tasks;
While iterating over an array, we will have an index to each element in the array. Also we are assigning an key to the elements, because an unique value needs to there as a key for identifying every element uniquely. Task component is as follows.
import React from 'react';
import './Task.css';
const Task=(props)=> {
return(
<li>
<p>
{props.task}
</p>
<button
onClick={props.remove}>
Completed
</button>
</li>
)} export default Task;
Let’s look at our app :)
Hurrah..!! Done with the logic of our app. Let’s start styling our app. Styling can be done for a React component in four ways.
CSS Stylesheets
Like normal styling of an HTML element we can also style the elements in our React component using stylesheets. Creating classes that holds the styles that we want to render on our html element in a .css file. Then importing that .css file into our React component and initializing to the className attribute of that element will solves our problem. Let’s start styling the Navbar component of our ToDoApp.
//path: src/components/Navbar/Navbar.css/* CSS STYLE SHEETS */ header {
background-color: #38ada9;
color: #ffffff;
padding: 10px;
/*box-shadow: 5px 7px 5px 7px #888888;*/
}
Here i have applied style to the html tag directly (header). So no need of initializing to the className attribute of that element. Just importing .css file into the Navbar component gets our job done.
// path : src/components/Navbar/Navbar.jsimport React, { Component } from 'react';
import './Navbar.css'; class Navbar extends Component {
render() {
return(
<header>
<h1> ToDoApp </h1>
</header>
)
}
} export default Navbar;
Navbar component part is done. Final code of Navbar component looks like this. Have a look of our app after applying style to Navbar component.
Now let’s apply the similar type of styling for the two sections that we have observed in above picture. Such that TaskAdd should be at the left position. Next to that, right side Tasks Remaining should be displayed. Now add the style which includes float property set to left in the TaskAdd.css file to meet our requirements.
// path: src/components/Tasks/TaskAdd/TaskAdd.css.task-add {
float: left;
margin: 0 auto;
padding: 70px 80px 80px 130px;
}
Here we have used class, so we need to import this .css file in the component and also should be assigned to the className attribute of the element where we want our styled class to be triggered.
// path: src/components/Tasks/TaskAdd/TaskAdd.jsimport React, { Component } from 'react';import './TaskAdd.css';class TaskAdd extends Component {render() {
return(
<div className="task-add"> <h1>Add your task here</h1> <input
type="text"
onChange={this.props.changed}
placeholder="Enter Task here..!!"></input>
<button
onClick={this.props.clicked}>
Add
</button> </div>
)};}export default TaskAdd;
Lets add the similar type of styling for Tasks components. so that all the remaining tasks will be shown at the right side of our app.
// path: src/components/Tasks/Tasks.css
/* Style sheets */ .task-remain {
float: right;
margin: 0 auto;
padding: 70px 150px 80px 80px;
}
Now importing that .css file into our Tasks component. Let’s start importing now.
import React from 'react';
import Task from './Task';
import './Tasks.css'; const Tasks=(props)=> {
return (
<div className="task-remain">
<h1> Tasks to be completed </h1>
<ul>
{
props.tasks.map((task, index) => {
return (
<Task
remove={()=>props.remove(index)}
task={task}
key={index}/>
)
})
}
</ul>
</div>
)
}; export default Tasks;
Let’s have a look of our ToDoApp after applying style to these two components.
Now it looks some what pretty, when compared to previous version. Let’s add an inline style to the mode button which is highlighted in the above picture.
Inline CSS
React allows to style our component using Inline CSS. Attributes of normal CSS are passed as Javascript objects and assigned to the style attribute of the element we are trying to style. Since they are passed as Javascript object, CSS attributes they are written in the form of CamelCase . For example, background-color is written as backgroundColor.
Now let’s add an inline style to the Mode button in the App component.
// path: src/App.jsimport React, { Component } from 'react';
import Navbar from './components/Navbar/Navbar';
import Tasks from './components/Tasks/Tasks';
import TaskAdd from './components/Tasks/TaskAdd/TaskAdd';
import './App.css';class App extends Component {
......
...... render() {
// Button style for Dark Mode Option
let buttonStyle = {
padding: '10px',
border: '1px solid #000000',
borderRadius: '10px',
outline: 'none',
display: 'block',
margin: '10px auto',
fontSize: '100%'
} ....
.... return (
.......
....... <button
style={buttonStyle}>
Mode
</button>
)
}
}export default App;
In the similar manner, add inline styles to some remaining elements in our components. Lets add an background color to our App component, because it will be helpful while we are handling Dark Mode to switch colors in our app.
// path: src/App.jsimport React, { Component } from 'react';
import Navbar from './components/Navbar/Navbar';
import Tasks from './components/Tasks/Tasks';
import TaskAdd from './components/Tasks/TaskAdd/TaskAdd';
import './App.css';class App extends Component {
......
......render() {
// Button style for Dark Mode Option
let buttonStyle = {
padding: '10px',
border: '1px solid #000000',
borderRadius: '10px',
outline: 'none',
display: 'block',
margin: '10px auto',
fontSize: '100%'
}
// Inline Styling for Background color let bColor = {
backgroundColor: '#ffffff',
color: '#000000',
height: '100vh'
} ....
....return (
<div className={bColor}>
.......
....... <button
style={buttonStyle}>
Mode
</button>
</div> )
}
}export default App;
Similarly, add style to the TaskAdd component’s input field, heading and button.
// path: src/components/Tasks/TaskAdd/TaskAdd.jsimport React, { Component } from 'react';
import './TaskAdd.css'; class TaskAdd extends Component {
render() { let styleInput = {
padding: '6px',
display: 'inline-block',
border: '2px solid #ccc',
borderRadius: '5px',
marginRight: '30px',
fontSize: '140%',
outline: 'none'
}; let styleHeading = {
marginBottom: '20px'
} let buttonStyle = {
padding: '14px',
width: '20%',
textAlign: 'center',
marginTop: '10px',
fontWeight: 'bold',
backgroundColor: '#74b9ff',
display: 'inline-block',
border: 'transparent',
borderRadius: '5px',
fontSize: '120%'
}
return(
<div className="task-add">
<h1
style={styleHeading}>
Add your task here
</h1> <input
style={styleInput}
type="text"
onChange={this.props.changed}
placeholder="Enter Task here..!!">
</input> <button
onClick={this.props.clicked}
style={buttonStyle}>
Add
</button>
</div>
)
};
} export default TaskAdd;
Similary add inline style to the heading and un-ordered list of the Tasks component.
// path: src/components/Tasks/Tasks.jsimport React from 'react';
import Task from './Task';
import './Tasks.css'; const Tasks=(props)=> { let styleHeader = {
marginBottom: '20px'
}; let styleList = {
listStyle: 'none'
} return ( <div className="task-remain">
<h1 style={styleHeader}>
Tasks to be completed
</h1> <ul style={styleList}>
{
props.tasks.map((task, index) => {
return (
<Task
remove={()=>props.remove(index)}
task={task} key={index}/>
)
})
}
</ul>
</div>
)
}; export default Tasks;
Similary now we are adding inline style to text and the completed button in the Task component.
import React from 'react';
import './Task.css'; const Task=(props)=> { let styleText = {
fontSize: '160%'
}; let styleCompletedButton = {
backgroundColor: '#00b894',
fontWeight: 'bold',
padding: '10px',
margin: '15px 0',
border: 'transparent',
borderRadius: '5px',
outline: 'none',
fontSize: '100%'
}; return(
<li>
<p
style={styleText}>
{props.task}
</p> <button
style={styleCompletedButton}
onClick={props.remove}>
Completed
</button>
</li>
)
} export default Task;
Let’s have a look of our ToDoApp after applying these inline style’s to our components.
Conditional styling or Dynamic styling
It is not a different type of styling, but React allows us to apply style to our components based on some conditionals or we can pass class names to the elements in our component dynamically. Let’s add these conditional styling to our app to make it look more prettier.
Now start with the dark mode option. When an onClick event is triggered near Mode button element in the App component, then the background color, font color and also the should display the mode dynamically. So that the same button can be used to turn our app into dark mode and can also turn our app back to light mode. We will do that by conditonal styling.
// path: src/App.jsimport React, { Component } from 'react';
import Navbar from './components/Navbar/Navbar';
import Tasks from './components/Tasks/Tasks';
import TaskAdd from './components/Tasks/TaskAdd/TaskAdd';
import './App.css';class App extends Component {
......
...... // Handles the mode of our application darkModeHandler = () => {
this.setState({
darkMode: !this.state.darkMode
})
} render() { // Button style for Dark Mode Option
let buttonStyle = {
padding: '10px',
border: '1px solid #000000',
borderRadius: '10px',
outline: 'none',
display: 'block',
margin: '10px auto',
fontSize: '100%'
}
// Inline Styling for Background color let bColor = {
backgroundColor: '#ffffff',
color: '#000000',
height: '100vh'
} ....
.... // Conditional Styling
if(this.state.darkMode) {
//console.log("dark")
bColor = {
backgroundColor: '#2d3436',
color: '#ffffff',
height: '100vh'
};
} return (
<div style={bColor}>
.......
....... <button
style={buttonStyle}
onClick={this.darkModeHandler}>
Mode
</button>
</div>)
}
}export default App;
The above conditional styling changes the background color based on the boolean value darkMode. If it is false, light mode is triggered which is set as default. In case if it is true, if enters the conditional statement and reset the style properties in it.
To display the mode near the button dynamically, such that it will display Light Mode when our app is in dark mode and vice versa. We will achieve it by using ternary variable. Let’s have a look.
// path: src/App.js.....
.....<button
style={buttonStyle}
onClick={this.darkModeHandler}>
{ this.state.darkMode ? 'Light': 'Dark' } Mode
</button>.....
.....
Now let’s make the button to change its color based on the Mode. We will achieve it by dynamically adding classes to the element based on some conditionals.
Create classes in the App.css file for background color, bold and font-color and import the .css file into our App component.
// path: src/App.css@import url('https://fonts.googleapis.com/cssfamily=Shadows+Into+Light&display=swap'); * {
margin: 0;
padding: 0;
font-family: 'Shadows Into Light', cursive;
word-spacing: 2px; letter-spacing: 1px;
} .bold {
font-weight: bold;
} .white-font {
color: #ffffff;
} .black-font {
color: #000000;
} .orange-bg {
background-color: #ff7f50;
} .green-bg {
background-color: #b8e994;
}
Here we added bold, white-font, black-font, orange-bg and also green-bg. Also we have imported the Google font and applied as common property. Let’s add these classes dynamically to the HTML element in our App component.
/ path: src/App.jsimport React, { Component } from 'react';
import Navbar from './components/Navbar/Navbar';
import Tasks from './components/Tasks/Tasks';
import TaskAdd from './components/Tasks/TaskAdd/TaskAdd';
import './App.css';class App extends Component {
......
......render() {
// Adding classes dynamically let buttonClasses = [] // Pushing bold class into the array
buttonClasses.push('bold'); // Checking the Mode and dynamically pushing a CSS class
if(this.state.darkMode) {
buttonClasses.push('green-bg', 'black-font');
//console.log(buttonClasses);
} else {
buttonClasses.push('orange-bg', 'black-font');
//console.log(buttonClasses);
}return (
<div style={bColor}>
.......
.......
<button
style={buttonStyle}
onClick={this.darkModeHandler}
className={buttonClasses.join(' ')}>
{ this.state.darkMode ? 'Light': 'Dark' } Mode
</button> )
}
}export default App;
Let’s have a look of our app in both modes after applying these styles to it.
We had an error in our App. Anyone observed?? It a tiny one..!!
If every task is removed by marking it as completed, then it is showing nothing. We should add any conditional statement to which checks the length of the tasksRemain array. If it is zero, then it should display No Tasks. This will make our app more user friendly. Also add an alert type background for every task based on the mode. It makes our app to look more attractive. We will achieve this by adding classes dynamically.
// path: src/App.css....
.....no-task-alert {
float: right;
margin: 0 auto;
font-weight: bold;
font-size: 30px;
opacity: 0.7;
border-radius: 5px;
margin: 80px 350px 0 0;
padding: 80px;
} .dark-mode {
background-color: white;
color: black;
} .light-mode {
background-color: black;
color: white;
}// path: src/App.js....
....class App extends Component { ....
.... render() {
....
....
let numTasks = this.state.tasksRemain.length return(
....
.... { numTasks === 0 ?
<p
className={this.state.darkMode ? 'no-task-alert dark-mode':'no-task-alert light-mode'}>
No Tasks
</p> : <Tasks
tasks={this.state.tasksRemain}
remove={this.removeTaskHandler}
darkMode={this.state.darkMode}/>
} )
}
}export default App;
Also add these alert type background styles for Task component. Here we added only for No Tasks indication.
// path: src/components/Tasks/Task.css....
.....list-style {
opacity: 0.7;
border-radius: 5px;
padding: 10px;
margin-bottom: 10px;
} .dark-mode {
background-color: white;
color: black;
} .light-mode {
background-color: black;
color: white;
}// path: src/components/Tasks/Task.js....
....return(
<li className={props.darkMode ? 'list-style dark-mode': 'list-style light-mode'}>
<p
style={styleText}>
{props.task}
</p> <button
style={styleCompletedButton}
onClick={props.remove}>
Completed
</button>
</li>
)....
....
Tadaaa..!! We have completed styling of our app. You can have your own ToDoApp for your daily use that was developed using React. Let’s have a look of final version of our app.
There are three more ways to style an React component. I haven’t used in the project. But we will go through them now.
Styled Components
Styled-components is a library for React. That helps us to use component-level styles in our app, where code will be a mixture of Javascript and CSS. For using styled components in our app, we need to install it first using this command.
npm install --save styled-components
Styling a component using styled components looks some what like this.
CSS Modules
CSS Modules is similar to styling an React component, like CSS stylesheets. In CSS Modules, the classes we had created are locally scoped. That feature we will not get in CSS external stylesheets. This helps a lot that these CSS classes won’t clash with each other or overide with another, eventhough they are declared with same name. By configuring CSS Modules, in the config folder the class names we have defined will be created something like [APPNAME__CLASSNAME__HASHCODE ] based upon the rule we declared.
To know more about how to configure CSS Modules go through this article- Article
Radium
Radium is library for React. The only cons we had while applying Inline CSS is we can’t apply psuedo selectors or any media queries. This Radium library helps us to apply psuedo selectors and also media queries in our Javascript objects and can pass as Inline styles to our React component.
To use Radium in our project, we should install it first. Install Radium library using this command.
npm install --save radium
We will appy psuedo selectors to the elements somewhat like this. And we will wrap our component with Radium while exporting to apply these selectors.
var styles = {
off: {
backgroundColor: ‘#FF5722’,
border: 0,
width: ‘20px’,
height: ‘20px’,
borderRadius: ‘50%’,
color: ‘white’,
transitionDuration: ‘.2s’,
transitionTimingFunction: ‘ease-out’,
transform: ‘translate(0px,0px)’,
‘:hover’: {
backgroundColor: ‘#FF7043’
},
‘:focus’: {
outline: ‘none’
},
}// Wrapping with Radiumexport default Radium(App);
We had gone through all the ways of styling an React component. There is no any particular rule that states to follow any specific type of styling. It’s one personal choice to follow a specific way of styling an React component.
Github Repository link- https://github.com/itzzmeakhi/ToDoApp/tree/master
Live ToDoApp link — http://bit.ly/react-ToDoApp .
Strictly for PC’s, bcoz i haven’t used any bootstrap or media queries to make it align for small screen devices. You can play around it :)
If you are trying to deploy your app to Github pages, follow this guide
Hope you liked this article :)
Do share the story and clap it if you liked it.
Let me know if you have anything to ask :)