Styling React Components
Level: Beginner
- Inline styles: when and how to use them for dynamic styling
- CSS Classes: maintaining styles across components
- CSS Modules: preventing class name collisions and scoping
- Tailwind CSS: rapid development with utility classes
- Dynamic styling based on props and state
- Conditional styling for different states (active, selected, disabled)
- Responsive design in React components
- When to choose each approach for School Management System screens
Why This Matters
Styling React Components is part of building maintainable React applications. You will use it when creating student dashboards, forms, tables, API-connected screens, routing flows, and reusable UI components.
React components need to look good. There are multiple ways to style them.
The Problem
Beginners often write React code that works for a small demo but becomes difficult when data, forms, API calls, and reusable components grow. This lesson explains Styling React Components in a way that helps you build predictable UI for real .NET Web API projects.
Approach 1: Inline Styles
Pass a JavaScript object to style attribute.
function StudentCard({ student }) {
const cardStyle = {
border: "1px solid #ddd",
padding: "20px",
borderRadius: "8px",
backgroundColor: "#f9f9f9"
};
return (
<div style={cardStyle}>
<h3 style={{ color: "#333", fontSize: "18px" }}>{student.name}</h3>
<p style={{ color: "#666" }}>Class: {student.className}</p>
</div>
);
}
Pros: Scoped to component, dynamic styling Cons: Verbose, no hover/media queries, not reusable
Approach 2: CSS Classes
Define CSS in a file, apply with className.
// StudentCard.jsx
function StudentCard({ student }) {
return (
<div className="student-card">
<h3 className="student-name">{student.name}</h3>
<p className="student-class">Class: {student.className}</p>
</div>
);
}
/* StudentCard.css */
.student-card {
border: 1px solid #ddd;
padding: 20px;
border-radius: 8px;
background-color: #f9f9f9;
}
.student-name {
color: #333;
font-size: 18px;
margin: 0;
}
.student-class {
color: #666;
}
/* Hover effect */
.student-card:hover {
background-color: #f0f0f0;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
/* Responsive */
@media (max-width: 600px) {
.student-card {
padding: 10px;
}
}
Import the CSS:
import './StudentCard.css';
function StudentCard({ student }) {
return (
<div className="student-card">
<h3 className="student-name">{student.name}</h3>
<p className="student-class">Class: {student.className}</p>
</div>
);
}
Pros: Familiar, supports full CSS (hover, media queries) Cons: Class name collisions across files, bloated CSS
Approach 3: CSS Modules (Scoped CSS)
CSS files that scope classes to components automatically.
/* StudentCard.module.css */
.card {
border: 1px solid #ddd;
padding: 20px;
border-radius: 8px;
}
.name {
color: #333;
font-size: 18px;
}
.card:hover {
background-color: #f0f0f0;
}
// StudentCard.jsx
import styles from './StudentCard.module.css';
function StudentCard({ student }) {
return (
<div className={styles.card}>
<h3 className={styles.name}>{student.name}</h3>
<p>Class: {student.className}</p>
</div>
);
}
Classes are scoped — .card in StudentCard.module.css won't conflict with .card elsewhere.
Pros: Scoped, full CSS support, no collisions Cons: Slightly different syntax
Approach 4: Tailwind CSS (Utility Classes)
Use pre-made utility classes.
Install:
npm install -D tailwindcss
npx tailwindcss init
Use:
function StudentCard({ student }) {
return (
<div className="border border-gray-300 p-5 rounded-lg bg-gray-50 hover:bg-gray-100">
<h3 className="text-gray-800 text-lg font-semibold">{student.name}</h3>
<p className="text-gray-600">Class: {student.className}</p>
</div>
);
}
Pros: Fast, small bundle, consistent design Cons: Learning curve, verbose classes, requires setup
Dynamic Styling
Often you need to style based on props or state.
With Inline Styles
function StudentBadge({ status }) {
const statusColors = {
'Active': { backgroundColor: '#4CAF50', color: 'white' },
'Inactive': { backgroundColor: '#f44336', color: 'white' },
'Graduated': { backgroundColor: '#2196F3', color: 'white' }
};
return (
<span style={statusColors[status] || statusColors['Inactive']}>
{status}
</span>
);
}
With CSS Classes
function StudentBadge({ status }) {
const statusClass = status.toLowerCase(); // 'active', 'inactive', etc.
return <span className={`badge badge-${statusClass}`}>{status}</span>;
}
.badge {
padding: 4px 8px;
border-radius: 4px;
font-weight: bold;
}
.badge-active {
background-color: #4CAF50;
color: white;
}
.badge-inactive {
background-color: #f44336;
color: white;
}
.badge-graduated {
background-color: #2196F3;
color: white;
}
With Tailwind
function StudentBadge({ status }) {
const statusClasses = {
'Active': 'bg-green-500 text-white',
'Inactive': 'bg-red-500 text-white',
'Graduated': 'bg-blue-500 text-white'
};
return (
<span className={`px-2 py-1 rounded font-semibold ${statusClasses[status]}`}>
{status}
</span>
);
}
Conditional Styling
Apply styles based on conditions.
function StudentRow({ student, isSelected }) {
return (
<tr className={isSelected ? 'selected' : 'normal'}>
<td>{student.name}</td>
<td>{student.marks}</td>
</tr>
);
}
.normal {
background-color: white;
}
.selected {
background-color: #e3f2fd;
border-left: 3px solid #2196F3;
}
Or with Tailwind:
function StudentRow({ student, isSelected }) {
return (
<tr className={isSelected ? 'bg-blue-50 border-l-4 border-blue-500' : 'bg-white'}>
<td>{student.name}</td>
<td>{student.marks}</td>
</tr>
);
}
Real Example: Teacher Card
import styles from './TeacherCard.module.css';
function TeacherCard({ teacher, onClick, isSelected }) {
const containerClass = isSelected
? `${styles.card} ${styles.selected}`
: styles.card;
return (
<div className={containerClass} onClick={onClick}>
<div className={styles.header}>
<h3 className={styles.name}>{teacher.name}</h3>
<span className={styles.experience}>{teacher.experienceYears}y</span>
</div>
<p className={styles.subject}>{teacher.subject}</p>
<p className={styles.qualification}>{teacher.qualification}</p>
</div>
);
}
export default TeacherCard;
/* TeacherCard.module.css */
.card {
border: 1px solid #ddd;
border-radius: 8px;
padding: 16px;
margin: 8px 0;
cursor: pointer;
transition: all 0.2s ease;
}
.card:hover {
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
border-color: #2196F3;
}
.card.selected {
background-color: #e3f2fd;
border-color: #2196F3;
border-left: 4px solid #2196F3;
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 8px;
}
.name {
margin: 0;
color: #333;
font-size: 16px;
font-weight: 600;
}
.experience {
background-color: #f0f0f0;
padding: 4px 8px;
border-radius: 4px;
font-size: 12px;
color: #666;
}
.subject {
margin: 4px 0;
color: #666;
font-weight: 500;
}
.qualification {
margin: 4px 0;
color: #999;
font-size: 14px;
}
When to Use Each Approach in SMS
| Scenario | Approach | Example |
|---|---|---|
| Student card styling | CSS Modules | .card { border: 1px solid #ddd; } |
| Active/inactive status badge | Inline styles or Tailwind | {status === 'Active' ? 'bg-green-500' : 'bg-red-500'} |
| Form input with error state | CSS Modules + conditional | .input.error { border-color: red; } |
| Dashboard theme (light/dark) | CSS Modules or Tailwind | Dynamic className based on theme prop |
| Attendance table row highlights | CSS Modules + isSelected | .row.selected { background-color: #e3f2fd; } |
| Fee payment status colors | Inline object map | statusColors[status] object lookup |
| Responsive student list grid | Tailwind or CSS media queries | grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 |
Which Approach to Use?
- Inline styles: Small components, dynamic styling based on props, status badges
- CSS Classes: Standard approach, full CSS features, easy to learn, recommended for teams
- CSS Modules: Medium+ projects, avoid class name collisions, maintainable at scale
- Tailwind: Fast prototyping, design consistency, team adoption, no CSS file management
For School Management System:
- Use CSS Modules (scoped, maintainable, prevents naming collisions)
- Or Tailwind (faster development, consistent design tokens)
- Avoid raw inline styles for complex styling (harder to maintain)
Responsive Design
/* CSS Classes */
.student-list {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 16px;
}
@media (max-width: 768px) {
.student-list {
grid-template-columns: 1fr;
}
}
// Tailwind
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{students.map(student => (
<StudentCard key={student.id} student={student} />
))}
</div>
Key Takeaways
- Multiple styling approaches exist
- CSS Modules prevent class name collisions
- Tailwind is fast but requires learning classes
- Responsive design is essential
- Next: useEffect for side effects
- Using
classinstead ofclassName— React needsclassName - Forgetting to scope CSS — Use modules or BEM naming
- Over-styling inline — Extract to CSS file for complex styles
- Not testing responsive — Always test on mobile
Keep CSS organized:
- One
.module.cssper component - Share utility CSS in
global.css - Use consistent naming (BEM or component-based)
Use ChatGPT, Claude, or Copilot to go deeper on React Styling. Try these prompts:
"When would you use inline styles vs. CSS modules?""What problem does CSS Modules solve?""What are the pros and cons of Tailwind CSS?""Quiz me on React styling approaches"
💡 Tip: After reading this article, paste your own code into AI and ask "What could go wrong here and why?" — fastest way to find edge cases and deepen understanding.
Quick Definitions
- Styling React Components - The main React concept explained in this lesson.
- Component - A reusable function that returns UI.
- Props/state/effects - Core React ideas used to pass data, remember data, and run side effects.
- Real project usage - How this appears in forms, dashboards, routes, and API-connected pages.
Common Mistakes
- Copying React code without understanding data flow
- Mutating arrays or objects directly instead of creating new values
- Forgetting keys, dependencies, loading states, or error states where needed
- Putting too much logic in one component
- Not testing the screen with realistic School Management System data
Practice Task
Create a small React example using Styling React Components. Keep it focused on one School Management System screen.
Suggested practice:
- Build a small component or page for students, attendance, marks, or fees.
- Pass realistic data into the component.
- Add one success state and one empty/error state where relevant.
- Explain the data flow in your own words.
- Rebuild the same example once without looking at the article.
Quick Revision
| Question | Answer |
|---|---|
| What is the main idea? | Understand and apply Styling React Components in React. |
| Where is it used? | Student dashboards, forms, tables, routes, and API-connected screens. |
| What should beginners focus on? | Clear components, predictable data flow, and small examples. |
| What is the best debugging habit? | Check props, state, render output, and browser console step by step. |
Styling React Components is a React concept used to build clear, reusable, and predictable user interfaces. I would explain the problem it solves, show a small component example, and mention a common mistake beginners should avoid.
It is used in screens like student lists, admission forms, attendance dashboards, marks reports, routing pages, and API-connected admin panels.