Styling, SEO & Context API

1. CSS, SCSS & Tailwind

Q: What is the difference between CSS, SCSS, and Sass?
Syntax and features.

Basic Implementation: Syntax Comparison

/* CSS */ .nav { background: blue; } .nav a { color: white; } /* SCSS (Sassy CSS) - Most Popular */ .nav { background: blue; a { color: white; } // Nesting } /* Sass (Indented) */ .nav background: blue a color: white

Real World Example: Mixins for Media Queries

// _mixins.scss @mixin mobile { @media (max-width: 768px) { @content; } } // Component.scss .container { width: 100%; @include mobile { padding: 10px; } }
Show Answer
  • CSS: Standard styling language. No variables (historically), no nesting.
  • Sass (Syntactically Awesome Style Sheets): A preprocessor.
    • .sass: Indentation-based syntax (no brackets/semicolons).
    • .scss (Sassy CSS): Superset of CSS. Uses brackets/semicolons. Valid CSS is valid SCSS.
  • Features: Nesting, Variables, Mixins, Functions.
Q: Why use Tailwind CSS over traditional CSS/SCSS?
Utility-first.

Basic Implementation: The Utility Approach

<!-- Traditional CSS --> <div class="chat-notification"> <div class="chat-icon"></div> <div class="chat-content">...</div> </div> <!-- Tailwind CSS --> <div class="p-6 max-w-sm mx-auto bg-white rounded-xl shadow-md flex items-center space-x-4"> <div class="shrink-0">...</div> <div>...</div> </div>

Real World Example: Responsive Design

// No media queries needed in CSS file <div class="bg-red-500 md:bg-green-500 lg:bg-blue-500"> I change color based on screen size! </div>
Show Answer

Pros:
- Speed: No context switching between HTML and CSS files.
- Consistency: Uses a design system (spacing, colors) out of the box.
- Bundle Size: Purges unused styles, resulting in tiny CSS files.
- No Naming: No more struggling to name classes like .wrapper-inner-container.

Q: What is the `@apply` directive in Tailwind?
Extracting components.

Basic Implementation: Extracting Classes

/* styles.css */ .btn-primary { @apply bg-blue-500 text-white font-bold py-2 px-4 rounded; } .btn-primary:hover { @apply bg-blue-700; }

Real World Example: When to use it?

// Use sparingly! Prefer React components for reusability: `const Button = ({ children }) => <button className="...">{children}</button>` Only use `@apply` if you are styling 3rd party HTML you can't control (like Markdown content).
Show Answer

It allows you to inline existing utility classes into your own custom CSS class. Useful when you have a repeating pattern (like a button) and want to clean up the HTML.

.btn-primary {
  @apply bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-700;
}
Q: How does CSS Specificity work?
The score (0, 0, 0, 0).

Basic Implementation: The Calculator

/* Score: 0-0-0-1 (Element) */ div { color: red; } /* Score: 0-0-1-0 (Class) */ .text-blue { color: blue; } // Wins over div /* Score: 0-1-0-0 (ID) */ #header { color: green; } // Wins over class /* Score: 1-0-0-0 (Inline) */ <div style="color: purple"> // Wins over ID

Real World Example: The `!important` Trap

// Problem: .btn { background: red !important; } // Later... .btn-blue { background: blue; } // Fails because !important overrides it. // Fix: Avoid `!important`. Increase specificity naturally: .nav .btn-blue { background: blue; }
Show Answer

It determines which rule applies when multiple rules target the same element.
1. Inline styles: (1,0,0,0)
2. IDs: (0,1,0,0)
3. Classes/Attributes/Pseudo-classes: (0,0,1,0)
4. Elements/Pseudo-elements: (0,0,0,1)
!important overrides everything (use sparingly).

Q: What is the "Box Model"?
Content, Padding, Border, Margin.

Basic Implementation: Box Sizing Reset

/* The most important CSS snippet */ *, *::before, *::after { box-sizing: border-box; } // Why? // Without this: width: 100px + padding: 20px = 140px total width. // With this: width: 100px includes the padding. Total width stays 100px.

Real World Example: Debugging Layouts

// Debugging Trick: * { outline: 1px solid red; } // Helps visualize the box boundaries of every element on the page.
Show Answer

Every element is a box.
Content: The actual text/image.
Padding: Space between content and border (inside).
Border: The edge of the box.
Margin: Space outside the border (pushes other elements away).

Tip: Always use box-sizing: border-box so padding doesn't increase the element's width.

Q: Flexbox vs. Grid?
1D vs 2D.

Basic Implementation: Flexbox (1D)

.navbar { display: flex; justify-content: space-between; // Distribute space align-items: center; // Vertical center }

Real World Example: Grid (2D)

.photo-gallery { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 16px; } // Creates a responsive grid where items are at least 200px wide, filling the row.
Show Answer
  • Flexbox: One-dimensional (Row OR Column). Best for alignment, distributing space, and small components (Navbars, Cards).
  • Grid: Two-dimensional (Rows AND Columns). Best for overall page layout and complex structures.

2. SEO & Performance

Q: How do you improve SEO in a React (SPA) application?
Crawlers and Meta tags.

Basic Implementation: React Helmet

import { Helmet } from "react-helmet";

const Page = () => (
  <div>
    <Helmet>
      <title>My Page Title</title>
      <meta name="description" content="This is a description" />
    </Helmet>
    <h1>Content</h1>
  </div>
);

Real World Example: SSR (Next.js)

// In Next.js (App Router), you export metadata:
export const metadata = {
  title: 'My Page',
  description: 'SEO optimized page',
  openGraph: {
    images: ['/og-image.png'],
  },
};
Show Answer

Problem: SPAs render content via JavaScript. Some older crawlers might see a blank page.

Solutions:

  1. Server-Side Rendering (SSR): Use Next.js or Remix to send pre-rendered HTML.
  2. Meta Tags: Use react-helmet to manage <head> tags dynamically.
  3. Sitemap & Robots.txt: Ensure crawlers know what to index.
  4. Semantic HTML: Use <header>, <main>, <article> instead of just <div>.
Q: What are Core Web Vitals?
LCP, FID, CLS.

Basic Implementation: Measuring

import { onCLS, onFID, onLCP } from 'web-vitals';

function sendToAnalytics(metric) {
  const body = JSON.stringify(metric);
  // Use `navigator.sendBeacon()` if available, falling back to `fetch()`.
  (navigator.sendBeacon && navigator.sendBeacon('/analytics', body)) ||
    fetch('/analytics', { body, method: 'POST', keepalive: true });
}

onCLS(sendToAnalytics);
onFID(sendToAnalytics);
onLCP(sendToAnalytics);
Show Answer

Google's metrics for user experience:

  • LCP (Largest Contentful Paint): Loading performance. (Target: < 2.5s)
  • FID (First Input Delay) / INP (Interaction to Next Paint): Interactivity. (Target: < 100ms)
  • CLS (Cumulative Layout Shift): Visual stability. (Target: < 0.1)

2. React Component Libraries & Best Practices

Q: Headless UI vs. Styled UI Libraries?
Radix vs MUI.

Basic Implementation: The Difference

// Styled (MUI) - Comes with styles import Button from '@mui/material/Button'; <Button variant="contained">Click Me</Button> // Headless (Radix UI) - Unstyled, just logic import * as Dialog from '@radix-ui/react-dialog'; <Dialog.Root> <Dialog.Trigger className="my-custom-btn">Open</Dialog.Trigger> <Dialog.Content className="my-modal-styles">...</Dialog.Content> </Dialog.Root>

Real World Example: Building a Design System

// You want full control over the look (Tailwind) but don't want to write accessibility logic. // Use Headless UI + Tailwind: const MyModal = () => ( <Dialog.Content className="bg-white p-6 rounded-lg shadow-xl fixed top-1/2 left-1/2 -translate-x-1/2"> <Dialog.Title className="text-lg font-bold">Edit Profile</Dialog.Title> <Dialog.Close className="absolute top-2 right-2">X</Dialog.Close> </Dialog.Content> );
Show Answer
  • Styled (MUI, AntD, Chakra): Come with pre-built styles. Fast to start, but hard to customize to match a unique design system. Heavy bundle size.
  • Headless (Radix UI, Headless UI, React Aria): Provide logic and accessibility (keyboard nav, focus management) but zero styles. You style them yourself (e.g., with Tailwind). Best for custom design systems.
Q: What is "Tree Shaking" in the context of UI Libraries?
Import cost.

Basic Implementation: Import Styles

// BAD: Imports the entire library (huge bundle size) import { Button, TextField, Modal } from 'huge-library'; // GOOD: Imports only specific files (Tree Shaking friendly) import Button from 'huge-library/Button'; import TextField from 'huge-library/TextField';

Real World Example: Bundle Analysis

// If tree-shaking fails, your vendor.js file might look like: // vendor.js (2.5MB) -> includes DatePicker, Charts, Maps... even if you only used a Button. // Solution: // 1. Use ES Modules (ESM) builds. // 2. Check `sideEffects: false` in package.json of the library.
Show Answer

The ability to include only the code for the components you actually use.
Bad: import { Button } from 'huge-lib'; (Might bundle the whole lib if not configured right).
Good: import Button from 'huge-lib/Button'; (Direct import).

Q: When should you build your own component library?
Build vs Buy.

Basic Implementation: The Wrapper Pattern

// Even if you "Buy" (use MUI), wrap it! // This allows you to swap the underlying library later without changing every page. // components/Button.js import MuiButton from '@mui/material/Button'; export const Button = ({ children, ...props }) => { return <MuiButton {...props} disableElevation>{children}</MuiButton>; };

Real World Example: Decision Matrix

// Scenario A: Internal Admin Dashboard // Priority: Speed. Design doesn't matter. // Decision: BUY (MUI, AntD). // Scenario B: Consumer-facing E-commerce Brand // Priority: Pixel-perfect brand identity, Performance. // Decision: BUILD (Headless + Tailwind).
Show Answer

Build: When you have a unique design system, need strict control over bundle size, or have specific accessibility needs not met by existing libs.
Buy (Use existing): For internal tools, MVPs, or when speed is more important than unique branding.

3. CSS & Performance

Q: What is "Critical CSS"?
Above the fold.

Basic Implementation: Inlining

<head> <!-- Critical CSS (Inlined) --> <style> body { margin: 0; font-family: sans-serif; } .hero-section { background: blue; height: 100vh; } </style> <!-- Non-Critical CSS (Loaded async) --> <link rel="stylesheet" href="/react_guide/styles.min.css" media="print" onload="this.media='all'"> </head>

Real World Example: Next.js Automatic Inlining

// Next.js automatically identifies CSS used on the initial render // and inlines it into the HTML <head> for you. // You don't do this manually in modern frameworks.
Show Answer

The minimum CSS required to render the top part of the page (above the fold). It should be inlined in the HTML <head> to prevent "Flash of Unstyled Content" (FOUC) and improve First Contentful Paint (FCP).

Q: What is "CLS" (Cumulative Layout Shift) and how does CSS affect it?
Jumping content.

Basic Implementation: The Problem

<!-- BAD: Browser doesn't know height until image loads --> <img src="hero.jpg" /> <p>Text below jumps down when image loads.</p> <!-- GOOD: Reserve space --> <img src="hero.jpg" width="800" height="400" />

Real World Example: Aspect Ratio Boxes

/* CSS Aspect Ratio */ .video-container { aspect-ratio: 16 / 9; background: #eee; /* Placeholder color */ } <!-- The box takes up space immediately, even before the video loads --> <div class="video-container"> <iframe ... /> </div>
Show Answer

A metric measuring visual stability. CSS causes it if:
- Images don't have width and height attributes (browser doesn't reserve space).
- Fonts load late and swap (FOUT), changing text size.
- Dynamic content inserts without a reserved container.

Q: CSS Animations vs. JS Animations?
Performance.

Basic Implementation: CSS Transition

.btn { transition: transform 0.2s ease; } .btn:hover { transform: scale(1.1); /* GPU optimized */ }

Real World Example: Complex Sequencing (JS)

// Framer Motion (JS based) // Use when you need physics (springs) or exit animations <motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} > Modal Content </motion.div>
Show Answer
  • CSS (Transitions/Keyframes): Run on the compositor thread (GPU). Smoother, doesn't block the main thread. Best for simple UI states (hover, modal slide-in).
  • JS (Framer Motion/GSAP): Runs on the main thread (mostly). More control, physics-based, complex sequencing. Can cause jank if main thread is busy.
Q: What is the `will-change` property?
Hinting the browser.

Basic Implementation: Syntax

.sidebar { will-change: transform; } /* Tells browser: "I'm gonna move this soon, get ready." */

Real World Example: Hover Optimization

/* Only apply when needed to save memory */ .card:hover { will-change: transform; } /* Warning: Don't apply to everything (* { will-change... }). It crashes browsers. */
Show Answer

Tells the browser that an element is expected to change (e.g., transform, opacity). The browser can optimize ahead of time (e.g., creating a new layer). Use sparingly; overuse consumes memory.

4. SEO (Search Engine Optimization) in React

Q: Why is CSR (Client-Side Rendering) bad for SEO?
Empty HTML.

Basic Implementation: View Source

<!-- What Google Bot sees in a CSR app --> <body> <div id="root"></div> <script src="bundle.min.js"></script> </body> <!-- No content, no keywords, no links to follow. -->

Real World Example: Social Sharing

// When you paste a CSR link into Slack/Twitter/Facebook: // Preview Card: [Title: React App] [Image: None] [Desc: None] // Why? Social bots do NOT run JavaScript. They only read the initial HTML.
Show Answer

In CSR (standard React), the initial HTML is empty (<div id="root"></div>). Search engine bots (crawlers) might not execute the JS to see the content, or it takes too long, leading to poor indexing.

Q: SSR (Server-Side Rendering) vs. SSG (Static Site Generation) for SEO?
Next.js strategies.

Basic Implementation: Next.js Functions

// SSR (Dynamic) export async function getServerSideProps() { const data = await fetchFromDB(); return { props: { data } }; } // SSG (Static) export async function getStaticProps() { const data = await fetchFromCMS(); return { props: { data } }; }

Real World Example: Use Case

// Product Page (Price changes often, Inventory check) -> Use SSR (getServerSideProps) // Blog Post (Content rarely changes) -> Use SSG (getStaticProps) -> Faster, served from CDN.
Show Answer
  • SSR (getServerSideProps): Generates HTML on every request. Good for dynamic data (e.g., Search Results). Great SEO.
  • SSG (getStaticProps): Generates HTML at build time. Extremely fast. Good for blogs, marketing pages. Best SEO and Performance.
Q: What are Meta Tags and how to manage them in React?
Head management.

Basic Implementation: HTML Head

<head> <title>My Page</title> <meta name="description" content="Best widgets in town" /> </head>

Real World Example: Dynamic Metadata (Next.js)

// app/products/[id]/page.js export async function generateMetadata({ params }) { const product = await getProduct(params.id); return { title: product.name, description: product.summary, openGraph: { images: [product.imageUrl], }, }; }
Show Answer

Tags like title, description, and Open Graph (OG) tags for social sharing. In React, use React Helmet (or built-in Metadata API in Next.js) to dynamically update these tags for each route.

Q: What is `robots.txt` and `sitemap.xml`?
Instructions for bots.

Basic Implementation: robots.txt

User-agent: * Allow: / Disallow: /admin Disallow: /private-dashboard Sitemap: https://mysite.com/sitemap.xml

Real World Example: Dynamic Sitemap

// You don't write sitemap.xml manually for 10,000 products. // Use a script or Next.js plugin to generate it during build: // Output: <url> <loc>https://mysite.com/product/1</loc> <lastmod>2023-10-01</lastmod> </url> ...
Show Answer
  • robots.txt: Tells crawlers which pages they can or cannot access.
  • sitemap.xml: A list of all URLs on your site to help crawlers discover content.

5. Context API (Basic to Complex)

Q: Basic: How do you create and consume a Context?
createContext, Provider, useContext.

Basic Implementation: The Pattern

const UserContext = createContext(null); const App = () => ( <UserContext.Provider value={{ name: 'Alice' }}> <Profile /> </UserContext.Provider> ); const Profile = () => { const user = useContext(UserContext); return <div>{user.name}</div>; };

Real World Example: Custom Hook Wrapper

// Always create a custom hook to consume context // This adds safety (checking if used within provider) export const useUser = () => { const context = useContext(UserContext); if (!context) { throw new Error('useUser must be used within a UserProvider'); } return context; };
Show Answer
// 1. Create
const ThemeContext = createContext('light');

// 2. Provide
<ThemeContext.Provider value="dark">
  <App />
</ThemeContext.Provider>

// 3. Consume
const theme = useContext(ThemeContext);
Q: Mid: What is the performance pitfall of Context?
Re-rendering everything.

Basic Implementation: The Mistake

const App = () => { // This object is recreated on EVERY render of App const value = { theme: 'dark', toggle: () => {} }; // So all consumers re-render, even if data didn't actually change return <Ctx.Provider value={value}>...</Ctx.Provider>; };

Real World Example: Debugging

// Use React DevTools "Profiler" // Check "Highlight updates when components render" // If typing in a search box causes the Footer to flash -> Context issue.
Show Answer

If the value passed to the Provider changes (even a new object reference), every component consuming that context will re-render. If you put your entire app state in one context, typing in a text input could re-render the whole app.

Q: Complex: How to optimize Context to prevent unnecessary re-renders?
Split it up.

Basic Implementation: Memoization

const value = useMemo(() => ({ theme, toggle }), [theme]); return <Ctx.Provider value={value}>...</Ctx.Provider>;

Real World Example: Split Contexts

// Split State and Dispatch to prevent re-renders const StateCtx = createContext(); const DispatchCtx = createContext(); // Component A only needs to read state const state = useContext(StateCtx); // Component B only needs to update state (won't re-render when state changes) const dispatch = useContext(DispatchCtx);
Show Answer
  1. Split Contexts: Separate State and Dispatch.
    ThemeStateContext (holds "dark") and ThemeDispatchContext (holds setTheme). Components that only need to toggle theme won't re-render when the theme changes.
  2. Memoize Value: Wrap the value object in useMemo.
    const value = useMemo(() => ({ state, dispatch }), [state]);
Q: Complex: Context vs. Redux - When to switch?
Frequency and Scope.

Basic Implementation: Context (Low Frequency)

// Good for: - Theme (Light/Dark) - User Auth State (Logged in/out) - Language/Locale

Real World Example: Redux/Zustand (High Frequency)

// Good for: - Real-time stock ticker - Complex dashboard with many widgets dependent on shared data - Undo/Redo functionality - Caching API responses across screens
Show Answer

Context: Best for low-frequency updates (Theme, User, Locale) or static data.
Redux/Zustand: Best for high-frequency updates (Dashboard, Real-time data) or when you need middleware, time-travel debugging, or to update state outside of React components.