The Style
Your app works. Now make it look like someone got paid to build it.
1. Global CSS
One CSS file. Every component uses it.
π§βπ» Example
App.css:
.card {
padding: 20px;
background: whitesmoke;
}import "./App.css";
function App() {
return (
<div className="card">
<h1>Bashi Academy</h1>
</div>
);
}Two things to remember: use className (not class), and these styles apply to the entire app, not just the file that imports them.
π Summary
| Task | Code |
|---|---|
| Import CSS | import "./App.css" |
| Apply a class | className="card" |
| Scope | Global (every component) |
2. CSS Modules
Global CSS has a problem. Two components both use .title:
import "./Hero.css"; // .title { color: blue }
function Hero() {
return <h1 className="title">Welcome</h1>;
}import "./Sidebar.css"; // .title { color: red }
function Sidebar() {
return <h3 className="title">Menu</h3>;
}Whichever file loads last wins. Your Hero turns red. You didn't change anything. The styles just broke. This is called a class name collision.
π The Fix
Rename .css to .module.css. Import it as an object.
Hero.module.css:
.title {
color: blue;
}import styles from "./Hero.module.css";
function Hero() {
return <h1 className={styles.title}>Welcome</h1>;
}React turns .title into .Hero_title_x7d2f. Unique. No collision. Both components keep .title in their own file. Zero conflict.
Rules:
- File must end with .module.css
- Import as object: import styles from "./Hero.module.css"
- Apply with: className={styles.title}
π Summary
| Task | Code |
|---|---|
| Create module file | Hero.module.css |
| Import module | import styles from "./Hero.module.css" |
| Apply class | className={styles.title} |
| Result | Scoped class, no collisions |
3. Inline Styles
No CSS file. You write the style directly on the element as a JavaScript object.
π§βπ» Example
<h1 style={{ color: "navy" }}>Hello</h1>Why double curly braces? The outer {} is a JSX expression. The inner {} is a JavaScript object. CSS property names use camelCase: fontSize not font-size.
The real reason inline styles exist: dynamic styling based on state.
function StatusBadge() {
const [isOnline, setIsOnline] = useState(false);
return (
<button
style={{ color: isOnline ? "green" : "red" }}
onClick={() => setIsOnline(!isOnline)}
>
{isOnline ? "Online" : "Offline"}
</button>
);
}The color changes when the state changes. No CSS file can do that.
Limitations: no hover, no media queries. Use it for quick dynamic styles, not full layouts.
When to use what
| Method | Use when |
|---|---|
| Global CSS | Base styles, resets, fonts, body background |
| CSS Modules | Component-specific styles (default choice) |
| Inline styles | Quick dynamic styles based on state |
π Summary
| Task | Code |
|---|---|
| Inline style | style={{ color: "red" }} |
| CamelCase | fontSize, not font-size |
| Dynamic style | style={{ color: isActive ? "green" : "gray" }} |
4. Component Libraries
You just spent 3 lessons writing CSS by hand. What if someone already built 200+ styled components for you? Buttons, cards, navbars, forms. Tested, responsive, accessible. You just add a CSS class.
| Library | Style | Best for |
|---|---|---|
| Bootstrap | Classic, simple, class-based | Beginners, fast prototyping |
| Material UI (MUI) | Google's Material Design | Enterprise apps, Android-style |
| Tailwind CSS | Utility classes, full control | Developers who want custom designs |
We use Bootstrap. No new components. No new syntax. Just className.
π§βπ» Setup
Install:
npm i bootstrap@5.3.8Remove the default index.css file. Then open main.jsx and replace:
import "./index.css";with:
import "bootstrap/dist/css/bootstrap.css";Test it works:
<div className="alert alert-success" role="alert">
YES! Bootstrap installed!
</div>Green box? You're in.
π Summary
| Task | How |
|---|---|
| Install | npm i bootstrap@5.3.8 |
| Import | import "bootstrap/dist/css/bootstrap.css" in main.jsx |
| Use a class | className="btn btn-primary" |
| Find components | getbootstrap.com/docs |
5. The Docs
You don't memorize Bootstrap. You shop. Open the docs, find the component, copy the code, change class to className, paste into React.
π§βπ» Components You'll Use
| Component | What It Is |
|---|---|
| Buttons | className="btn btn-primary" |
| Alerts | Colored message boxes |
| Badges | Small inline labels |
| Cards | Title, text, image, button container |
| List Group | Stacked list of items |
| Navbar | Logo, links, full navigation bar |
| Placeholders | Loading skeleton while data loads |
| Forms | Input, label, button |
The Process
Every component follows this flow:
- Open Bootstrap docs
- Find the component
- Copy the HTML
- Change class to className
- Paste into your React component
<div className="alert alert-success">
Order confirmed!
</div><div className="card" style={{ width: "18rem" }}>
<div className="card-body">
<h5 className="card-title">Suqaar</h5>
<p className="card-text">Spiced meat with vegetables.</p>
<button className="btn btn-primary">Order</button>
</div>
</div>π Summary
| Task | How |
|---|---|
| Find a component | Search the Bootstrap docs |
| Use in React | Change class to className |
| Rule | Don't memorize. Shop. |
6. The Pattern
Every Bootstrap class follows the same naming formula. Learn the formula, learn all of Bootstrap.
π§βπ» Spacing
{property}{side}-{size}
<div className="m-3">Margin all sides</div>
<div className="mt-2">Margin top</div>
<div className="px-4">Padding left + right</div>
<div className="p-5">Padding all sides</div>Property:
| Letter | Meaning |
|---|---|
| m | margin |
| p | padding |
Side:
| Letter | Meaning |
|---|---|
| t | top |
| b | bottom |
| s | start (left) |
| e | end (right) |
| x | left + right |
| y | top + bottom |
| (none) | all sides |
Size: 0, 1, 2, 3, 4, 5, auto
1 = small, 3 = medium, 5 = large.
π§βπ» Colors
Same color names work everywhere: buttons, text, backgrounds.
<button className="btn btn-primary">Save</button>
<button className="btn btn-danger">Delete</button>
<p className="text-success">Order confirmed</p>
<div className="bg-warning p-3">Warning message</div>| Color | Meaning |
|---|---|
| primary | Blue (main action) |
| secondary | Gray |
| success | Green |
| danger | Red |
| warning | Yellow |
| info | Light blue |
| light | Light gray |
| dark | Dark gray |
Works with: btn-, text-, bg-, alert-, badge bg-
π§βπ» Sizes
<button className="btn btn-sm btn-primary">Small</button>
<button className="btn btn-primary">Default</button>
<button className="btn btn-lg btn-primary">Large</button>π§βπ» Utilities
| Class | What it does |
|---|---|
| text-center | Center text |
| text-start | Align text left |
| text-end | Align text right |
| rounded | Rounded corners |
| shadow-sm | Subtle shadow |
| border | Thin border |
| w-100 | Full width |
| w-50 | Half width |
π Cheatsheet
| Category | Pattern | Example |
|---|---|---|
| Margin | m{side}-{size} | mt-3, mx-auto |
| Padding | p{side}-{size} | p-4, py-2 |
| Button color | btn btn-{color} | btn btn-primary |
| Text color | text-{color} | text-danger |
| Background | bg-{color} | bg-success |
| Button size | btn-{size} | btn-sm, btn-lg |
7. The Layout
How to arrange things on screen. Two tools: Flex for quick rows, Grid for page structure.
π§βπ» Flex
Turn any <div> into a flex container with d-flex.
<div className="d-flex justify-content-between align-items-center">
<h1>Mangio Express</h1>
<button className="btn btn-primary">Sign Up</button>
</div>Horizontal (justify):
| Class | Items go |
|---|---|
| justify-content-start | All left |
| justify-content-center | All center |
| justify-content-end | All right |
| justify-content-between | First left, last right |
Vertical (align):
| Class | Items go |
|---|---|
| align-items-start | Top |
| align-items-center | Middle |
| align-items-end | Bottom |
Gap:
<div className="d-flex gap-3">
<button className="btn btn-primary">Save</button>
<button className="btn btn-secondary">Cancel</button>
</div>π§βπ» Grid
12 columns. You pick how many each section takes. Always this order: container β row β col.
<div className="container">
<div className="row">
<div className="col-6">Left half</div>
<div className="col-6">Right half</div>
</div>
</div>Common layouts:
| Classes | Result |
|---|---|
| col-6 + col-6 | Two equal halves |
| col-4 + col-8 | Sidebar + main content |
| col-4 + col-4 + col-4 | Three equal columns |
| col + col + col | Auto equal columns |
π§βπ» Responsive
Add a breakpoint to make it stack on small screens.
<div className="container">
<div className="row">
<div className="col-sm-6">Stacks on mobile</div>
<div className="col-sm-6">Side by side on tablet+</div>
</div>
</div>| Breakpoint | Screen size |
|---|---|
| col- | Always columns |
| col-sm- | 576px+ (tablet) |
| col-md- | 768px+ (laptop) |
| col-lg- | 992px+ (desktop) |
π Cheatsheet
| Task | Classes |
|---|---|
| Flex row | d-flex |
| Space between | d-flex justify-content-between |
| Center vertically | d-flex align-items-center |
| Gap | d-flex gap-3 |
| Two columns | container β row β col-6 + col-6 |
| Responsive stack | col-sm-6 (stacks on mobile) |
| 12 columns rule | Column numbers in one row must add up to 12 |