Website Development

IIM Bangalore BBA in Digital Business and Entrepreneurship · Term 2 · 8 modules, 605 topics.

Advanced CSS and Responsive Design

Multiple Classes to HTML

Multiple classes let you apply several CSS styles to one HTML element by listing class names separated by spaces in the class attribute. This avoids creating a new class for every combination of styles, keeping the code modular and maintainable.

Intuition

Why not write a single class that does everything? Because you often need different combinations of the same basic styles (color, background, underline) across elements. Defining each style as a separate class and then combining them in the HTML lets you reuse those basic building blocks.

How it works

<p class="standard-color standard-underline standard-highlight">Text</p>

Each class refers to a rule in the CSS. The element gets the union of all rules from its classes.

Example from the lecture

Three paragraphs needed different treatments:

ParagraphStyles required
1stHighlight
2ndHighlight + Underline
3rdHighlight + Underline + Color

Without multiple classes – you would need to create a new class (e.g., .highlight-underline) and duplicate the rules.

With multiple classes – apply existing classes directly:

<p class="standard-highlight">Paragraph 1</p>
<p class="standard-highlight standard-underline">Paragraph 2</p>
<p class="standard-highlight standard-underline standard-color">Paragraph 3</p>

Benefits

  • Reusability – each class defined once, used many times.
  • Modularity – change a single rule to update every element that uses it.
  • Semantic HTML – class names describe the style, not the combination.
  • Easier maintenance – no need to hunt for duplicated rules.

Exam tip: This technique is essential for writing DRY (Don’t Repeat Yourself) CSS and will be used heavily with Flexbox, Grid, and frameworks like Bootstrap.

Key takeaways

  • Add multiple classes by separating names with a space in the class attribute.
  • Eliminates the need for combination-specific classes.
  • Reduces code duplication and improves maintainability.
  • Fundamental for modular, scalable CSS.

CSS Layouts

Layouts control how elements are arranged on the page. Older methods (tables, inline-block, floats) were not designed for the web’s responsive nature. Modern CSS provides Flexbox and Grid as purpose-built tools.

Evolution of layout methods

MethodKey ideaMajor weaknesses
TablesRows & columns for arrangementMessy HTML, no responsiveness, hard to maintain
display: inline-blockElements sit side by side with width/heightAlignment is fragile, vertical-align often fails, overflow, fixed heights break on resize
floatPush elements left or rightNever intended for layout; clearing issues, collapsing containers
FlexboxOne-dimensional (row or column) flexible layoutOnly handles one axis at a time
GridTwo-dimensional rows & columnsMore complex than Flexbox for simple cases

Demo: the pain of inline-block

A common layout – sidebar + main content – was attempted with display: inline-block.

.sidebar {
  display: inline-block;
  width: 30%;
  height: 60px;          /* forced to align tops */
  background: aqua;
}
.main-content {
  display: inline-block;
  width: 60%;
  height: 60px;
  background: lightgreen;
}

Problems encountered:

  • Alignment – the sidebar and main content did not start at the same vertical position; vertical-align: middle failed.
  • Height mismatch – fixed heights caused overflow when content grew; removing heights broke alignment again.
  • Responsiveness – fixed percentages did not adapt; on narrower screens the layout broke.
  • Spacing – margins had to be manually added; no automatic gap.

Exam tip: The demo highlights why inline-block should not be used for page layouts. Flexbox or Grid are the standard solutions.

Modern solution: Flexbox

Applying display: flex to the parent container solved almost everything in one line.

main {
  display: flex;
  gap: 30px;
}
  • Sidebar and main content automatically align at the same height (stretch by default).
  • No need for height or vertical-align.
  • The gap property creates uniform spacing.
  • Removing explicit widths causes elements to fill available space; adding width: 30% on the sidebar and letting the main take the rest works naturally.
  • The layout adapts to content length without overflow.

Real‑world usage

  • Times of India – inspected cards and found display: flex on parent containers.
  • Adidas – product listings use display: grid with grid-template-columns: 1fr 1fr 1fr and a gap.

Why it matters

Flexbox and Grid are the foundation of responsive design. Combined with media queries and frameworks like Bootstrap, they allow layouts to adapt to phones, tablets, and desktops with minimal code.

Key takeaways

  • Layouts evolved from tables → inline-block → floats → Flexbox/Grid.
  • inline-block is brittle for full-page layouts: alignment, overflow, and responsiveness are hard to control.
  • Flexbox excels at one-dimensional layouts (row or column).
  • Grid handles two-dimensional layouts with explicit row/column definitions.
  • Using display: flex on a parent instantly aligns children, handles spacing with gap, and resizes automatically.

Flexbox

Flexbox (Flexible Box Layout) gives a powerful, one-dimensional layout system for aligning and distributing space among items in a container — even when their sizes are unknown or dynamic. Instead of wrestling with floats, inline‑blocks, or positioning hacks, you set display: flex on the parent and let flex properties handle the rest. Its main strength: responsive arrangements that adapt to screen width without media queries.

The Two Axes

Every flex container has a main axis and a cross axis, determined by flex-direction:

flex-directionMain axisCross axis
row (default)Horizontal (left → right)Vertical
row-reverseHorizontal (right → left)Vertical
columnVertical (top → bottom)Horizontal
column-reverseVertical (bottom → top)Horizontal

Exam tip: Properties that align act on one axis or the other. Mixing them up is a classic trap. Remember: justify-content works on the main axis; align-items works on the cross axis.

Container (Parent) Properties

Apply these to the parent element (display: flex).

flex-direction

Sets the direction of the main axis and thus the order items are placed.

  • row (default), row-reverse, column, column-reverse

justify-content

Distributes space along the main axis.

ValueEffect
flex-startItems packed at start (default)
flex-endItems packed at end
centerItems centred
space-betweenEven space between items, none at edges
space-aroundSpace around each item (edges get half the gap)
space-evenlyEqual space everywhere

align-items

Controls alignment along the cross axis (single‑line containers).

ValueEffect
stretch (default)Items stretch to fill cross‑axis size
flex-startAligned at start of cross axis
flex-endAligned at end
centerCentred
baselineBaselines of text aligned

flex-wrap

Decides whether items wrap onto multiple lines when there isn’t enough space.

  • nowrap (default) – force all items onto one line (can overflow).
  • wrap – items break into new lines from top to bottom.
  • wrap-reverse – items wrap from bottom to top.

align-content

Works only when flex-wrap is wrap or wrap-reverse. It distributes space between flex lines along the cross axis (like justify-content does for rows).

ValueEffect
flex-startLines packed at start
flex-endLines packed at end
centerLines centred
space-betweenEven space between lines
space-aroundSpace around each line
space-evenlyEqual space everywhere

Exam tip: align-items aligns items within a single line; align-content aligns multiple lines when wrapping occurs. If flex-wrap is nowrap, align-content has no effect.

Child (Item) Properties

Apply these to the flex children (items) inside the container.

order

Controls the visual order (default 0). Higher values appear later. Items with equal order keep their HTML source order.

/* Moves .b2 to the end, even if it appears first in HTML */
.b2 { order: 1; }

align-self

Overrides align-items for a single item along the cross axis.

  • Accepts the same values as align-items (flex-start, flex-end, center, baseline, stretch).

flex-basis

Sets the initial size of an item along the main axis before any growing or shrinking. In a row layout it acts like width; in a column layout like height. It takes precedence over width (or height) but can be overridden by min‑width/max‑width.

flex-grow

A unitless number that defines how the item grows relative to siblings when there is extra space along the main axis.

  • Default 0 (no growth).
  • If all items have flex-grow: 1, they share extra space equally.
  • An item with flex-grow: 2 gets twice the growth of an item with flex-grow: 1 (not twice the total size).

flex-shrink

A unitless number that defines how the item shrinks relative to siblings when space is tight.

  • Default 1 (items shrink proportionally).
  • Setting flex-shrink: 0 prevents the item from shrinking below its flex-basis or content size.

flex (Shorthand)

Combines three properties in one declaration:

flex: <flex-grow> <flex-shrink> <flex-basis>;
/* Example: */
flex: 1 1 150px;  /* grow, shrink, basis */

Order of precedence for sizing (highest to lowest):

  1. min-width / max-width
  2. flex-basis
  3. width (or height in column)
  4. Content size (if none of the above set)

Worked Example: flex-grow in action

Six items with flex-basis: 120px inside a container:

  • .b1, .b2, .b4: flex-grow: 1
  • .b3: flex-grow: 5

After available space is distributed, each of the three grow:1 items increased by ~77 px, while .b3 increased by ~385 px (5 × 77). The final sizes:
.b1, .b2, .b4: 120 + 77 = 197px
.b3: 120 + 385 = 505px

Quick Visual: Axis and Alignment

flowchart TD
    A[Container display: flex] --> B{flex-direction?}
    B -->|row| C[Main: horizontal / Cross: vertical]
    B -->|column| D[Main: vertical / Cross: horizontal]
    C --> E[justify-content controls horizontal spacing]
    C --> F[align-items controls vertical alignment]
    D --> G[justify-content controls vertical spacing]
    D --> H[align-items controls horizontal alignment]
    E & F --> I[Flex children laid out accordingly]
    G & H --> I

Exam tip: The flex shorthand is almost always preferred over setting flex-grow, flex-shrink, and flex-basis separately. A common pattern is flex: 1 (equivalent to 1 1 0%).

Key takeaways

  • Flexbox requires display: flex on the parent.
  • flex-direction decides the main axis; all spacing/alignment properties depend on it.
  • justify-content controls main axis spacing; align-items controls cross axis (single line); align-content controls cross axis (multiple lines when wrapping).
  • order, flex-grow, flex-shrink, flex-basis, and align-self are applied to children.
  • The shorthand flex: grow shrink basis is the cleanest way to set item flexibility.
  • Use the CSS Tricks Flexbox Cheat Sheet for quick reference — even experienced developers rely on it.

CSS Grid

CSS Grid is a two-dimensional layout system designed for complex layouts that need control over both rows and columns simultaneously. Unlike Flexbox (which excels in one dimension – either a row or a column), Grid handles both with equal power.

The core idea: define a grid container (parent) and grid items (children). Using properties on the parent you create the grid structure, and using properties on the children you position or size them within that structure.


Grid Container Basics

To create a Grid layout, set the parent container’s display property to grid. The default behavior creates a single-column grid (items stack vertically).

Defining Columns and Rows

PropertyDescriptionExample
grid-template-columnsDefines the number and width of columnsgrid-template-columns: 300px 300px 200px;
grid-template-rowsDefines the number and height of rowsgrid-template-rows: 100px 100px 100px;

Values can be absolute (px, em), percentage, or fractional units (fr). The fr unit distributes available space proportionally:

grid-template-columns: 1fr 2fr 1fr;  /* second column twice as wide as the others */

Repeating Columns/Rows

Use repeat() to avoid typing the same size multiple times:

grid-template-columns: repeat(4, 1fr);  /* four equal columns */

Min and Max Sizes with minmax()

The minmax(min, max) function lets you set a flexible range for a column or row. It will never shrink below min and never grow beyond max.

grid-template-columns: 1fr minmax(100px, 1fr) 1fr;
/* The middle column is at least 100px wide, but can grow equally with the others */

Gap Between Tracks

Use gap (shorthand) or row-gap / column-gap to add spacing between grid cells.

gap: 10px 30px;   /* row-gap 10px, column-gap 30px */
/* or */
row-gap: 10px;
column-gap: 20px;

Using auto for Content-Based Sizing

A column/row set to auto will size itself to fit the content (no extra space).


Grid Lines, Cells, Tracks & Inspection

When you define a grid, the browser creates invisible grid lines that separate rows and columns. These lines are numbered starting from 1 (top-left) and also negatively from -1 (bottom-right).

  • Grid cell – the area between four adjacent grid lines (one unit of the grid).
  • Grid track – the space between two adjacent grid lines, i.e., a full row or column.
  • Grid item – a child element placed inside the grid.

Exam tip: Negative line numbers (-1, -2, etc.) let you reference the last line without knowing the total number of tracks – extremely useful for spanning to the far edge.

Chrome DevTools has a built-in Grid overlay (Layout tab → Grid) that shows lines, track sizes, and area names.


Auto Flow & Automatic Track Creation

By default, grid items flow left-to-right, top-to-bottom (row-major). This is controlled by grid-auto-flow.

  • grid-auto-flow: row (default) – fills rows first, then new rows are added.
  • grid-auto-flow: column – fills columns first, then new columns are added.

When you have more items than explicit cells, extra items create implicit tracks. Their size is controlled by:

  • grid-auto-rows – height of new rows (when flow is row)
  • grid-auto-columns – width of new columns (when flow is column)
grid-auto-rows: 100px;   /* any new row will be 100px tall */

Alignment Inside the Grid

Alignment properties work similarly to Flexbox but operate on two axes: inline (horizontal) and block (vertical).

Aligning Items Within Cells (justify-items / align-items)

These are set on the grid container and affect all items:

PropertyAxisEffect
justify-itemsHorizontal (row axis)Aligns items inside each cell
align-itemsVertical (column axis)Aligns items inside each cell

Values: start, end, center, stretch (default).

Aligning the Entire Grid (justify-content / align-content)

These move the grid tracks themselves within the container:

PropertyAxisEffect
justify-contentHorizontalDistributes tracks across the inline axis
align-contentVerticalDistributes tracks across the block axis

Values: start, end, center, stretch, space-between, space-evenly, etc.

Exam tip: *-items works inside each cell; *-content works on the whole grid. They are not interchangeable.

Per-Item Alignment (justify-self / align-self)

These are set on a grid item to override the container’s justify-items / align-items for that one item.

.item1 {
  justify-self: start;   /* align only this item left */
  align-self: end;       /* align it to bottom of its cell */
}

Positioning Grid Items

By default, each item occupies one cell. You can make items span multiple cells by specifying start and end grid lines using properties on the child.

Longhand Properties

grid-column-start: 1;
grid-column-end: -1;      /* spans all columns */
grid-row-start: 2;
grid-row-end: 4;          /* spans rows from line 2 to line 4 */

Shorthand with span

Use span <number> to indicate how many tracks to cover without specifying exact end lines.

grid-column: span 2;      /* spans 2 columns */
/* Equivalent to grid-column-start: auto; grid-column-end: span 2; */

You can also combine line numbers and span:

grid-column: 2 / span 2;  /* start at line 2, span 2 columns */
grid-row: 1 / 3;          /* start at line 1, end at line 3 */

Grid Template Areas – Visual Layout Design

Instead of manually positioning each item, you can name areas and place items into them. This creates a highly readable, visual layout.

  1. On each grid item, give it a name using grid-area:

    .header  { grid-area: header; }
    .sidebar { grid-area: sidebar; }
    .main    { grid-area: main; }
    .footer  { grid-area: footer; }
    
  2. On the grid container, define the layout with grid-template-areas:

    .container {
      display: grid;
      grid-template-columns: repeat(3, 1fr);
      grid-template-rows: 100px 1fr 100px;
      grid-template-areas:
        "header header header"
        "sidebar main   main"
        "footer footer footer";
    }
    

Each row of the string corresponds to a row in the grid. The same name repeats across columns to make an item span multiple cells. A period (.) leaves a cell empty.

Exam tip: grid-template-areas is the most intuitive way to build page layouts (e.g., header, sidebar, main, footer). It’s also easier to modify than number-based positioning.


Making Grids Responsive with autofit and autofill

Instead of hard-coding a fixed number of columns, you can let the grid decide how many columns fit the container width.

  • autofill – creates as many tracks as will fit, including empty ones (good for predictable spacing).
  • autofit – creates as many tracks as will fit, but collapses empty tracks (so items stretch to fill the space).

Use with repeat() and minmax() for a fully responsive grid without media queries:

grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
/* Each column at least 100px wide, grows equally; extra tracks are collapsed */

As the container width changes, columns adjust their count automatically. This is a CSS-only solution for fluid card layouts.


Key Takeaways

  • Set display: grid on the parent; use grid-template-columns and grid-template-rows to define structure.
  • The fr unit distributes available space proportionally. minmax() and repeat() are essential for flexible grids.
  • Grid lines are numbered positively (1,2,3…) and negatively (-1,-2,…); use them to position items precisely.
  • Alignment: *-items aligns inside cells, *-content aligns tracks inside the container. *-self overrides on a single item.
  • Grid items can span multiple cells using grid-column / grid-row with line numbers or span.
  • grid-template-areas provides a visual, easy-to-maintain layout method.
  • repeat(auto-fit, minmax(min, 1fr)) creates responsive grids without media queries.
  • Always inspect grids using Chrome DevTools Layout tab for debugging track sizes and lines.

Flexbox vs Grid: Overview

Flexbox (Flexible Box) and CSS Grid are modern layout systems that replace older methods like float and positioning. Both make it easy to create responsive designs — containers and items adjust based on available space. Both provide alignment properties along main and cross axes (e.g., justify-content, align-items for Flexbox; justify-items, align-items, justify-content, align-content for Grid).

But they differ in dimensions, control, and content flow.

Key Differences

AspectFlexboxGrid
DimensionalityOne-dimensional — lays out items in a single direction (row or column)Two-dimensional — controls both rows and columns simultaneously
ControlGreater control over individual items (grow, shrink, alignment)Control primarily at the container level (define rows, columns, then place items)
Content flowContent-driven — items adjust based on their size; layout changes dynamicallyStructure-first — define the grid, then place items into fixed tracks; layout is pre-defined
WrappingItems wrap naturally but don’t stick to exact row/column linesItems always follow the defined grid lines, even when overflowing to new rows

Live demonstration behavior

  • Grid with fixed columns (e.g., grid-template-columns: 1fr 1fr 1fr): items occupy cells in order; the seventh item wraps to the next row within the defined column structure.
  • Flexbox with flex-wrap: wrap: items flow seamlessly into new lines, but each line is independent — there’s no “row” alignment across lines. Odd numbers of items distribute space per line.

Exam tip: Flexbox is ideal for distributing a set of items along one axis and letting them wrap naturally. Grid is for aligning items across both axes in a predictable grid.

When to Use Each

  • Use Flexbox for simple one-dimensional layouts: nav bars, footers, rows of buttons, cards in a single row/column. Its strength lies in alignment and distribution along one direction (justify-content, align-items, flex-wrap).
  • Use Grid for full page layouts where you need control over both rows and columns simultaneously: header, sidebar, main content, footer. Grid defines the overall structure; items are placed into named areas.

Working Together (Complementary)

Flexbox and Grid are not mutually exclusive. Use Grid for the big picture (page structure) and Flexbox for the details (alignment within each grid cell).

Worked Example: Page Layout with Grid + Flexbox

A typical responsive page structure:

Page Container (display: grid)
├── Header (display: flex → justify-content: center, align-items: center)
├── Sidebar (display: flex → flex-direction: column, justify-content: flex-start)
├── Main Content (display: flex → flex-direction: column, align-items: center)
└── Footer (display: flex → justify-content: center, align-items: center)

Grid setup for the page container:

  • grid-template-columns: repeat(3, 1fr) — three equal columns
  • grid-template-rows: 10% auto 10% — header 10%, main content auto, footer 10%
  • grid-template-areas:
    "header header header"
    "sidebar main  main"
    "footer footer footer"
    
  • Each child gets a grid-area name matching the template.

Flexbox inside each area:

  • Header: display: flex; justify-content: center; align-items: center; gap: 2em → navigation links centered.
  • Sidebar: display: flex; flex-direction: column; justify-content: flex-start; align-items: center; padding: 10% → buttons stacked vertically.
  • Main content: display: flex; flex-direction: column; align-items: center → paragraphs centered.
  • Footer: display: flex; justify-content: center; align-items: center → centered text.

Result: a full-page layout built in seconds, responsive by default (relative units like 1fr and %).

Key Takeaways

  • Flexbox is one-dimensional; Grid is two-dimensional.
  • Flexbox is content-driven; Grid is structure-first.
  • Use Flexbox for alignment and distribution within a container; use Grid for overall page layout.
  • They complement each other: Grid for the macro layout, Flexbox for micro alignment inside cells.
  • Flexbox wraps items naturally; Grid forces items into defined rows/columns.
  • Properties like justify-content behave differently: in Flexbox it aligns items along the main axis; in Grid it aligns the entire grid tracks (use justify-items for aligning items within cells).

Media Queries

Media queries are CSS rules that apply styles conditionally based on properties of the user's device — most commonly screen width, but also orientation, resolution, and more. They are the backbone of responsive design: they let a single HTML page change layout, font sizes, visibility, and other styles at specific breakpoints (width thresholds where the page restructures).

Intuitively: a website that looks great on a 27‑inch monitor would be unusable on a phone. Media queries are the switch that flips the design at the right screen sizes — no JavaScript needed.


Syntax and Key Properties

A media query starts with @media, followed by a condition in parentheses, then a block of normal CSS rules.

@media (condition) {
  /* CSS rules go here */
}

Two width‑based conditions are most common:

ConditionMeaning (English)Logical equivalent
max-width: 750pxAt most 750 px widewidth ≤ 750px
min-width: 1200pxAt least 1200 px widewidth ≥ 1200px
(min-width: 800px) and (max-width: 1000px)Width between 800 px and 1000 px800px ≤ width ≤ 1000px

Exam tip: max-width = “up to and including”. min-width = “starting at and above”. Think of max as a ceiling and min as a floor.

Combining Conditions with and

You can write a range by joining min-width and max-width with the and keyword:

@media (min-width: 800px) and (max-width: 1000px) {
  body { background-color: brown; }
}

This style is active only when the viewport is at least 800 px AND at most 1000 px.


How Real Sites Use Breakpoints

Inspecting live responsive sites (e.g., Adidas, Mokobara) reveals multiple breakpoints:

  • At ≈1150 px: navigation restructures (menu collapses into a hamburger icon).
  • At ≈700 px: search bar moves, layout switches from multi‑column to single column.

These thresholds are defined with media queries in the site’s CSS. The design “breaks” at specific widths and reassembles — hence the term breakpoint.

flowchart LR
  A[Viewport width] --> B{Check breakpoints}
  B -->|"width ≥ 1200px"| C[4‑column grid, full nav]
  B -->|"800px ≤ width < 1200px"| D[2‑column grid, condensed nav]
  B -->|"width < 800px"| E[1‑column grid, hamburger menu]

Worked Example: Responsive Grid Layout

Goal: a grid of items that shows 4 columns on wide screens, 2 columns on tablets, and 1 column on phones.

HTML

<div class="grid-container">
  <div>1</div><div>2</div><div>3</div><div>4</div>
</div>

CSS – start with a default (any rules outside media queries apply unless overridden):

.grid-container {
  display: grid;
  justify-items: center;
}

Now add media queries targeting specific ranges:

/* Phone: max-width 750px → 1 column */
@media (max-width: 750px) {
  .grid-container {
    grid-template-columns: 1fr;
  }
}

/* Tablet: between 800px and 1000px → 2 columns */
@media (min-width: 800px) and (max-width: 1000px) {
  .grid-container {
    grid-template-columns: 1fr 1fr;
  }
}

/* Wide desktop: min-width 1200px → 4 columns */
@media (min-width: 1200px) {
  .grid-container {
    grid-template-columns: repeat(4, 1fr);
  }
}

What happens when the viewport shrinks:

  • ≥1200 px → four equal columns.
  • 800–1000 px → two columns.
  • ≤750 px → single column.
  • Gaps between breakpoints (e.g., 751–799 px) apply no media‑query rules, so the default grid-template-columns (if any) or fallback behaviour takes effect.

The same pattern is used on real e‑commerce sites like Adidas: product grids change from 4‑column → 3‑column → 2‑column at different breakpoints.

Exam tip: Avoid overlapping breakpoints. Use max-width for “up to”, min-width for “from”, and and for ranges. Plan breakpoints at natural content thresholds, not arbitrary pixel values.


Other Common Uses

  • Images – make images full‑width on mobile, side‑by‑side on desktop.
  • Typography – increase font size on larger screens.
  • Visibility – hide/show elements (e.g., a hamburger menu icon) based on width.
  • Padding and margins – reduce whitespace on small screens.

Key Takeaways

  • Media queries apply CSS only when a condition (usually viewport width) is met.
  • max-width: X = applies to widths ≤ X; min-width: X = applies to widths ≥ X.
  • Use and to combine conditions for a range: (min-width: A) and (max-width: B).
  • Breakpoints are the width values where the design restructures; inspect real sites to find common ones (e.g., 768 px, 992 px, 1200 px).
  • Media queries are purely CSS — no JavaScript required for responsive behaviour.
  • They can control grids, images, navigation, colours, and any other CSS property.

Bootstrap

A CSS framework is a box of ready-made tools – pre-written CSS components and classes that speed up styling. Bootstrap is the most widely used CSS framework, especially on older sites. Among sites that use a framework, Bootstrap dominates (Tailwind CSS is gaining on newer projects).

Adding Bootstrap via CDN

  • Copy the CDN (Content Delivery Network) link into <head> before your own stylesheet (so your custom CSS overrides Bootstrap).
  • Copy the JavaScript bundle <script> into <body> after all content – required for interactive components (dropdowns, carousels, navbars).
<!-- CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<!-- JS (at end of body) -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>

Layout Grid System

Bootstrap’s layout is based on a 12-column grid under the hood (it uses Flexbox, not CSS Grid). Three layers: container → row → col.

  • Container (.container) gives a responsive fixed-width wrapper; its max-width changes at predefined breakpoints.
  • Row (.row) is a Flexbox container with negative margins to offset column padding.
  • Column (.col) automatically takes equal width. Specify width with .col-{number} (sum to 12). Use responsive variants: .col-md-6, .col-lg-4.
BreakpointInfixContainer max-widthWindow ≤ → full width
Extra small(none)100%Always full
Smallsm540px (approx)< 576px → 100%
Mediummd720px< 768px → 100%
Largelg960px< 992px → 100%
Extra largexl1140px< 1200px → 100%
XXLxxl1320px< 1400px → 100%

The transcript only mentioned container max-width for xl as 1320px and that .container-lg becomes full-width below 960px. Breakpoint pixel values above are standard Bootstrap values; if the lecture didn't state them exactly, rely only on the stated values.

Example: three equal columns

<div class="container">
  <div class="row">
    <div class="col">Column 1</div>
    <div class="col">Column 2</div>
    <div class="col">Column 3</div>
  </div>
</div>

To control width ratios, use numbered classes: .col-4, .col-3, .col-5 (4+3+5=12). Or mix with .col-auto (width based on content).

Utility Classes

Bootstrap provides shorthand classes for spacing, borders, colors, alignment, etc. Notation: {property}{sides}-{size}.

PropertyCodeMeaning
Marginmmargin
Paddingppadding
Sidesttop
bbottom
sleft (start)
eright (end)
xleft + right
ytop + bottom
(none)all sides
Size00
10.25rem
20.5rem
31rem
41.5rem
53rem

Examples: mt-3 (margin-top 1rem), px-5 (padding-left/right 3rem), mx-auto (auto horizontal margin for centering).

Borders: .border, .border-top, .border-0, .border-primary, .border-5 (width 5px).
Colors: predefined color classes – primary (blue), secondary, success (green), danger (red), warning (orange), etc.
Alignment: text-center, justify-content-center, align-items-start, etc. (equivalent to Flexbox properties).

Components

Bootstrap ships with pre-styled components – copy HTML from the docs and modify classes.

  • Buttons: use classes .btn, .btn-primary, .btn-warning, etc.
  • Cards: .card with .card-img-top, .card-body, .card-title, .card-text, .btn.
  • Navbar: .navbar, .navbar-expand-lg, .nav-item, .nav-link. Responsive hamburger menu requires JavaScript.
  • Hero sections, forms, icons – all available as examples in the Bootstrap docs.

Exam tip: You do not need to memorise every class; learn how to navigate the documentation and copy‑paste components. The power of Bootstrap is rapid prototyping using pre‑built, professional styles.

Pros and Cons of Frameworks (like Bootstrap)

ProsCons
Fast development – no need to write complex media queriesMany classes cluttering HTML
Professional styling out of the boxHarder to achieve completely custom designs
Well-thought-out, responsive gridOver-reliance on framework can stifle learning vanilla CSS
Large community and documentationUpdating the framework may break custom overrides

Key Takeaways

  • Bootstrap is a CSS framework: a set of ready‑made classes for layouts, utilities, and components.
  • Always link via CDN: CSS in <head>, JavaScript bundle at end of <body>.
  • The grid system uses container > row > col with a 12‑column flexbox layout; responsive breakpoints control width.
  • Utility classes (m-*, p-*, border-*, etc.) replace hand‑written CSS for spacing, borders, colors.
  • Components (buttons, cards, navbar) are copied from docs and customised; interactive ones need the JS bundle.
  • Underneath, all Bootstrap styles use standard CSS properties (Flexbox, media queries, colors). Understand the fundamentals to troubleshoot and customise.

Module Summary: Advanced CSS and Responsive Design

Module 5 covered advanced CSS layout and responsiveness — specifically Flexbox, CSS Grid, media queries, and a brief introduction to the Bootstrap framework. The core expectation is to apply these tools to create a well‑structured, responsive website that works seamlessly on mobile and desktop.

Assignment: Build a Responsive Site

Students must enhance their personal resume website from Module 4 using the following techniques:

  • Layout – Use Flexbox or Grid to arrange all components across different pages.
  • Bootstrap integration – Optionally use Bootstrap components, icons, or its grid system to improve layout.
  • Responsiveness – Add media queries to ensure the site looks great on all screen sizes.

Deliverable: A responsive website that functions well on both mobile and desktop devices.

Looking Ahead

The next two modules will cover JavaScript — introducing interactivity and dynamic behaviour into websites.


Key takeaways

  • Module 5 focuses on Flexbox, Grid, media queries, and Bootstrap.
  • The assignment requires applying these tools to build a responsive resume site.
  • Responsive design (via media queries) is mandatory for mobile‑friendly layout.
  • Bootstrap components and grid are optional enhancements.
  • JavaScript (interactivity) is the next major topic.

Basics of Javascript

What JavaScript Does

JavaScript transforms a static website (HTML + CSS) into a dynamic, interactive experience. Without JavaScript, a page is like a beautiful picture: it can look good but cannot respond to clicks, update content in real time, or fetch live data. JavaScript gives instructions to HTML elements — a script that tells each part what to do and when.

Real-world examples (all require JavaScript)

  • Moneycontrol.com – interactive charts, live stock data, ads. Disabling JavaScript breaks chart rendering and removes ads.
  • Timeanddate.com – a continuously ticking clock. Without JavaScript, the time freezes on page load.
  • Flex (creative portfolio) – scroll-triggered animations, colour changes, horizontal scrolling, falling elements.
  • Mission Mass – dynamic page transformations (scroll-driven direction changes).

These sites become unresponsive or broken when JavaScript is turned off.

A brief history

  • 1995 – Netscape Navigator held >80% browser market share. Websites were static; every interaction required a server request.
  • Netscape hired Brendan Eich, who created JavaScript in 10 days. Originally called LiveScript, renamed to JavaScript to capitalise on Java’s popularity (they are completely different languages).
  • Standardised as ECMAScript (abbreviated ES). Modern versions: ES5, ES6 (and later).
  • Today, sites like Twitter, YouTube, Netflix, and most of the web depend entirely on JavaScript.

How JavaScript works

Computers understand only binary (0s and 1s). JavaScript is a programming language that acts as a translator: we write human-readable instructions (e.g., alert("Hello")), and the browser’s JavaScript engine converts those instructions into machine code.

JavaScript code        Browser engine        Machine instructions
    (human)       →     (interpreter)    →     (0s and 1s)

JavaScript is an interpreted language (runs line‑by‑line in the browser), unlike Java which is compiled.

Key takeaways

  • JavaScript makes websites interactive (live updates, click responses, animations).
  • It was created in 10 days at Netscape (1995) and standardised as ECMAScript.
  • JavaScript is not related to Java; it runs in all major browsers.
  • It translates our instructions into commands the browser can execute.

Where to write JavaScript

  1. Chrome DevTools Console – for quick one‑line tests.
    • Open: Menu → More tools → Developer tools (or right‑click → Inspect → Console tab).
    • Type alert("Hello"); and press Enter → a popup appears.
    • Use Shift+Enter to write multiple lines before executing.
  2. Chrome DevTools Snippets – for longer code that can be saved and re‑run.
    • Sources tab → Snippets (may need to click >> to find it) → New snippet.
    • Write code, save, click Run (or Ctrl/Cmd+Enter).
    • Output appears in a console at the bottom.
  3. In HTML files (later modules) – JavaScript is added via <script> tags in a .html file, run with Live Server.
ToolBest forNotes
ConsoleQuick tests, single expressionsNot saved; accidental Enter executes
SnippetsMulti‑line code, saved snippetsSaved in browser, easy to rerun
HTML <script>Full web pagesUsed in later modules for DOM

First command: alert()

alert("Hello");
alert("Hi");
alert("Hello boss");
  • alert – a built‑in keyword that calls a function (technically window.alert()).
  • Parentheses () – hold the argument (the message).
  • Quotation marks " " or ' ' – enclose a string (text).
  • Semicolon ; – marks the end of an instruction (like a full stop). Always include it.

If you type an invalid command, e.g., sayHi, the browser returns:
Uncaught ReferenceError: sayHi is not defined

Using MDN documentation

To verify valid JavaScript commands and learn details, search MDN JavaScript (Mozilla Developer Network).
Example: search “MDN alert” to see the full specification, variants like open(), focus(), prompt(), etc.

Exam tip: alert() is a method of the window object, but you can write just alert(). Semicolons are optional in many cases, but using them consistently prevents errors.

Key takeaways

  • Use Chrome DevTools Console for one‑liners, Snippets for longer code.
  • alert() syntax: keyword alert, parentheses, quoted message, semicolon.
  • Semicolon ends a statement.
  • Use MDN as the authoritative reference for JavaScript methods and syntax.

Data Types in JavaScript

Data types define the kind of value a variable can hold — like a water bottle holds water, a box holds toys. In JavaScript, every value has a type, and knowing the type tells you what operations you can perform.

String

A string is a sequence of characters used to represent text. Strings are enclosed in single quotes ('), double quotes ("), or backticks (`).

"Govind"        // double quotes
'IIM Bangalore' // single quotes
`IIMB space`    // backticks
''              // empty string - still a string
"1234"          // digits in quotes - still a string
  • Strings can contain letters, numbers, symbols, and special characters (e.g., \n for newline).
  • Useful for messages, user input, and joining text (concatenation).

Number

A number represents numeric values — integers and decimals alike. JavaScript treats all numbers as the same type (no separate integer/floating distinction).

25
4.5
  • Arithmetic operations (+, -, *, /) work on numbers.
  • If you wrap digits in quotes (e.g., "25"), they become a string, not a number.

Boolean

A boolean has only two possible values: true or false. It is used for decisions and conditional logic.

true
false
  • Often results from comparisons (e.g., 5 > 3true).

The typeof Operator

Use the typeof operator to check the data type of a value. It is an operator, not a function — no parentheses needed.

typeof "hello"   // "string"
typeof 42        // "number"
typeof true      // "boolean"
typeof ""        // "string"
typeof "1234"    // "string" (because quoted)

Exam tip: typeof is an operator, not a function. Common mistake: writing typeof(x) — while it works, the correct form is typeof x. Prefer the operator form.

Why Data Types Matter

  • Operations behave differently per type: adding numbers sums them; adding strings joins them.
  • Knowing the type helps avoid bugs, especially when data comes from user input or external APIs.
  • typeof is your first debugging tool to confirm what you're working with.

Key takeaways

  • String – text in quotes ("", '', backticks).
  • Number – any numeric value (no separate integer/decimal).
  • Booleantrue or false.
  • typeof – operator to return the type as a string.
  • Same literal (e.g., 25 vs "25") can be number or string depending on quotes.

Variables in JavaScript

A variable is a labelled container that stores a value so you can reuse or change it later. Think of it as a box with a label, or a tentacle that grabs a value and can later grab a different one.

Declaring Variables

Three keywords create variables:

KeywordUse caseCan reassign?
letModern, value may changeYes
varOlder style, similar to let but different scopeYes
constValue must stay constantNo (error on reassignment)

Syntax: keyword variableName = value;

let name = "Govind";      // declare + assign
let month = "January";
const birthYear = 1990;   // cannot change later
var price = 200;          // older way
  • Variable names should be meaningful (city not x).
  • Use let by default in modern code; use const when the value is fixed.

Assignment and Reassignment

  • Declaration creates the variable (using let, var, or const).
  • Assignment gives it a value with =.
  • Reassignment changes the value without repeating the keyword.
let city = "Mumbai";
city = "Bangalore";   // reassign – no let/var/const

With const, reassignment throws an error:

const name2 = "Govind";
name2 = "Raj";   // ❌ TypeError: Assignment to constant variable

Reading Variable Values

Use the variable name anywhere you need its value:

let age = 99;
age;            // → 99

console.log() – Viewing Values

The console.log() function prints values to the console. It accepts literals (in quotes) or variable names (without quotes).

let greeting = "Hello, welcome!";
console.log(greeting);            // prints the variable's value
console.log("Hello");             // prints a string literal
console.log(10);                  // prints a number
  • Essential for debugging and understanding what your code is doing.

Undefined Variables

Referencing a variable that was never declared causes a ReferenceError:

console.log(country);   // ❌ country is not defined

Declare it first:

let country = "India";
console.log(country);   // → India

Key takeaways

  • Variables are containers; declare with let, var, or const.
  • let and var allow reassignment; const does not.
  • Syntax: let name = value; – keyword, name, =, value, semicolon.
  • Reassign without repeating the keyword: name = newValue;
  • console.log() prints values — use it for debugging.
  • Accessing an undeclared variable throws an error.

Variables with Alert and Prompt

Alert and prompt are built‑in browser functions that let a JavaScript program communicate with the user.
Alert displays a message (popup with an OK button). Prompt asks for input and returns whatever the user types.

Intuition: you want a tiny conversation — ask the user something, store their answer, then respond using that answer.

Syntax

alert("Your message here");
let variableName = prompt("Question for the user");
  • alert – takes one string argument; shows the string in a pop‑up.
  • prompt – takes one string argument (the question); returns the string the user typed (or null if cancelled).

Worked Example – Greet the User

let username = prompt("What is your name?");
alert("Hi " + username + ", welcome to this course.");

Flow:

flowchart LR
  A[User types name] --> B[Value stored in username]
  B --> C[alert combines text + username]

If the user enters “Shahrukh”, the alert shows: Hi Shahrukh, welcome to this course.

String Concatenation

The + operator joins (concatenates) strings together.
"Hi " + username + ", welcome" becomes one continuous string.

Exam tip: When a variable holds a number (e.g. from prompt), it is actually a string by default. Concatenation still works, but be aware that "5" + 3 = "53" (string), not 8.

Second Example – Age

let age = prompt("What is your age?");
alert("Wow, you are " + age + " years old.");

You can reuse the same variable in multiple places:

alert("Wow " + username + ", you are " + age + " years old.");

Key Takeaways

  • alert displays a message; prompt gets user input.
  • prompt returns a string; store it in a variable for later use.
  • Use + to concatenate strings and variables.
  • Combining prompt and alert creates simple interactive programs.
  • Variables become dynamically assigned – their value comes from user input at runtime.

Variable Naming Rules and Camel Case

Good variable names make code readable and maintainable. JavaScript has strict rules and community conventions.

Allowed Characters

  • Letters (a–z, A–Z)
  • Digits (0–9) – but cannot start with a digit
  • Underscore (_) and dollar sign ($) – avoid both at the start (underscore has special meaning in many contexts)
let name = "Govind";         // valid
let NAME = "Raj";            // different variable (case‑sensitive)
let name123 = "Lakshmi";     // valid
let 1name = "error";         // ❌ SyntaxError

What to Avoid

RuleWhy
No special characters (@,#,%)Cause syntax errors
No spaceslet user age → unexpected number
No JavaScript reserved wordslet, const, function, if, etc.
No starting with _ (convention)Reserved for internal/protected properties
No starting with a digitIllegal token

Exam tip: Reserved words include break, case, catch, class, const, continue, debugger, default, delete, do, else, export, extends, finally, for, function, if, import, in, instanceof, let, new, return, super, switch, this, throw, try, typeof, var, void, while, with, yield. Never use them as variable names.

Case Sensitivity

name and NAME are two different variables. JavaScript is case‑sensitive.

Lower Camel Case (Recommended Convention)

Start with a lowercase letter; capitalise the first letter of each subsequent word.

let userName = "Govind";      // camelCase
let userAge = 21;
let cityOfResidence = "Mumbai";
let workOfArt = "picasso";

Without camelCase: workofart could be misread as work of art or workof art.
With camelCase: workOfArt is instantly clear.

Best Practices

  • Descriptivelet totalItems instead of let x.
  • Concise – avoid overly long names like totalNumberOfElementsInCart; use totalItems.
  • Consistent – stick to camelCase throughout your project.
  • Meaningful – the name should indicate what data the variable holds.

Dynamic Typing

JavaScript does not require you to declare a data type. The type is determined by the assigned value – and can change later.

let age = 25;          // number
age = "twenty five";   // now string – no error

This flexibility is powerful but can cause bugs. Clear naming helps you (and others) keep track of what type is expected.

Key Takeaways

  • Variable names: letters, digits (not first), _, $. No spaces, no reserved words.
  • Case‑sensitivemyVarmyvar.
  • Use lower camelCaseuserName, totalPrice.
  • Be descriptive yet concise.
  • JavaScript is dynamically typed – same variable can hold different types.

Variable Reassignment

Variable reassignment means giving a new value to a variable that already exists. A variable’s value can be changed at any time, and assigning one variable to another copies the current value (for primitive types like strings and numbers). This is a foundational concept for understanding how JavaScript stores and manages data in memory.

Swapping values

A classic task is swapping the values of two variables (e.g., cup1 = "coffee", cup2 = "tea" → swap so cup1 holds "tea" and cup2 holds "coffee").

Method 1: using a temporary (third) variable

  1. Store the value of cup1 into a third variable cup3.
  2. Assign cup1 the value of cup2.
  3. Assign cup2 the value of cup3.
let cup1 = "coffee";
let cup2 = "tea";
let cup3;                     // empty cup

cup3 = cup1;   // cup3 = "coffee"
cup1 = cup2;   // cup1 = "tea"
cup2 = cup3;   // cup2 = "coffee"

After the swap: cup1"tea", cup2"coffee", cup3 still holds "coffee".

How copying works: When we wrote cup3 = cup1, the value "coffee" was copied into cup3. Changing cup1 later (e.g., cup1 = "juice") does not affect cup3 – each variable has its own independent memory slot.

Method 2: arithmetic swap (numbers only)

For numeric variables, values can be swapped without an extra variable using addition and subtraction.

let x = 5, y = 10;

y = x + y;   // y = 5 + 10 = 15
x = y - x;   // x = 15 - 5 = 10
y = y - x;   // y = 15 - 10 = 5

console.log(x, y); // 10, 5

Why it works: The trick uses the sum as a temporary storage. After the first step, y holds the sum (x + y); then x becomes the original y (sum – original x), and finally y becomes the original x (sum – new x).

Exam tip: The arithmetic swap is a clever trick but only works for numbers (and can fail with very large values causing overflow, or with floats). In real code, use a temporary variable – it’s clearer and works for any type.

Key insight: primitive values are copied, not referenced

When you assign let a = b for primitive values (strings, numbers, booleans, null, undefined, Symbol, BigInt), JavaScript copies the value. The two variables become completely independent:

let x = 2;
let y = x;   // y = 2 (a copy)
x = 10;      // x changes, but y remains 2
console.log(y); // 2

This applies to the cup example: after the swap, cup3 still holds "coffee". If you later write cup3 = "juice", cup2 does not change.

Contrast with objects: (Out of scope for this lecture, but note that objects and arrays are stored by reference, not copied.)

Key takeaways

  • Assigning a primitive variable to another copies the value – each variable has its own memory slot.
  • Swapping values can be done with a temporary variable (any type) or with arithmetic (numbers only).
  • After a copy, modifying one variable does not affect the other.
  • The arithmetic swap trick is efficient but limited – know it as an exercise, but prefer the temp-variable method in practice.

Strings: Indexing, Properties, Concatenation

A string is an ordered sequence of characters used to represent text. In JavaScript, strings can be written with double quotes (" "), single quotes (' '), or backticks (` `). All are equivalent – the choice is stylistic.

Indexing and Bracket Notation

Computers count positions starting at zero – this is zero-based indexing.

Take let greeting = "Hello".
The character–index mapping:

CharacterIndex
H0
e1
l2
l3
o4

To retrieve a character, use bracket notation: string[index].

  • greeting[0]"H"
  • greeting[1]"e"
  • greeting[4]"o"

If the index exceeds the last valid position, JavaScript returns undefined – no error is thrown, the program continues.

  • greeting[99]undefined

Exam tip: Accessing out-of-bounds always gives undefined, not an error. This is a frequent interview and exam question.

The .length Property

The length property returns the total number of characters in the string. It is a property, not a method – no parentheses.

  • "Hello".length5
  • The highest valid index is always length - 1 (here, 4).

Because indexing starts at zero, length is one greater than the last index. For "Simran" (6 characters), Simran.length = 6 and Simran[5] = "n".

Concatenation and Type Coercion

Strings can be joined with the + operator – this is concatenation.

"Raj" + " Simran"   → "Raj Simran"

When a string and a number are added, JavaScript performs type coercion: it converts the number to a string before concatenating.

  • "1" + 1"11" (string)
  • "Hello" + 42"Hello42"

This can lead to unexpected results:

ExpressionResultExplanation
"1" + 1"11"Number 1 coerced to string
1 + "1""11"Same coercion
1 + 1 + "2""22"Left-to-right: 1+1=2, then 2 + "2" = "22"
"2" + 1 + 1"211"Left-to-right: "2" + 1 = "21", then "21" + 1 = "211"

Exam tip: Avoid mixing strings and numbers in the same expression. If concatenation is intended, convert numbers manually with String(n) or .toString() to make intent clear.

Immutability

Strings are immutable – once created, their individual characters cannot be changed by assigning to an index.

let animal = "cat";
animal[0] = "b";          // no error, but does nothing
console.log(animal);      // still "cat"

To modify a string, you must reassign the entire variable:

animal = "bat";           // works

This applies to all string manipulations – any operation that appears to change a string actually returns a new string.

Key takeaways

  • Strings are zero-indexed; use str[i] to access characters.
  • Out-of-bounds indexing yields undefined, not an error.
  • .length gives the character count (not the highest index).
  • + joins strings; mixing numbers and strings causes type coercion — be explicit.
  • Strings are immutable – direct character assignment fails; reassign the whole string.

String Methods

String methods are functions attached to string objects that perform actions on text — converting case, trimming whitespace, searching, extracting, replacing, and more. Unlike string properties (e.g., .length), methods do work and always end with parentheses (). Most string methods do not modify the original string; they return a new string instead.

Syntax

string.method(arg1, arg2, ...)
  • string can be a variable or a string literal.
  • The parentheses may contain optional arguments — values that control the method's behaviour.

Common string methods at a glance

MethodWhat it doesReturns
.toUpperCase()Converts all characters to uppercase.New string
.toLowerCase()Converts all characters to lowercase.New string
.trim()Removes whitespace from both ends.New string
.indexOf()Finds the first index of a substring (search from start).Number or -1
.slice()Extracts a part of the string (by index).New string
.replace()Replaces the first occurrence of a substring with another.New string
.repeat()Repeats the string a specified number of times.New string

Exam tip: .indexOf returns -1 when the substring is not found — a common bug if you forget to check for that.


1. Changing Case: .toUpperCase() and .toLowerCase()

Intuition: Convert text to all caps or all lowercase, e.g., for normalising user input.

Examples (from lecture):

let name = "govind";
console.log(name.toUpperCase());     // "GOVIND"
console.log(name);                   // "govind" (original unchanged)

let shout = "Hello!";
console.log(shout.toLowerCase());    // "hello!"

2. Cleaning Whitespace: .trim()

Intuition: Remove accidental spaces before/after user input — common in form data.

Behaviour: Removes spaces, tabs, newlines from both ends. Returns a new string.

let badInput = "   hello world   ";
let clean = badInput.trim();
console.log(clean);          // "hello world"
console.log(badInput);       // "   hello world   " (unchanged)

3. Searching: .indexOf(substring, start?)

Intuition: Find where a piece of text first appears inside a string. Useful for checking existence or extracting from a known point.

  • Returns the index (0-based) of the first occurrence of substring.
  • The optional second argument – start – tells the method to begin searching from that index.
  • Returns -1 if substring is not found.

Examples:

let paragraph = `I think Ruth's dog is cuter than your dog.`;

console.log(paragraph.indexOf("T"));         // 2
console.log(paragraph.indexOf("TH"));        // 2
console.log(paragraph.indexOf("dog"));       // 13
console.log(paragraph.indexOf("dog", 14));   // 37 (starts searching from index 14)
console.log(paragraph.indexOf("cat"));       // -1 (not found)

4. Extracting a Substring: .slice(start, end?)

Intuition: Cut out a portion of a string by index — like a pair of scissors for text.

  • If only start given: returns from that index to the end.
  • If start and end given: returns from start up to but not including end.
  • Negative indices count from the end of the string (-1 = last character).

Examples:

let paragraph = "I think Ruth's dog is cuter than your dog.";

console.log(paragraph.slice());         // whole string
console.log(paragraph.slice(5));        // "nk Ruth's dog is cuter than your dog."
console.log(paragraph.slice(5, 10));    // "nk Ru"
console.log(paragraph.slice(-2));       // "g."
console.log(paragraph.slice(-10));      // " your dog."

Exam tip: .slice() does not modify the original string — always store the result in a new variable.


5. Replacing Text: .replace(search, replacement)

Intuition: Find a specific substring and swap it with something else. Only the first match is replaced.

  • search: the substring (or regex) to look for.
  • replacement: the new string to put in its place.

Examples:

let paragraph = "I think Ruth's dog is cuter than your dog.";
let newPar = paragraph.replace("dog", "cat");
console.log(newPar);      // "I think Ruth's cat is cuter than your dog."
                          // Only the first "dog" changed.

// Replace only part of a word
let partial = paragraph.replace("do", "DE");
// "I think Ruth's DEg is cuter than your dog."

For advanced replacements (all occurrences, case-insensitive), use regular expressions.


6. Repeating Text: .repeat(count)

Intuition: Generate a string repeated count times – useful for padding, ASCII art, or test data.

console.log("ha".repeat(3));   // "hahaha"

Chaining Methods

Because each method returns a new string, you can call another method on the result — forming a method chain. This makes code concise.

Without chaining:

let corrected = badInput.trim();
let upper = corrected.toUpperCase();

With chaining:

let best = badInput.trim().toUpperCase();
console.log(best);    // cleaned and uppercased, all in one line

The order matters: first trim, then uppercase (or vice versa – both work here).


Key Takeaways

  • String methods are called with parentheses; properties (like .length) are not.
  • Most methods return a new string and leave the original untouched – always capture the result in a variable.
  • .indexOf returns -1 when not found.
  • .slice(start, end) does not include the character at end.
  • .replace only replaces the first match (use regex for global).
  • Method chaining lets you combine multiple operations in one expression.
  • MDN Web Docs is the authoritative reference for all string methods – bookmark it.

String Template Literals

Template literals are a cleaner, more readable way to create strings in JavaScript when you need to embed variables or expressions. Instead of glueing pieces together with +, you use backticks (`) and placeholders written as ${ ... }.

The problem: concatenation

let name = "Govind";
let age = 99;
let city = "Bangalore";
let country = "India";

alert("Hi " + name + " from " + city + ", " + country + "! Welcome here to our tutorial.");

This works, but:

  • Hard to read and write – many + signs and manual spacing.
  • Adding apostrophes or special characters forces quote changes.
  • Long strings become error‑prone.

Template literal syntax

Use backticks instead of single or double quotes. Inside, any ${ expression } is evaluated and converted to a string automatically.

alert(`Hi ${name} from ${city}, ${country}! Welcome here to our tutorial.`);
FeatureOld concatenationTemplate literal
Quote style' or "` (backtick)
Variable insertion"..." + var + "..."`${var}`
Expression insertionMust pre‑compute`${2 + 4}`"6"
Multi‑line stringsNeed \nJust press Enter inside backticks

Exam tip: Template literals only work with backticks. Using single or double quotes will treat ${...} as literal text, not an expression.

Embedding any expression

Anything inside ${ } is a valid JavaScript expression – variables, arithmetic, function calls, even conditional logic. The result is coerced to a string.

let price = 25;
alert(`The price for ${ask} is $${price}.`);   // → The price for eggs is $25.

To include a literal dollar sign, write $ before the placeholder – only ${ triggers evaluation.

Multi‑line strings

Template literals preserve line breaks. No \n needed.

alert(`Hi
Yes`);
// Output:
// Hi
// Yes

Key takeaways

  • Template literals use backticks (`) and ${...} placeholders.
  • They replace cumbersome + concatenation.
  • Any expression inside ${} is evaluated and string‑coerced.
  • Multi‑line content is natural – just hit Enter.
  • Always use backticks; single/double quotes do not support template syntax.

Null and Undefined

Both represent “nothing” but are used in different scenarios.

ConceptWho sets it?Meaningtypeof
undefinedAutomatically by JavaScriptA variable has been declared but not assigned; a missing property."undefined"
nullExplicitly by the programmer“I intend to leave this empty.”"object" (historical quirk)

Undefined

JavaScript assigns undefined when something hasn’t been defined yet.

let x;
console.log(x);   // undefined

Also appears when:

  • Accessing a non‑existent array index: "abc"[10]undefined
  • A function returns nothing: function f() {}undefined

Null

You assign null to indicate a variable is intentionally empty.

let y = null;
console.log(y);   // null
typeof y;         // "object"  (this is a long‑standing JS bug, but testable)

Exam tip: null is an object type in JavaScript – a historical mistake. undefined is its own type. They are loosely equal (null == undefinedtrue) but strictly not equal (null === undefinedfalse).

When to use each

  • Use null when you want to explicitly say “no value here” (e.g., future assignment, cleared data).
  • Let JavaScript give you undefined when something is missing – you do not usually assign undefined yourself.

Key takeaways

  • null is programmer‑set; undefined is JS‑set.
  • typeof null"object"; typeof undefined"undefined".
  • Both mean “nothing”, but context matters.
  • Loosely equal (==), but strict equality (===) is false.

Numerical Operators

JavaScript provides arithmetic operators to perform basic math on numbers. Intuition: these work like a calculator but live inside code, operating on variables or literal values.

Arithmetic Operators

OperatorNameExample (x=10, y=20)Result
+Additionx + y30
-Subtractionx - y-10
*Multiplicationx * 550
/Divisiony / 54
**Exponentiation (power)x ** 2100
%Modulus (remainder)10 % 31

Modulus is especially useful for checking divisibility — e.g., a number is even if number % 2 === 0.

Order of Operations (Operator Precedence)

JavaScript follows the same precedence as standard math: Parentheses → Exponents → Multiplication/Division → Addition/Subtraction (PEMDAS / BODMAS). Evaluation is left-to-right for operators of equal precedence.

flowchart LR
  A[Expression] --> B{Parentheses first?}
  B -->|Yes| C[Evaluate inside ()]
  C --> D
  B -->|No| D[Exponents **]
  D --> E[* / % left to right]
  E --> F[+ - left to right]
  F --> G[Result]

Best practice: Use parentheses () to make intent explicit, even when precedence is clear.

  • (5 + 2) * 3 → clearly first add, then multiply.
  • 5 + 2 * 311 (multiply first: 2*3=6, then 5+6=11).

Special Operators

Increment (++) and Decrement (--)

  • Increase or decrease a variable by exactly 1.
  • Only work on variables (not on literals like 5++).
  • Modify the variable in place.
let x = 10;
x++;  // x becomes 11
x--;  // x becomes 10 again

Compound Assignment Operators

Used to modify a variable by a larger amount concisely.

OperatorEquivalent toExample (starting x=10)
x += 4x = x + 4x14
x -= 5x = x - 5x5
x *= 2x = x * 2x20
x /= 2x = x / 2x5

Exam tip: ++ and -- change the variable itself — they are not expressions that return a new value (though they can be used in expressions; prefix vs. postfix matters, but this lecture only covers the basic postfix form).

Worked Example: Check if a number is even

let num = 21;
if (num % 2 === 0) {
  console.log("even");
} else {
  console.log("odd");
}
// Output: odd

Key takeaways

  • Six core arithmetic operators: +, -, *, /, **, %.
  • Use % to get remainder; num % 2 === 0 tests evenness.
  • Order: Parentheses → Exponents → MD → AS. Use parentheses for clarity.
  • ++ and -- increment/decrement by 1 on variables.
  • Compound assignment (+=, -=, *=, /=) shortens x = x op value.

Math Object

The Math object is a built-in JavaScript collection of properties (constants) and methods (functions) for common mathematical operations. Intuition: you don't have to write your own square root or PI — the browser gives them to you.

Access via Math (capital M) followed by a dot and the property/method name.

Properties (constants)

PropertyValue
Math.PI3.141592653589793

Methods

Rounding

MethodBehaviourExampleResult
Math.round(x)Rounds to nearest integerMath.round(3.43)3; Math.round(5.55)6
Math.floor(x)Rounds down to lower integerMath.floor(5.9999)5
Math.ceil(x)Rounds up to higher integerMath.ceil(3.43)4

Other Common Methods

MethodPurposeExampleResult
Math.abs(x)Absolute value (removes sign)Math.abs(-1)1
Math.sqrt(x)Square rootMath.sqrt(4)2
Math.pow(base, exp)Exponentiation (base**exp)Math.pow(2,3)8
Math.random()Random decimal between 0 (inclusive) and 1 (exclusive)Math.random()e.g. 0.732

Generating Random Integers (Worked Example)

Goal: a random integer between 1 and 10 (inclusive).

function getRandomInt(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}
// Simplified for 1–10:
let rand = Math.floor(Math.random() * 10) + 1;

Why it works:

  1. Math.random()0.0 to 0.999...
  2. Multiply by 10 → 0.0 to 9.999...
  3. Math.floor() → integer 0 to 9
  4. Add 1 → integer 1 to 10

Exam tip: to get a random integer in [min, max], the general formula is Math.floor(Math.random() * (max - min + 1)) + min.

Practical Example: Circumference of a Circle

let radius = 25;
let circumference = 2 * Math.PI * radius;
console.log(circumference); // 157.07963267948966

Chaining Methods

Methods can be nested, executed inside-out:

let result = Math.floor(Math.sqrt(Math.abs(-999)));
// 1. Math.abs(-999) → 999
// 2. Math.sqrt(999) → 31.606...
// 3. Math.floor(31.606) → 31
console.log(result); // 31

Key takeaways

  • Math.PI gives π.
  • Three rounding methods: round (nearest), floor (down), ceil (up).
  • abs, sqrt, pow are standard math helpers.
  • Math.random() returns [0,1); use Math.floor(Math.random() * N) + 1 for integers 1..N.
  • Chaining methods works inside-out; keep code readable with parentheses.

Logical Operators

Logical operators let you combine multiple conditions into a single expression that evaluates to true or false. They are the building blocks of decision‑making in JavaScript — everything from showing a cart count (“1 item” vs. “0 items”) to checking whether a user meets all requirements for a license.

Before understanding logical operators, you must master comparison operators, which compare two values and return a boolean.

Comparison operators

OperatorMeaningExampleResult
<Less than3 < 4true
>Greater than3 > 4false
<=Less than or equal to10 <= 10true
>=Greater than or equal to9 >= 10false
==Loose equality (type coercion allowed)10 == '10'true
===Strict equality (type must also match)10 === '10'false
!=Loose inequality10 != '10'false
!==Strict inequality10 !== '10'true

Loose equality (==) coerces one value to match the other’s type (e.g., string '10' becomes number 10). This can lead to surprising results:

'' == 0     // true (empty string is coerced to 0)
false == 0  // true

Exam tip: Always prefer strict equality (===) and strict inequality (!==) in your code. They behave predictably because they do not perform type coercion. Loose equality is rarely needed and often a source of bugs.

Logical operators — truth tables

JavaScript provides three logical operators: AND (&&), OR (||), NOT (!).

ABA && BA || B!A
truetruetruetruefalse
truefalsefalsetruefalse
falsetruefalsetruetrue
falsefalsefalsefalsetrue
  • && (AND)true only when both sides are true.
  • || (OR)true when at least one side is true.
  • ! (NOT) → inverts the boolean value.

Short‑circuit evaluation

&& stops evaluating as soon as it finds a falsy operand. || stops as soon as it finds a truthy operand. This is important for performance and for avoiding side effects, but for now focus on the boolean result.

Worked examples

1. Driving license eligibility (AND)

let age = 25;
let hasLL = true; // has learner's license
let eligible = (age >= 18) && (hasLL === true);
console.log(eligible); // true

If either condition fails (e.g., age = 17 or hasLL = false), the result is false.

2. Club entry (OR)

let age = 9;
let hasSpecialPermit = true;
let allowed = (age > 10) || (hasSpecialPermit === true);
console.log(allowed); // true (permit overrides age)

Only when both are false (age <= 10 and no permit) the result is false.

Comparing strings with logical operators

Strings can be compared with <, >, <=, >=. JavaScript compares them character by character based on their Unicode code points.

'B' > 'A'   // true (Unicode 66 > 65)
'a' > 'A'   // true (97 > 65)

Capital letters have lower Unicode values than lowercase letters, so 'A' < 'a' is true. This can be unintuitive — always test string comparisons in your specific context.

Key takeaways

  • Logical operators (&&, ||, !) combine or invert booleans; understand their truth tables.
  • Comparison operators (<, >, <=, >=, ===, !==) return booleans; always prefer strict equality (=== / !==) over loose equality.
  • Loose equality ( == ) coerces types — can produce unexpected results like '' == 0.
  • Strings are compared by Unicode values: 'A' < 'a', 'B' > 'A'.
  • Practise combining conditions with && and || to solve real‑world eligibility checks (age + license, special permit, etc.).

Conditional Statements

Conditional statements allow code to execute only when a condition evaluates to true. They control the flow of execution based on variable states or logical checks — the program decides what to run, when.

The if Statement

Syntax:

if (condition) {
  // code runs if condition is true
}
  • if is a keyword; condition must be a boolean (true / false).
  • Curly braces {} form a block; no semicolon after the closing brace.
  • Statements before and after the if block always execute in normal top‑to‑bottom order.

Example – hot day check:

let temperature = 31;
if (temperature > 30) {
  console.log("This is a hot day");
}

Output: "This is a hot day" only when temperature > 30.

if…else if…else Chain

For multiple conditions, use else if and optionally a final else as a default.

Syntax:

if (condition1) {
  // block A
} else if (condition2) {
  // block B
} else if (condition3) {
  // block C
} else {
  // default – runs if no condition above is true
}

Execution rule: Only the first block whose condition is true executes; all subsequent conditions are skipped. else runs only if no preceding condition is true.

Example – temperature classifier:

let temperature = 21;
if (temperature < 20) {
  console.log("Normal day");
} else if (temperature < 25) {
  console.log("Kind of hot day");
} else if (temperature < 30) {
  console.log("Hot day");
} else {
  console.log("Crazy hot day");
}
  • 21 → first condition false, second true"Kind of hot day".
  • 100 → all three else if conditions false"Crazy hot day".
flowchart TD
    A[Start chain] --> B{Condition1?}
    B -->|true| C[Execute block1]
    B -->|false| D{Condition2?}
    D -->|true| E[Execute block2]
    D -->|false| F{Condition3?}
    F -->|true| G[Execute block3]
    F -->|false| H[Execute else block]
    C --> I[End of chain]
    E --> I
    G --> I
    H --> I

Example – marks grading:

let marks = 95;
if (marks > 95) {
  alert("Excellent marks");
} else if (marks > 80) {
  alert("Great marks");
} else {
  alert("You can do better");
}

With 95: first condition false, second true"Great marks". Even if later conditions are also true, only the first matching block executes.

Chain vs. Multiple Separate if Statements

StructureBehavior
if…else if…elseOnly one block runs (first true condition).
Multiple standalone ifEach if is independent; all true conditions execute.

Example – separate ifs:

if (temperature < 20) console.log("Normal");   // runs if true
if (temperature < 25) console.log("Kind of hot"); // also runs if true

For temperature = 10, both print. With a chain, only the first would print.

Nesting if Statements

An if block can contain another if…else structure for hierarchical decisions.

Example – driving license eligibility:

let age = 25;
let hasLL = "Y";

if (age >= 18) {
  if (hasLL === "Y") {
    alert("You can take DL");
  } else {
    alert("First get a LL");
  }
} else {
  alert("Grow older");
}
  • Outer if checks age eligibility first.
  • Only if age >= 18 does the inner if check for a learner’s license.

Alternative using else if (without nesting):

if (age >= 18 && hasLL === "Y") {
  alert("You can take DL");
} else if (age >= 18 && hasLL !== "Y") {
  alert("First get a LL");
} else {
  alert("Grow older");
}

Both achieve the same logic; choose nesting when conditions are naturally grouped.

Logical Operators in Conditions

Combine multiple sub‑conditions with && (AND), || (OR), ! (NOT). They can be written directly in the condition or pre‑stored in a variable.

if (age >= 18 && hasLL === "Y") { ... }

Exam tip: In an if…else if chain, order matters. When overlapping ranges exist (e.g., marks > 95 and marks > 80), the first true condition executes and the rest are ignored. Always test edge cases like marks = 96 where both could be true.

Key Takeaways

  • if runs code only when its condition is true.
  • else if adds additional conditions; else is the default catch‑all.
  • In a chain, only one block executes — the first true one.
  • Separate if statements are independent and may both run.
  • Nesting places an if inside another if to handle hierarchical decisions.
  • Use logical operators (&&, ||, !) to combine conditions.

Nested Conditionals

Nested conditionals are if statements placed inside another if (or else/else if) block. They allow decisions that depend on multiple layers of conditions — the inner check only matters if the outer condition is true.

Structure

if (outerCondition) {
    if (innerCondition) {
        // runs when both true
    } else {
        // outer true, inner false
    }
} else {
    // outer false
}

Worked example: Movie ticket pricing

A cinema charges different prices based on two factors: age (≥18 or <18) and membership (Y/N). Without nesting, four separate conditions would be needed. Nesting makes the dependency explicit.

let age = parseInt(prompt("What is your age?"));
let member = prompt("Are you a member? (Y/N)");

if (age > 18) {
    if (member === "Y") {
        alert("Your ticket price is 200");
    } else {
        alert("Your ticket price is 300");
    }
} else {
    // age <= 18
    if (member === "Y") {
        alert("Your ticket price is 50");
    } else {
        alert("Your ticket price is 100");
    }
}

The logic flows as:

flowchart TD
    A[Age > 18?] -->|Yes| B[Member?]
    A -->|No| C[Member?]
    B -->|Y| D[Price 200]
    B -->|N| E[Price 300]
    C -->|Y| F[Price 50]
    C -->|N| G[Price 100]

Input validation with isNaN()

User input from prompt() is always a string. Use parseInt() to convert to a number, then check with isNaN() to ensure a valid numeric entry. The lecture wrapped the entire nesting inside an if (!isNaN(age)) block.

if (!isNaN(age)) {
    // nested conditionals here
} else {
    alert("Please enter a valid age");
}

Benefits & drawbacks

BenefitDrawback
Handles dependent conditions cleanlyReadability suffers as nesting depth increases
Avoids repeating outer checksDebugging becomes harder
Matches natural decision hierarchiesOveruse leads to "spaghetti logic"

Exam tip: When asked to simplify nested code, consider using logical operators (&&, ||) to flatten conditions. For the ticket example, the price could be computed with a single expression: if (age > 18) ? (member === "Y" ? 200 : 300) : (member === "Y" ? 50 : 100) — but nesting is clearer for beginners.

Key takeaways

  • Nested ifs let you test conditions that depend on earlier results.
  • Always validate numeric input with parseInt() + isNaN().
  • Keep nesting shallow (≤3 levels) to maintain readability.
  • Example: ticket price depends on age first, then membership.

Truthiness

Truthiness refers to how JavaScript treats a non‑boolean value as true or false when used in a boolean context (e.g., inside an if condition). Not every value is a literal true or false, but every value behaves as one of them.

Falsy values (the complete list)

Only these six (plus 0n for BigInt) evaluate to false:

ValueExample
falsefalse
0, -00, -0
""empty string
nullnull
undefinedundefined
NaNNaN

All other values — including any non‑zero number, non‑empty string, array, object, function — are truthy.

Quick code demonstration

if (0)        console.log("truthy"); // never runs
if ("hello")  console.log("truthy"); // runs
if (null)     console.log("truthy"); // never runs
if ([])       console.log("truthy"); // runs (array is truthy)

Practical benefit: simplified conditions

Instead of writing verbose checks like:

if (email !== "" && email !== null && email !== undefined) { ... }

you can write:

if (email) { ... }

The if (email) condition is false when email is "", null, or undefined — exactly the cases you want to reject.

Worked example: Email form validation

let email = prompt("Enter your email:");
if (email) {
    alert("Thank you");
} else {
    alert("Please enter email. It is mandatory.");
}

If the user presses Cancel (null) or leaves it empty (""), the condition fails and the else block runs.

Exam tip: A common mistake is assuming if ("false") is false. It is truthy because it's a non‑empty string. Only the boolean false is falsy. Also, if ([]) is truthy — empty arrays are objects, which are truthy.

Key takeaways

  • Truthiness lets any value act as a boolean in conditions.
  • Falsy values: false, 0, "", null, undefined, NaN.
  • Use truthy checks to write cleaner conditions (if (age) instead of if (age !== 0 && age !== null ...)).
  • Beware: "0", "false", [], {} are all truthy.
  • Understanding truthiness prevents bugs when validating user input.

Array Basics

Arrays solve the problem of managing collections of data. Instead of dozens of individual variables (song1, song2, …), one array holds all items in an ordered list.

Declaration – use square brackets []:

let playlist = [];           // empty array
let fruits = ['banana', 'apple', 'peach'];   // initialised with three strings

Key fact: typeof an array returns "object" – arrays are a special kind of object in JavaScript.

What can an array hold?

  • Any data type — numbers, strings, booleans, null, NaN, even other arrays.
  • Mixed types in the same array are allowed (JavaScript is dynamically typed).
let mixed = [1, 11.4, "asd", true, NaN, null, [1, 2, 3]];
// mixed.length is 8; the nested array counts as one element

Nested arrays (arrays inside arrays) are useful for complex data like matrices or grouped records.

The length property

array.length returns the count of elements, not the highest index.
Example: fruits.length3 even though indices go 0,1,2.

Exam tip: length is a property, not a method — no parentheses. Use it to loop or to add an element at the end via array[array.length] = "new".


Key takeaways – Array creation & properties

  • Arrays store multiple values under one variable, making code cleaner.
  • Declare with []; empty or initialised with comma-separated values.
  • typeof array"object".
  • Arrays can mix types, including nested arrays.
  • length gives the number of elements, not the last index.

Indexing and Mutability

Arrays are zero-indexed. Access elements with square brackets:

console.log(fruits[0]);   // "banana"
console.log(fruits[2]);   // "peach"
console.log(fruits[99]);  // undefined — no error

Arrays are mutable – you can change an element directly:

fruits[0] = "mango";   // changes first element
fruits[3] = "mango";   // adds a new element at index 3
fruits[10] = "tomato"; // adds at index 10; indices 4–9 become empty slots (undefined)

Exam tip: Mutability is a key difference from strings. Strings are immutablestr[0] = "B" does nothing; arrays change in place.

Sparse arrays – assigning to an index far beyond length creates empty slots (filled with undefined but not actual undefined values). The array’s length jumps to that index + 1.

let fruits = ['banana','apple','peach'];
fruits[10] = 'tomato';
// fruits[4..9] are empty; fruits.length becomes 11

Manual addition to the end (cumbersome)

fruits[fruits.length] = 'strawberry';   // works but verbose

Array Methods – Adding and Removing Elements

JavaScript provides built-in methods that handle indexing automatically. Most modify the original array (in place), unlike string methods that return a new string.

MethodOperationLocationReturn valueMutates?
push(elem1, elem2, ...)Add one or moreEndNew array length (implied)Yes
pop()Remove oneEndRemoved elementYes
unshift(elem1, elem2, ...)Add one or moreStartNew array lengthYes
shift()Remove oneStartRemoved elementYes

push and pop – work at the end

let fruits = ['tomato', 'green strawberry'];
fruits.push('kiwi', 'blueberry');   // adds two elements
console.log(fruits);                // ['tomato','green strawberry','kiwi','blueberry']

let popped = fruits.pop();          // removes 'blueberry'
console.log(popped);                // 'blueberry'
console.log(fruits);                // ['tomato','green strawberry','kiwi']

shift and unshift – work at the start

Analogy (queue):

  • shift removes the first person; everyone shifts forward.
  • unshift adds a “celebrity” to the front; everyone shifts back.
let queue = [1,2,3,4,5,6];
let first = queue.shift();          // removes 1, returns 1
console.log(queue);                 // [2,3,4,5,6]

queue.unshift('govind', 'friend');  // adds two to front
console.log(queue);                 // ['govind','friend',2,3,4,5,6]

Exam tip: shift and unshift have confusing names. Remember: shift = remove first → everyone shifts forward; unshift = add first → everyone un-shifts (moves back). Practice with small arrays.

Key difference from strings

let str = "cat";
str[0] = "b";          // fails silently – str remains "cat"
str.toUpperCase();     // returns "CAT" but str unchanged

let arr = [1,2,3];
arr.push(4);           // arr becomes [1,2,3,4] – modified in place
  • Strings: methods return a new string; original unchanged.
  • Arrays (most mutator methods): modify the array directly.

Key takeaways – Indexing & methods

  • Access/modify elements with arr[index].
  • Arrays are mutable; assigning beyond length creates empty slots.
  • push / pop operate at the end; unshift / shift at the start.
  • All four methods mutate the original array.
  • pop and shift return the removed element; push and unshift return the new length (commonly used but not explicitly required).
  • Always check MDN for full details on array methods.

More Array Methods

Array methods are built-in functions that let you manipulate, query, and transform arrays efficiently. The key difference between them is whether they mutate (modify) the original array or leave it unchanged. Most methods return a new array or a single value instead.

concat – Combine arrays

concat() merges two or more arrays into a new array. It does not change the original arrays.

const veggies = ['tomato', 'cucumber', 'carrot'];
const fruits = ['apple', 'banana'];
const combined = veggies.concat(fruits);
// combined → ['tomato', 'cucumber', 'carrot', 'apple', 'banana']
// veggies is unchanged

Also accepts multiple arrays: veggies.concat(fruits, playlist).

includes – Check for existence

includes() returns a Booleantrue if the element exists in the array, false otherwise. It performs an exact match and does not modify the array.

veggies.includes('cucumber'); // true
veggies.includes('car');      // false (partial match not allowed)

indexOf – Find the first index

indexOf() returns the first index of a given element, or -1 if not found. Works like the string version. Does not mutate.

veggies.indexOf('carrot'); // 2
veggies.indexOf('car');    // -1

join – Make a string from an array

join() concatenates all elements into a string, separated by a given separator (default is comma). The array itself is unchanged.

veggies.join();           // "tomato,cucumber,carrot"
veggies.join(' - ');      // "tomato - cucumber - carrot"
veggies.join(' - govind - '); // "tomato - govind - cucumber - govind - carrot"

reverse – Flip the order

reverse() reverses the order of elements in place – the original array is mutated.

console.log(veggies); // ['tomato', 'cucumber', 'carrot']
veggies.reverse();
console.log(veggies); // ['carrot', 'cucumber', 'tomato']

slice – Extract a portion

slice(start, end) returns a shallow copy of a portion of the array from start (inclusive) to end (exclusive). Negative indexes count from the end. Original array is not modified.

const arr = ['tomato', 'cucumber', 'carrot', 'enter sandman'];
arr.slice(1, 4); // ['cucumber', 'carrot', 'enter sandman'] (index 1 to 3)
arr.slice(1);    // ['cucumber', 'carrot', 'enter sandman'] (from index 1 to end)
arr.slice(-2);   // ['carrot', 'enter sandman'] (last two elements)

splice – Add, remove, or replace

splice(start, deleteCount, item1, item2, ...) mutates the array. It removes deleteCount elements starting at index start, then optionally inserts any provided items at that position.

deleteCountItems providedEffect
> 0noneRemove that many elements
0yesInsert items without removing anything
> 0yesReplace removed elements with the items

Examples

let arr = veggies.concat(fruits, playlist); // large test array
// Remove 2 items from index 1
arr.splice(1, 2); // removes 'cucumber' and 'carrot'
// Remove 2 from index 1 and insert 'govind'
arr.splice(1, 2, 'govind');
// Insert without removal: arr.splice(1, 0, 'govind', 'raj', veggies);

Exam tip: The fastest way to tell if a method mutates: read MDN. Common mutating methods: reverse, splice, push, pop, shift, unshift. Non-mutating: concat, includes, indexOf, join, slice, map, filter.

Quick reference table

MethodMutates?ReturnsPurpose
concatNoNew arrayCombine arrays
includesNoBooleanCheck existence
indexOfNoNumber (index or -1)Find first index
joinNoStringCreate string from array
reverseYesThe mutated array itselfReverse order
sliceNoNew array (shallow copy)Extract a portion
spliceYesArray of removed elementsAdd/remove/replace in place

Key takeaways

  • concat, includes, indexOf, join, slice do not modify the original array.
  • reverse and splice mutate the original array.
  • splice is the most flexible: you can delete, insert, or replace in one call.
  • The slice method behaves like the string slice – same syntax, zero-based, negative indexes work.
  • Always verify method behaviour on MDN; memorisation is not required – practice builds familiarity.

Arrays as Reference Types

JavaScript arrays are reference types, not primitive values. A variable holding an array stores a memory address (a reference) to where the array’s data lives—not the data itself. This has two critical consequences: value-based comparison fails, and assignment creates aliases.

Arrays Are Not Equitable by Value

Two arrays with identical elements are different objects in memory. Using == or === compares their references, not their contents.

const fruits1 = ['apple', 'banana'];
const fruits2 = ['apple', 'banana'];
console.log(fruits1 == fruits2);   // false
console.log(fruits1 === fruits2);  // false

To compare actual array contents, you must iterate element-by-element or use a utility (e.g., every() with index matching). Direct equality always returns false for distinct arrays.

Assignment Creates a Shared Reference

When you assign an array to another variable, the new variable points to the same memory location. Mutating the array through either variable changes the shared data.

const a1 = [1, 2];
const a2 = a1;         // a2 references same array as a1
a1[1] = 5;            // mutate the shared array
console.log(a1, a2);  // both are [1, 5]

This contrasts with primitive values (numbers, strings), where assignment copies the value:

Data typeOperationOutcome
Primitivelet x=1; let y=x; x=2;y remains 1
Array (reference)let a=[1,2]; let b=a; a[0]=5;b also sees [5,2]

How to break the reference – create a true copy:

  • Assign a new array literal: a2 = [1, 2];
  • Use .slice() (returns a shallow copy): a2 = a1.slice();

After a true copy, mutations to the original do not affect the copy.

let a1 = [1, 2];
let a2 = a1.slice();
a1[0] = 10;
console.log(a1, a2);   // [10, 2] and [1, 2]

Exam tip: Any direct assignment arr2 = arr1 makes both variables reference the same array. Mutations through either one affect the other. To guard against unintended side effects, always copy with .slice() or the spread operator.

Key takeaways

  • Arrays are stored as references; ==/=== compare memory locations, not contents.
  • Two different arrays with identical elements are never ===.
  • Assigning an array to a new variable creates an alias, not a copy.
  • Mutating the array through any alias changes the shared data.
  • Use .slice() (or spread [...arr]) to create a shallow copy and break the alias.

Multidimensional Arrays (Nested Arrays)

A multidimensional array is an array whose elements are themselves arrays. Useful for matrices, grids, and tabular data.

Example – 3×3 matrix (2D array):

const matrix = [
  [1, 2, 3],
  [4, 5, 6],
  [7, 8, 9]
];

Accessing elements:

  • matrix[0] → first row: [1, 2, 3]
  • matrix[0][1] → first row, second column: 2
  • Use successive bracket notation: [row][col] for 2D.

Higher dimensions – adding another level of nesting (array inside an array inside an array) creates a 3D structure.

Key takeaways

  • Nested arrays create multidimensional structures (2D, 3D, etc.).
  • Access elements with multiple bracket indices: arr[i][j][k].
  • Common uses: matrix operations, game boards, spreadsheets.

Overall Key Takeaways

  • Arrays are reference types – never compare with ==/=== to check content equality.
  • Assigning an array copies the reference, not the data; mutations propagate.
  • Create independent copies with .slice() or spread syntax.
  • Multidimensional arrays (arrays of arrays) enable row–column data structures; index with multiple brackets.

JavaScript Objects

Objects in JavaScript are collections of key-value pairs. They store multiple related values, each labeled with a meaningful key (or property name). Think of an object as a labeled filing cabinet: you access a value by its label, not by a numeric index (as in arrays). Objects are fundamental for representing complex, structured data.

Syntax

An object literal is defined with curly braces {}. Inside, keys and values are separated by a colon :, and pairs are comma-separated:

let person = {
  name: "Govind",        // key: "name", value: "Govind"
  age: 120,              // key: "age", value: 120
  isStudent: false,      // key: "isStudent", value: false
  classes: ["web development", "Excel"],  // value can be an array
  address: "Bannerghatta, Bangalore"
};

Keys are implicitly converted to strings (even if you omit quotes). The convention is to use camelCase keys that follow variable naming rules.

Properties

Each key-value pair is called a property. You have already used properties on built-ins (e.g., "hello".length). Objects let you define your own.

Values can be any data type:

  • string, number, boolean
  • array
  • nested object (another object)
  • function (covered in a later module)

Accessing Properties

Two ways to read a property’s value:

NotationSyntaxExampleNotes
Dot notationobject.keyperson.name"Govind"Key must be a valid identifier (no spaces, no numbers at start)
Bracket notationobject["key"]person["age"]120Key is always a string (even if you write 123, it becomes "123")

Use dot notation for known, simple keys; bracket notation when the key is dynamic or contains characters that break dot syntax.

Dynamic keys with bracket notation

Bracket notation accepts a variable whose value is a string key:

let searchKey = "name";
console.log(person[searchKey]);   // "Govind"

searchKey = "123";
console.log(person[123]);         // Access key "123", works because key is auto-converted

Exam tip: Bracket notation is essential for computed or runtime‑determined keys. Dot notation is safer for hard‑coded keys, but bracket notation is more flexible — know both.

Modifying and Adding Properties

You can change an existing property or add a new one by simple assignment:

person.name = "Simran";             // dot notation – update
person.isStudent = true;            // update

person.ethnicity = "Indian";        // add new property (dot)
person["fatherName"] = "Shah Rukh Khan"; // add new property (bracket)

Properties that don’t exist are created on the fly.

Nested Objects

A property’s value can itself be an object, enabling deep data structures:

let person = {
  name: "Govind",
  address: {
    city: "Bangalore",
    street: "Bannerghatta",
    pinCode: 123456
  }
};

console.log(person.address.city);    // "Bangalore"
console.log(person["address"]["pinCode"]); // 123456

Access nested properties by chaining dot or bracket notation.

Use Cases

  • User profiles (username, email, password)
  • Product details (name, price, available)
  • Application settings (theme, volume)
  • Every HTML element as a DOM object (next module)
  • The entire document object is a JavaScript object

Objects make code more readable and data more organised than separate variables.

Key takeaways

  • Objects are key-value pairs inside {}; keys are always strings.
  • Dot notation is concise for known, valid identifiers; bracket notation handles dynamic or problematic keys.
  • Properties can be added or updated by assignment on the fly.
  • Values can be any type, including nested objects and arrays.
  • Bracket notation requires the key as a string (or variable holding a string).
  • Use objects to bundle related data instead of many independent variables.

Loops in JavaScript

Loops let you repeat actions without duplicating code. Instead of writing hundreds of lines to display each comment or product, one loop iterates over the collection and handles each item dynamically.

Why loops matter

  • Process lists of data (comments, products, search results).
  • Display many items from arrays or objects.
  • Perform repetitive calculations.
  • Keep code clean, concise, and adaptable.

The for loop – the most common loop

The for loop runs a block of code a specific number of times. Its syntax has three parts inside parentheses, separated by semicolons:

for (initialization; condition; increment) {
  // body – code to repeat
}
PartPurposeExample
InitializationDeclare and set a loop variable (often i). Runs once before the loop starts.let i = 0
ConditionChecked before each iteration. If true, the body runs; if false, the loop stops.i <= 10
IncrementUpdates the loop variable after each iteration.i++ (adds 1)

Order of execution

flowchart TD
    A[Initialization: i = 0] --> B{Condition: i <= 10?}
    B -->|True| C[Execute body]
    C --> D[Increment: i++]
    D --> B
    B -->|False| E[Exit loop]

Worked example: Print numbers 0 to 10

for (let i = 0; i <= 10; i++) {
  console.log(i);
}

How it runs (step‑by‑step):

  1. i = 0 → check 0 <= 10true → print 0i becomes 1
  2. i = 1 → check 1 <= 10true → print 1i becomes 2
  3. … continues until i = 10 → print 10i becomes 11
  4. i = 11 → check 11 <= 10false → exit

Output: 0 1 2 3 4 5 6 7 8 9 10 (11 numbers, because i <= 10 includes 10).

Iterating over an array with a for loop

Given an array playlist = ["Enter Sandman", "Nothing Else Matters", "Fade to Black", "Unforgiven"], we can print each element:

for (let i = 0; i < playlist.length; i++) {
  console.log(playlist[i]);
}
  • i starts at 0 (first index).
  • Condition uses playlist.length (here 4) → loops while i < 4 → indices 0,1,2,3.
  • Prints each song.

Number the songs (1‑based)

for (let i = 0; i < playlist.length; i++) {
  console.log(`Song ${i + 1} is ${playlist[i]}`);
}

i + 1 is just for display; the actual loop variable i remains unchanged.

Variations of the for loop

1. Different step sizes

Increment expressionEffectExample output (0 to 10, step 2)
i += 2Skips every other number0 2 4 6 8 10
i *= 9Multiplies each step1 9 81 (if start at 1)

2. External counter (initialization outside)

let i = 1;
for (; i <= 100; i += 9) {
  console.log(i);
}

3. Increment inside the body

for (let i = 1; i <= 100; ) {
  console.log(i);
  i += 9;
}

All variations work as long as the loop variable is updated and the condition eventually becomes false.

Infinite loops – the critical trap

An infinite loop occurs when the condition never becomes false. The program freezes or crashes.

Dangerous examples

// Multiply by 9 starting from 0
for (let i = 0; i <= 100; i *= 9) {
  console.log(i);   // i stays 0 forever
}

// Condition always true
for (let i = 0; i >= 0; i++) {
  console.log(i);   // i keeps increasing, condition never false
}

Exam tip: Always ensure that something inside the loop changes the loop variable so that the condition will eventually be false. The most common mistake is an increment that doesn’t actually change the value (e.g., i *= 9 when i = 0) or a condition that can never be satisfied (e.g., i >= 0 with i++).

Key takeaways

  • for loops repeat code a fixed number of times using initialization, condition, and increment.
  • The condition is checked before each iteration; the increment runs after the body.
  • Use array.length as the upper bound when iterating over arrays.
  • Increment can be any expression (+=2, *=9, etc.) but must eventually make the condition false.
  • An infinite loop crashes the application – always verify that the loop will terminate.
  • The for loop is the foundation; other loops (while, for…in, for…of) are covered in later videos.

Nested Loops

A nested loop places one loop inside another. The inner loop runs through all its iterations for every single iteration of the outer loop. This structure is essential for processing multidimensional data – for example, a 2D grid or an array of arrays.

How it works (basic example)

for (let i = 0; i < 2; i++) {
  console.log("outer loop", i);
  for (let j = 0; j < 3; j++) {
    console.log("inner loop", j);
  }
}

Output:

outer loop 0
inner loop 0
inner loop 1
inner loop 2
outer loop 1
inner loop 0
inner loop 1
inner loop 2

The outer loop runs twice, and for each of those two runs the inner loop runs three times – total 6 inner iterations.

Traversing a nested array (traditional approach)

Given a nested (2D) array, you need one loop for the outer array and another loop for each inner array.

const nestedArray = [[1, 2], [3, 4, 5], [6, 7]];

for (let i = 0; i < nestedArray.length; i++) {
  console.log("Outer array:", nestedArray[i]);
  for (let j = 0; j < nestedArray[i].length; j++) {
    console.log("Inner element:", nestedArray[i][j]);
  }
}

The outer loop index i selects each sub‑array; the inner loop index j walks through the elements of that sub‑array.


for...of – modern iteration for arrays and strings

for...of directly gives you each value of an iterable (arrays, strings, Maps, Sets, etc.). No indexing needed – it’s more readable and less error‑prone.

Array example

for (const outerArray of nestedArray) {    // outerArray is each sub‑array
  console.log("Outer array:", outerArray);
  for (const element of outerArray) {      // element is each value inside
    console.log("Inner element:", element);
  }
}

Same output as the nested‑loop version above, but simpler.

String example (strings are iterable)

for (const char of "Hello") {
  console.log(char);   // prints H, e, l, l, o
}

Exam tip: for...of works on any iterable, but not on plain objects. Trying for (const x of person) will throw a TypeError.


for...in – object keys (use with caution)

for...in iterates over the keys (property names) of an object. You can then access values via bracket notation.

const person = { name: "Alice", age: 25, student: true };

for (const key in person) {
  console.log(key, person[key]);   // name Alice, age 25, student true
}

Drawbacks:

  • Confusing name – many languages use in for arrays, so it’s easy to mix up with for...of.
  • It also iterates over inherited enumerable properties (unless filtered).
  • Not recommended for arrays; use for...of instead.

Better alternative: Object.keys, Object.values, Object.entries

Instead of for...in, use these static methods that return arrays – then iterate with for...of.

MethodReturnsExample usage
Object.keys(obj)Array of keysfor (const k of Object.keys(person))
Object.values(obj)Array of valuesfor (const v of Object.values(person))
Object.entries(obj)Array of [key, value] pairsfor (const [k, v] of Object.entries(person))

Example (preferred approach):

const person = { name: "Alice", age: 25 };

// Keys only
for (const key of Object.keys(person)) {
  console.log(key);                // name, age
}

// Values only
for (const val of Object.values(person)) {
  console.log(val);                // Alice, 25
}

// Key-value pairs
for (const [key, val] of Object.entries(person)) {
  console.log(key, val);           // name Alice, age 25
}

This pattern is explicit, works with any array‑iteration method, and avoids the confusion of for...in.


Summary of loop choices

flowchart TD
  A[What to iterate?] --> B{Array or iterable?}
  B -->|Yes| C[Use for...of]
  B -->|No – it's an object| D[Use Object.keys/values/entries + for...of]
  C --> E[Or use traditional for loop with index]
  D --> F[Avoid for...in, it's confusing]

Key takeaways

  • Nested loops: outer loop controls rows, inner loop controls columns (or sub‑elements).
  • for...of is the cleanest way to iterate arrays, strings, and other iterables.
  • for...in iterates object keys but is error‑prone; prefer Object.keys() / Object.values() / Object.entries().
  • Use traditional for (let i = 0; i < arr.length; i++) when you need the index or break early.
  • For objects, always convert to an array first using Object.* methods, then use for...of.

Exam tip: Interviewers love asking why for...in on an array is bad – it includes inherited properties and key order isn’t guaranteed. Stick with for...of for array values.

Functions in JavaScript

A function is a reusable block of code that performs a specific task. Instead of writing the same logic over and over, you define it once and call it whenever needed. This follows the DRY (Don't Repeat Yourself) principle, making code more readable, modular, and testable.

Defining vs Calling

  • Defining a function stores it in memory without executing the code.
  • Calling (or invoking) a function runs the defined code.
// Defining
function greet() {
  console.log("Hello world");
}

// Calling
greet();   // logs "Hello world"

If you only reference the function name without parentheses (e.g., greet), JavaScript just tells you it's a function — it doesn't run it.

Parameters and Arguments

Functions can accept inputs to work with. The placeholder in the definition is a parameter; the actual value passed during the call is an argument.

function greet(name, age) {
  console.log(`Hello world ${name}. Wow, you are ${age} years old.`);
}

greet("Govind", 24);   // "Hello world Govind. Wow, you are 24 years old."
TermDefinitionExample
ParameterVariable defined in the function declarationname, age
ArgumentActual value supplied when calling the function"Govind", 24

If you call a function without providing an argument for a defined parameter, that parameter becomes undefined — the function still runs but with undefined in place.

Hoisting

JavaScript hoists function declarations to the top of their scope, so you can call a function before its definition appears in the code. However, relying on this is discouraged — always define before calling for clarity and easier debugging.

Worked Example: Generating a Random Number Repeatedly

Instead of writing console.log(Math.random()) multiple times, wrap it in a function:

function printRandom() {
  console.log(Math.random());
}

printRandom(); // logs a random number
printRandom(); // logs another random number
printRandom(); // logs another random number

Now you have a single block you can call from anywhere.

Exam tip: Hoisting only applies to function declarations (the function keyword form), not to function expressions (e.g., const f = function() {}). Know the difference — it’s a common trick question.

Key takeaways

  • A function is a reusable block of code defined with the function keyword.
  • Defining stores the code; calling (with ()) executes it.
  • Parameters are placeholders in the definition; arguments are the actual values passed.
  • Missing arguments become undefined — the function still runs.
  • Hoisting allows calling before definition, but good practice defines first.

Advanced Concepts in Functions

Functions in JavaScript can be treated as first-class citizens: they can be assigned to variables, passed as arguments, and returned from other functions. This flexibility enables powerful patterns like callbacks, factory functions, and recursion.

Assigning Functions to Variables

A function can be referenced by a variable without being executed. The variable can then be used to call the function.

function add(a, b) { return a + b; }
let addition = add;          // No parentheses – we assign the function itself
console.log(addition(1, 2)); // 3

Anonymous functions — functions without a name — can be created and directly assigned to a variable. A function statement without a name is invalid, but when used in an assignment it becomes valid.

let addition = function(a, b) { return a + b; };
addition(1, 2); // 3

Passing Functions as Arguments (Callbacks)

Because functions are first-class, they can be passed into other functions as arguments. This pattern is called a callback and enables reusable, dynamic logic.

Worked Example: executeXTimes

function randomNumber() {
  console.log(Math.floor(Math.random() * 100));
}

function executeXTimes(fn, count) {
  let i = 0;
  while (i < count) {
    fn();   // fn is the function passed in
    i++;
  }
}

executeXTimes(randomNumber, 5); // logs 5 random numbers
  • randomNumber is passed without parentheses — we pass the reference, not the result.
  • Inside executeXTimes, fn is called using fn().

Returning Functions (Factory Functions)

A function can return another function. This allows creating specialized functions on the fly — a factory function.

function multiplierFactory(multiplier) {
  return function(value) {
    return value * multiplier;
  };
}

const double = multiplierFactory(2);
const triple = multiplierFactory(3);

console.log(double(10)); // 20
console.log(triple(10)); // 30
  • The outer function captures the multiplier argument via closure.
  • The returned inner function uses that captured value whenever called.

Recursion

Recursion is when a function calls itself. It is useful for traversing nested structures where the depth is unknown (e.g., nested arrays, trees).

Worked Example: Printing a Nested Array

function printNestedArray(arr) {
  for (let item of arr) {
    if (Array.isArray(item)) {
      printNestedArray(item);  // recursive call
    } else {
      console.log(item);
    }
  }
}

let nestedArray = [
  [2.1, 2.2, 2.3],
  3, 4,
  [[5.11, 5.12], [5.21, 5.22]],
  6, 7, 8, 9
];

printNestedArray(nestedArray);
// Output: 2.1, 2.2, 2.3, 3, 4, 5.11, 5.12, 5.21, 5.22, 6, 7, 8, 9
  • Base condition: when an item is not an array, print it and stop recursing that branch.
  • Without a base condition, infinite recursion would crash the program.

Exam tip: Always ensure a recursive function has a base case that terminates the calls.

Object Methods

Methods are functions stored as properties of an object. They can access and modify the object’s data using the this keyword.

Defining a Method – Two Syntaxes

  1. Property + anonymous function:

    let person = {
      name: "Govind",
      age: 25,
      speak: function() {
        return `My name is ${this.name}`;
      }
    };
    
  2. Shorthand syntax (more modern):

    let person = {
      name: "Govind",
      age: 25,
      greet() {
        return `Hi, my name is ${this.name}, age ${this.age}`;
      }
    };
    
  • Call a method with parentheses: person.speak()"My name is Govind"
  • this inside the method refers to the object the method belongs to. Changing person.name updates the output.
  • All methods are functions, but not all functions are methods — methods are tied to a specific object.

Key Takeaways

  • Functions can be assigned to variables, making them first-class citizens.
  • Anonymous functions work when assigned, but not as standalone statements.
  • Callbacks (passing functions as arguments) enable reusable, dynamic code.
  • Factory functions return specialized functions via closures.
  • Recursion solves problems with nested structures; always include a base condition.
  • Methods are functions inside objects; use this to reference the object’s properties.

Business, Design and Product perspectives for web development

Module 2 Introduction: Business, Product & Design Perspectives

Module 1 established the technical foundation: internet mechanics, HTML/CSS/JS rendering, browser behavior, and internet history. Module 2 shifts from how websites are built to why they are built — the planning decisions made before a single line of code.

Core shift in focus

Module 1 (Technical)Module 2 (Strategic)
How the internet worksBusiness objectives – what outcome must the site drive?
How files (HTML, CSS, JS) create pagesProduct management – think like a PM: which features matter most for that outcome?
Browser renderingDesign patterns, visual hierarchy, color palettes, fonts – how to visually achieve the desired result

What Module 2 covers

  • Defining clear business objectives → every design and feature decision must be traceable to a specific outcome (e.g., increase sign-ups, reduce support tickets, boost average order value).
  • Analyzing live websites → reverse-engineer the decisions behind existing features.
  • Prioritizing features → given multiple possible features, choose the ones that best serve the objectives.
  • Design perspective → apply design patterns (reusable solutions to common UX problems), visual hierarchy (arrange elements to guide the eye), color palettes, and typography to achieve the desired user response.

Why it matters: A technically perfect site can fail if it doesn't serve a clear business goal. This module builds the planning discipline needed to align code with purpose.

Learning outcome

By the end of this module, you can plan websites that are both functional (they work) and strategically aligned (they achieve specific business goals).

Key takeaways

  • Module 2 moves beyond code to strategic planning: business objectives → feature prioritization → design execution.
  • Three pillars: business, product (features, prioritization), and design (patterns, hierarchy, color, typography).
  • Every design choice should be intentional and traceable to a desired outcome.
  • Real website analysis and feature trade-offs are core practice skills.

Business Objectives

Business objectives define the core purpose of a website and guide every subsequent decision in content, design, and user experience. Without them, a site becomes like a store without signs or product arrangement — visitors are confused, frustrated, and likely to leave. A clear objective answers: Is this site meant to inform, sell, or generate leads?

By setting the objective early, designers and developers create a coherent, purposeful site that serves both the business and the user.

Why objectives matter

A website built without a clear purpose lacks direction. Visitors don’t know what to do or expect. Clear objectives:

  • Shape content type and style (articles vs. product descriptions).
  • Determine design choices (readability vs. bold CTAs).
  • Influence interaction design (search/navigation vs. cart/checkout).
  • Keep the site focused — every element works toward the goal.

Impact on content, design, and interaction

AspectInformational site (e.g., blog)E‑commerce site (e.g., online store)
ContentIn-depth articles, resources, easy navigationProduct descriptions, reviews, images
DesignMinimal colors, clean typography, readable sectionsVibrant, visually engaging, eye‑catching offers
Call‑to‑actions (CTAs)Subtle, placed after content (e.g., newsletter sign‑up)Prominent, multiple “Add to bag” buttons
User interactionSearch, related articles links, subscription formShopping cart, streamlined checkout, high‑intent paths

Different objectives lead to fundamentally different user experiences.

Worked examples: TechCrunch vs. Nykaa

TechCrunch (informational)
Objective: inform and engage.

  • Simple layout, focus on typography, one brand color (green).
  • No distracting colors in reading sections.
  • Easy navigation with categories at top.
  • CTAs (e.g., subscribe) are less prominent, hidden after content.

Nykaa (e‑commerce)
Objective: drive sales.

  • Vibrant homepage with offers to attract low intent users (browsing).
  • Sign‑in option highlighted; pop‑ups for sign‑up.
  • Detailed categories structured for high intent users (ready to buy).
  • Product pages showcase details, reviews, related products, multiple “Add to bag” CTAs.
  • Post‑purchase flow streamlined for seamless checkout.

Exam tip: Always ask “What is the main purpose of this site?” before deciding on any feature, layout, or element. Every component must serve the objective.

How objectives connect to decisions

flowchart LR
    O[Business Objective] --> C[Content style]
    O --> D[Design & visual]
    O --> I[Interaction / UX]
    C --> E[Article vs. product]
    D --> F[Subtle vs. bold CTAs]
    I --> G[Search vs. cart]

Key takeaways

  • Business objectives give a website direction: inform, sell, or generate leads.
  • Without them, the site confuses users and fails to achieve business goals.
  • Objectives directly shape content, design (colors, CTAs), and interaction (navigation, checkout).
  • Low intent users browse; high intent users know what they want and need a fast path to purchase.
  • Compare TechCrunch (informational) and Nykaa (e‑commerce) to see how different objectives produce completely different sites.

Product Management Principles

Applying product management principles to web development shifts the focus from aesthetics to purposeful, impact-driven design. The core idea: every website must answer two fundamental questions – Why is it needed? and What do we want to achieve with it? Success comes from meeting business objectives while delivering a stellar user experience.

First Principles: Purpose-Driven Design

Before any design or code, define the website’s core purpose. A clear purpose ensures every element serves that goal. Common primary goals:

  • Drive sales (e-commerce)
  • Generate leads (conversion funnels)
  • Increase brand awareness (content / marketing)

Exam tip: Always start an exam answer with the two fundamental questions. They are the foundation for all subsequent product management decisions.

Structuring Around Business Objectives

Structure the website around the primary goal so that the user journey naturally leads to the desired outcome. Mapping out user journeys reduces friction and keeps attention on the objective.

Example – Flipkart
Business objective: drive e-commerce sales.
Structure the homepage to highlight sales, offers, product categories, ratings, and reviews – everything points toward purchase.

flowchart LR
    A[Land on homepage] --> B[Browse categories / search]
    B --> C[Subcategory pages]
    C --> D[Product page]
    D --> E[Add to cart]
    E --> F[Checkout: payment + address]
    F --> G[Purchase completed]

Apply this by:

  1. Defining primary goals – sell, inform, or engage.
  2. Designing user journeys – map every step from entry to conversion.
  3. Highlighting key features – banners, CTAs, pop-ups to direct attention.
  4. Reducing friction – remove unnecessary steps; make each next action obvious.

Prioritizing Features

Not all features contribute equally. Prioritize those that directly support business objectives.

Prioritization criteria (from the lecture):

CriterionWhat it meansExample
Analyze user behaviorUse tools like Google Analytics to see what users interact with mostHigh‑click items get priority
Focus on ROIFeatures that directly impact revenue (lead forms, e‑commerce integrations) take precedence“Buy now” over “Share on WhatsApp”
Test and iteratePut something out → test (A/B testing) → keep or changeIterate based on real data

Apply to Flipkart: “Add to cart” and “Buy now” are mandatory; “Share on social media” is lower priority. Personalized product recommendations boost cross‑selling, lightning deals create urgency – both aligned with driving sales.

Balancing Business and User Needs

A great website balances business goals with user expectations. Ignoring either leads to poor engagement or unmet objectives.

Example – Zomato

  • Business wants: encourage users to order food.
  • User wants: quickly find restaurants, view menus, get food fast.
  • Balanced approach: clear search, filters, delivery-time indicators, ratings – plus CTAs, nudges, visual deals to complete purchase.

Tips for balance:

  • Prioritize clarity and ease of use.
  • Gather user feedback to identify pain points.
  • Align every decision with both business and user perspectives.
  • Think from the user’s perspective.

User-Centered Design

To create an intuitive website, understand the user deeply.

Process:

  1. Put yourself in the user’s shoes – conduct surveys, gather insights, talk to users.
  2. Build user personas – who they are, needs, family structure, time available.
  3. Build the website for that persona.
  4. Continuously test with real users.

This ensures the design matches actual mental models and workflows.

Key Takeaways

  • Start with two fundamental questions: why needed and what to achieve.
  • Structure the website and user journey around clear business objectives.
  • Prioritize features by user behavior, ROI, and iterative testing.
  • Balance business goals (CTAs, nudges) with user needs (clarity, speed).
  • Use user personas and continuous testing to design intuitive experiences.
  • Every design decision should align with both business and user expectations.

What Is Color Theory?

Color theory is the science and art of using colors – how they mix, match, contrast, and, most importantly, how they affect human emotions and perceptions. It is not merely aesthetic: colors are psychological. A well-chosen palette can make a visitor want to stay on a site; a chaotic one can drive them away. The biological and cultural responses to color are equally powerful.

Color psychology deepens color theory by revealing how different hues influence emotions, behaviors, and decision-making. Warm colors (red, orange) can raise heart rate; cool colors (blue, green) can lower it and build trust.

How Color Shapes User Experience

  • Biological response – universal physiological reactions (e.g., red → urgency, excitement, danger)
  • Cultural response – learned associations vary across societies (e.g., red = celebration in India, danger in Western traffic signals)
  • Intensity & contrast – high-contrast designs grab attention; subtle tones promote relaxation. Streaming platforms like Netflix use high‑contrast red/black; wellness sites prefer soft green/white.

Exam tip: The Olympic study is a favorite exam hook – athletes wearing red won ~60% of matches against equally skilled opponents wearing blue. This illustrates color’s subconscious influence even in high‑stakes performance.


Breakdown of Individual Colors – Psychology & Brand Examples

ColorCore AssociationsTypical Web/Brand UseExamples from Transcript
RedEnergy, war, danger, strength, urgency, excitementStop signs, sales promotions, call‑to‑action buttons (“Buy Now”, “Limited Offer”)Netflix (attention‑grabbing), Puma sale banner
BlueCalmness, trust, reliability, peace, loyalty, competence, spiritualBanking, healthcare, payment providers, productivity/health appsRazorpay, JustPay, PayPal, insurance sites
YellowCreativity, happiness, energy, attention‑grabbingBrands wanting to stand out; educational sites (boosts engagement)Mokobara’s yellow Mokomini bag (went viral, often out of stock)
GreenNature, growth, freshness, harmony, balance, health, eco‑friendlinessGrocery, pharmacy, wellness, food delivery (freshness signal)Flipkart Grocery (green variant), BigBasket, medicinal/pharmacy sites
BrownDependability, ruggedness, trustworthiness, simplicity, natureOutdoor, natural, “earthy” brandingTimberland (brown in shoes / products to signal ruggedness)
WhiteCleanliness, simplicity, innocence, honesty, clarityMinimalist design, high‑end techApple (white + silver + black → sophistication)
BlackFormality, drama, sophistication, security, luxury, timelessnessLuxury branding, professional servicesNykaa (uses black/pink combination); luxury perfumes
Purple / PinkCompassion, sophistication, femininity (cultural), luxuryCosmetics, feminine‑targeted brandsNykaa (pink/purple to signal femininity & luxury)

Each color’s psychological impact is leveraged deliberately in branding and UI to evoke the desired emotional response.


Applications in Web Development

  • Call to action (CTA) – red for urgency (“Limited Offer”); green for success (checkout confirmation)
  • Trust signals – blue & green together evoke trust and healing
  • White space – enhances clarity, reduces cognitive load
  • Educational sites – yellow to boost engagement and creativity
  • Pharmacy / health – green signals freshness and health

The choice of color goes far beyond aesthetics – it directly influences conversion, trust, and user behavior.


Tools for Choosing Effective Color Palettes

Professionals use curated palettes to avoid reinventing the wheel. Recommended resources from the lecture:

ToolPurposeHow to Use
Color HuntPre‑made, trendy color schemesBrowse themes (retro, warm, cold, summer, winter, happy, skin, kids, Christmas, wedding, pastel) → copy hex codes → use in CSS
Adobe ColorCustom palette generationPick a base color → choose harmony rule (e.g., triadic, complementary) → generate harmonised colors
Coolors (coolors.co)Interactive palette generator & visualiserLock preferred colors, press space for random alternatives; see how palette looks on sample UI (mobile, web, logo, charts, icons)

Exam tip: Memorise at least one of these tools by name – they appear in design‑related exam questions as “industry‑standard resources”.


Cultural Context & Accessibility

  • Red – celebration vs. danger (e.g., Indian weddings vs. Western stop signs)
  • Pink – culturally associated with femininity (Nykaa’s target demographic)
  • Contrast – high contrast for headlines/CTAs; softer contrast for body text. Must test for readability and avoid jarring combinations.
  • Accessibility – ensure sufficient colour contrast for visually impaired users (e.g., using tools like WebAIM contrast checker – implied, not explicitly mentioned in transcript, but a logical extension of “test for accessibility”).

Key Takeaways

  • Color theory = science + art of colour mixing, matching, and emotional impact.
  • Color psychology adds a biological and cultural layer: each colour triggers specific feelings (e.g., blue → trust, red → urgency).
  • Use high contrast to grab attention; low contrast to promote calm (Netflix vs. wellness sites).
  • Tools like Color Hunt, Adobe Color, and Coolors help generate professional palettes quickly.
  • Always consider cultural context and accessibility – what works in one market may fail in another.
  • Brand choices are deliberate: Apple (white), Timberland (brown), Nykaa (pink), Razorpay (blue) all signal their brand values through colour.

Typography

Typography is the craft of arranging text to make written language legible, readable, and visually appealing. It is not merely choosing a font—it shapes the user’s experience, conveys mood, and can make or break a message. Poor typography creates cognitive roadblocks; good typography feels invisible and effortless.

Legibility vs. Readability

These are the two pillars of typography.

  • Legibility – How easily individual characters can be distinguished (e.g., 0 vs. O). Fonts like Roboto have clear, well-defined glyphs.
  • Readability – How easily a reader can engage with a block of text. Depends on line spacing, font size, layout, and overall visual comfort.

Exam tip: Legibility is about letters; readability is about the reading experience. Both must be good.

Font Families

Fonts fall into two main families, plus decorative categories.

FamilyCharacteristicsCommon ExamplesTypical Use Cases
Serif“Feet” (serifs) at ends of strokes; classic, formal, authoritativeTimes New Roman, GeorgiaPrint media, legal documents, luxury brands, academic journals
Sans Serif“Without” serifs; clean, modern, minimalistHelvetica, Arial, Open Sans, Roboto, LatoDigital screens, apps, websites, tech startups, lifestyle blogs
ScriptCursive, decorative, elegant(e.g., Pacifico)Invitations, headings (avoid long paragraphs)
DisplayBold, unique, attention-grabbing(e.g., Playfair Display)Headlines, sparingly for impact
  • Serifs originated from ancient stone carving—sculptors naturally created these strokes because sharp 90° angles were hard to carve.
  • Sans literally means “without.”

Psychology of Fonts

Each font family evokes specific emotions:

  • Serif – Stable, traditional, authoritative.
  • Sans Serif – Clean, friendly, contemporary.
  • Script – Elegant, personal.
  • Display – Bold, impactful.

Choose fonts that align with your brand’s message (e.g., an eco-friendly brand might pair a serif heading with a sans serif body).

Word Superiority Effect

The brain recognizes entire words faster than individual letters. Lowercase letters have more distinct shapes, making them easier to read. Avoid all caps for body text—it slows reading and feels like shouting.

Visual Hierarchy

Typography guides the reader’s eye through content using size, weight, and spacing. For a blog post:

  • Title: Large, bold, display font → 46 px
  • Subheadings: Medium, clean (e.g., Roboto Bold) → 24 px
  • Body text: Small, readable (e.g., Open Sans) → 16 px or 12 px

The ratio between levels creates a clear structure.

Google Fonts

Google Fonts is a free library with preview tools to adjust size, spacing, and see live examples. Top picks: Open Sans, Roboto, Lora (sans serif). The Knowledge section (especially Readability and Accessibility) offers guidance on how fonts influence reading.

Spacing and Contrast

  • Whitespace (between lines, words, letters) is critical—too much or too little hurts readability.
  • Contrast between text and background must be sufficient. Use colour-checking tools to meet accessibility standards (e.g., Web Content Accessibility Guidelines).

Reading Styles

People read differently depending on context and device. Typography must adapt.

Reading StyleContextMobileDesktop
GlanceableHeadlines, notifications, key statsLarge, bold textProminent banners, CTAs
InterludeNavigation menus, summaries, snippetsCompact, clear labels, collapsible menusWell-structured sidebars, quick summaries
Long-formArticles, novelsResponsive layout, text adjusts to small screensLarger fonts, wider spacing, comfortable reading

Pick the ideal font and size based on the dominant reading style of your content.

Key Takeaways

  • Typography is a language that sets tone and guides the reader.
  • Legibility (character clarity) and readability (text comfort) are both essential.
  • Serif = formal/authoritative; Sans Serif = modern/friendly; Script = decorative; Display = impactful.
  • Use visual hierarchy (size, weight, spacing) to structure content.
  • Adapt typography to reading style: glanceable, interlude, or long-form.
  • Always test contrast and use tools like Google Fonts for pairing and preview.

Call to Action (CTA)

A call to action (CTA) is a trigger — often a button or link — designed to guide users toward a specific action: signing up, making a purchase, or learning more. Without clear CTAs, users feel lost; CTAs act as signposts directing them along a planned journey.

Why CTAs matter

  • Guide user behavior – steer visitors toward goals (filling a form, downloading an app, buying a product).
  • Increase engagement – well-placed CTAs keep visitors on the site longer.
  • Drive conversions – turn casual visitors into paying customers, subscribers, or leads.

Example: On a Flipkart product page, the “Add to Cart” and “Buy Now” buttons are bold, contrasting, and large — and they remain visible as the user scrolls (sticky).

Types of CTAs

TypePurposeExample
Lead generationCollect user information (email, phone) for follow-upGoDigit – “You want to see prices? Give us these two info points.”
PurchaseDrive direct salesFlipkart / Amazon – “Add to Cart”, “Buy Now”
Learn moreProvide additional information for users not ready to commitKia Cars – prominent “Know More” button on a dark luxury background
Social sharingEncourage users to share content on social mediaThe Better India – share buttons (Facebook, Twitter, LinkedIn, WhatsApp) appear after user scrolls
Free trial / demoEntice users to try software (common for SaaS)Zoho – “Get Started for Free”, “Try Zoho One”

Color psychology in CTAs

Colors are powerful psychological tools that evoke emotions and guide decisions. Contrast against the background is essential — a bright CTA on a neutral background pops.

ColorEffectExample
RedCreates urgency, grabs attentionZoho’s “Sign Up” / “Try Zoho One” buttons
GreenAssociated with success, positivityPayment gateways – “Proceed to Pay”
BlueEvokes trust, reliabilityBank login buttons; Facebook’s login button
Yellow / orangeEnergetic, eye-catchingFlipkart’s “Add to Cart” and “Buy Now” (orange/yellow on blue background); Shop Now buttons

Layout tips for CTAs

  • Above the fold – place CTAs where users see them without scrolling. MakeMyTrip: flight search inputs are at the top of the homepage.
  • Follow natural eye path – center of screen or below engaging content. Google Chrome: “The browser that’s built to be yours” hero text, then a centered “Download Chrome” button.
  • White space – surround the CTA with enough spacing to make it pop. Apple: plain layout followed by a single “Buy” button.
  • Sticky CTAs – keep CTAs visible as the user scrolls. Flipkart: “Add to Cart” and “Buy Now” remain accessible while browsing specifications and reviews.

Best practices

  1. Use action-oriented language – words that inspire immediate action: Buy Now, Sign Up, Download, Get Started, Add to Cart.
  2. Make the value proposition clear – explicitly state what the user gains (e.g., “Recharge Now” emphasizes convenience).
  3. Test and optimize – experiment with colors, placements, and text via A/B testing; keep what resonates.

Exam tip: A CTA’s effectiveness depends on the combination of color, contrast, placement, and language. Single-factor changes rarely suffice – always test holistic variations.

Key takeaways

  • CTAs are triggers that guide users toward a specific action.
  • They drive conversions, increase engagement, and shape user behavior.
  • Types include lead generation, purchase, learn more, social sharing, and free trial/demo.
  • Color choice (red, green, blue, yellow) taps into psychology; contrast with background is critical.
  • Placement strategies: above the fold, natural eye path, ample white space, sticky positioning.
  • Best practices: action-oriented copy, clear value, and continuous A/B testing.

User Interface (UI) Design

User Interface (UI) design is the craft of making a website intuitive, engaging, and user-friendly. It answers the question: how should elements be arranged so users find what they need without thinking? The core tools are visual hierarchy, layout, alignment, white space, and audience adaptation.

Visual Hierarchy – Guiding the Eye

Visual hierarchy determines the order in which information is noticed and processed. Users naturally gravitate to the biggest, boldest, and brightest elements first. Without hierarchy, all text looks identical and the reader has no focus—like an invitation where every line has the same size and color.

Ways to create visual hierarchy:

MethodHow it worksExample
Color & contrastBright, contrasting colors draw attention; muted colors recedeNykaa’s “Add to Bag” and “Vitamin C Moisturizer” highlighted in a pop color
SizeLarger elements grab attention firstGo Digit’s input fields for registration number and mobile number are enormous (half the size of Virat Kohli’s image) to drive conversions
PositionElements placed in the natural scan path get noticed earlierF‑pattern or Z‑pattern (see below)

Natural scanning patterns

  • F‑pattern: Users scan left to right across the top, then move down and scan again, forming an “F”. Most common for text-heavy pages.
  • Z‑pattern: Users scan left to right, then diagonally down to the left, then left to right again. Common for pages with a single strong focal point.

Exam tip: Always place your most important content (e.g., call‑to‑action, key headline) where the eye lands first—top left for F‑pattern, or top center for Z‑pattern.

Layout & Structure – Making Content Digestible

A good layout guides the user’s journey. After seeing many websites, users expect certain elements in certain places:

  • Navigation at the top (not interspersed in content).
  • Date/time typically in the bottom‑right corner (like a computer clock).
  • Share buttons towards the right edge.

Poor layout example: Times of India – cluttered, advertisements popping up, menu in the middle, datetime at the top, incomplete sentences. Overwhelms and discourages reading.

Better layout example: The Hindu – clear hamburger menu on top left, login on right, logo in center, content broken into “Premium”, “Latest News”, and “Main topics”.

Good layout example: TechCrunch – logo top‑left, hamburger top‑right, categories clearly at the top, biggest article on left with image, smaller headlines on right, ad placed at bottom‑right.

Balanced layout uses:

  • Short paragraphs interspersed with images/visuals.
  • Card‑based design (Google News shows “Your briefing” as a card).
  • Ideal line length for readability: 40–60 characters per line. Too long (like Wikipedia’s monotonous blocks) loses the reader; too short feels choppy.

Exam tip: Wikipedia is often cited as a bad layout example – long unbroken lines, no visual breaks. Compare with a page that uses shorter sentences and cards.

Alignment – The Polish Factor

Alignment is one of the simplest ways to elevate design. A mix of differently aligned titles creates visual discord (e.g., some text centered, some left‑aligned, some right‑aligned). Good alignment uses a single axis – either all centered or all left‑aligned.

  • Reduce alignment points: keep items along a few clean grid lines.
  • Example: Compare an invitation with scattered alignment (jarring) vs. fully centered or fully left‑aligned (ordered and polished).

White Space – Letting Design Breathe

White space (empty space) is an essential design element, not wasted area. It prevents clutter and directs focus. Luxury shops space out products → feels premium. Discount stores pack shelves → feels cheap. The same applies to UI:

  • Apple’s website: lots of white space → sophisticated, valuable.
  • Ad‑heavy, cluttered sites: feel low‑quality, stressful.

Designing for the Audience

Always tailor design to the intended users:

AudienceDesign approach
ChildrenVibrant colors, playful typography (even comic fonts)
Corporate usersMinimalist, professional, subdued colors
Finance / LegalTrustworthy, clear, structured
E‑commerceEye‑catching buttons, visuals that drive purchase
Teenage fashionTrendy, dynamic
MedicalClarity and trustworthiness

One style does not fit all. Choose colors, fonts, and content that resonate with the specific audience.

Key takeaways – UI Design

  • Visual hierarchy controls attention through color, size, and position.
  • Users scan in F or Z patterns – place key content accordingly.
  • Good layout includes clear navigation, short paragraphs, and ideal line length (40–60 chars).
  • Alignment must be consistent along a single axis; avoid mixed alignments.
  • White space makes a design feel premium and focused.
  • Always design for the audience – adapt colors, typography, and structure to their expectations.

Mobile vs Desktop Design

Desktop and mobile users interact very differently. With mobile usage booming in India, optimizing for both is essential. The differences span layout, navigation, input method, performance, and interactions.

Layout Differences

AspectDesktopMobile
Screen sizeLarge → multiple columns, side‑by‑side items, gridsSmall → single column, cards take full width
Content densityShow many items at once (Amazon: 4‑grid, scrollable bar, many categories at top)Show fewer items; categories hidden behind “Shop by Category”
Search barProminent, but not the only navigationHighly prominent – searching is the primary way to find products
CategoriesTop navigation bar, visible immediatelyBottom navigation or hamburger menu; more visual‑based

Responsive design ensures content adjusts seamlessly between devices.

Navigation

  • Desktop: Top navigation bar with dropdown menus – users can hover and see subcategories. Flipkart desktop shows fashion, electronics, home appliances with subcategories prominently.
  • Mobile: Relies on hamburger menus or bottom navigation bars to save space. No hover → subcategories are only available on the product page via filters.
  • Design rule: Simplify navigation for mobile – use collapsible menus or sticky navigation bars.

Touch vs Click

InputCharacteristicsUI implication
Desktop (mouse/trackpad)Precision clicks possible; small buttons OKButtons can be small (e.g., Amazon rating link, dropdown arrow)
Mobile (touch)Thumbs lack precision; large targets neededButtons must be larger with enough padding to avoid accidental clicks

Example: On Amazon’s desktop, the “ratings” link is tiny; on mobile, the same element is much larger.

Speed & Performance

  • Desktop: Faster internet, better processing → heavy websites with high‑res images, dynamic ads, videos, detailed listings load quickly.
  • Mobile: Often on 4G (inconsistent speeds) → need to compress images, reduce animations, and optimize scripts for fast loading.

Interactions

  • Desktop: Hover effects reveal sub‑menus, tooltips, etc.
  • Mobile: Hover does not exist. Use touch‑friendly alternatives: swipe gestures, accordions, tap‑to‑expand menus.

Key takeaways – Mobile vs Desktop

  • Layout: Desktop uses multiple columns; mobile uses single‑column cards.
  • Navigation: Desktop has visible top menus with dropdowns; mobile uses hamburger or bottom nav.
  • Touch targets: Mobile buttons must be larger to prevent mis‑taps.
  • Performance: Mobile needs optimised images and fewer animations for slower networks.
  • Interactions: Replace hover with tap, swipe, or accordion patterns.
  • Always test on both devices – mobile optimization is a necessity in mobile‑first markets.

Assignment: Analyze and Improve a Small Business Website

This assignment tests your ability to apply product management and design principles to a real-world scenario. You will analyze an existing small business website, identify strengths and weaknesses, and propose improvements that align design, functionality, and business goals. The goal is not just to spot flaws, but to understand how every design choice serves (or fails) the site’s primary objective.

Selecting a Website

Pick a real website for a small local business – e.g., a restaurant, hair salon, service provider. Ensure you can access and evaluate it.

Analysis Framework

Use the concepts from the module (color, typography, UI, user flow, content structure) to assess the site systematically.

AspectKey Questions
Business goalsWhat is the primary business objective (e.g., increase online orders, drive foot traffic, collect leads)? Do the design elements support that goal?
User needsWho are the users? What do they need (hours, menu, contact info)? How well are those needs addressed?
Design elementsEvaluate color schemes, typography, spacing/white space. Are they consistent, legible, and appropriate for the brand?
Call‑to‑actions (CTAs)Are CTAs clear, prominent, and effective? (e.g., “Order Now”, “Book Appointment”)
User experience (UX)Is navigation intuitive? Is information easy to find? Is the site optimized for its primary objective?

Deliverable

Create a concise report (2–3 pages) or a PPT presentation. Structure it into clear sections:

  • Brief introduction of the small business.
  • Strengths and weaknesses of the current site.
  • Actionable improvement suggestions with concrete examples.
  • Summary explaining how proposed changes align with business goals and improve user experience.

Include photos, screenshots, and visual mockups to show the difference between current and proposed designs.

Worked Example (from transcript)

Scenario: A bakery’s website goal is to increase online orders.
Observation: Site has small images and unclear CTAs.
Improvement: Add a prominent “Order Now” button and larger, appetizing product images.

Your recommendations should similarly connect a specific flaw to a concrete fix and the business goal it supports.

Exam tip: For this assignment, explicitly state why each improvement serves the business goal — that linking is the core skill.

Key takeaways

  • Analyze a real small‑business website against module principles.
  • Evaluate business goals, design, CTAs, UX, and user needs.
  • Suggest actionable improvements with examples.
  • Deliver a 2–3 page report or PPT with visuals.
  • Demonstrate how design and business goals must align.

CMS and WordPress Basics, online ready to use tools

Introduction: AI and WordPress

This module bridges two worlds: WordPress – the world's most widely used Content Management System (CMS) – and AI-powered development – using machine learning tools to generate, optimize, and debug code. The goal is to combine the simplicity of a CMS with the speed of AI to build websites faster and with fewer errors.

WordPress — A Content Management System

A Content Management System (CMS) is software that lets users create, manage, and modify website content without needing technical expertise. WordPress is the dominant CMS because it:

  • Simplifies website creation (no manual HTML/CSS required for basic pages)
  • Offers a huge ecosystem of themes and plugins
  • Is used by individuals, small businesses, and large enterprises alike

This module covers only the basics of WordPress – enough to understand how it fits into a developer's toolkit.

AI-Powered Development

Over the previous modules you built websites from scratch using HTML, CSS, and JavaScript. AI tools now let you do the same work faster and more efficiently by:

  • Generating layouts – AI can produce HTML/CSS structures from a description
  • Improving styling – suggest CSS refinements or responsive adjustments
  • Automating JavaScript functions – write and debug common scripts
  • Suggesting best practices – optimise code style, accessibility, performance

The core insight: AI does not replace the need to understand code, but it handles repetitive tasks and catches mistakes, freeing you to focus on architecture and design.

Key takeaways

  • WordPress is a CMS that lowers the barrier to building websites.
  • AI tools can write, optimise, and enhance code across HTML, CSS, and JavaScript.
  • This module combines both: learn WordPress basics and practise using AI to speed up web development.
  • The skills from earlier modules (manual coding) are still essential – AI is an accelerator, not a crutch.

Introduction to WordPress

WordPress is the world’s most widely used content management system (CMS), powering over 40% of all websites. It enables building websites without manual coding (HTML, CSS, JavaScript) through a drag‑and‑drop interface, making development faster, easier, and accessible to non‑developers.

Why Use WordPress?

  • Free & open source – anyone can download, use, and modify it.
  • Highly customizable – thousands of themes and plugins available.
  • User‑friendly – no coding knowledge required; intuitive admin interface.
  • CMS‑driven – content is managed via posts (dynamic, blog‑like) and pages (static).

WordPress.org vs WordPress.com

AspectWordPress.org (Self‑Hosted)WordPress.com (Hosted)
HostingYou bring your own domain & hostingWordPress.com takes care of hosting
ControlFull control over customization, themes, monetizationLimited customization (free tier)
SetupRequires manual download & installationSign up and start immediately
CostFree software + hosting feesFree basic plan; paid plans remove ads & add features
Recommended forProfessional sites, full ownershipBeginners, quick prototyping, learning

Exam tip: For a free, low‑commitment start to learn WordPress, use WordPress.com. For a production site with complete freedom, use self‑hosted WordPress.org.

Getting Started with WordPress.com

  1. Sign up at wordpress.com – create an account.
  2. Choose a domain – free subdomain (yoursite.wordpress.com) or a paid custom domain.
  3. Select a theme – pick a starting design (can be changed later).
  4. Set site title – e.g., “IIMB WordPress Demo”.
  5. Launch – the site is live immediately.

Creating Pages and Posts

  • Pages – for static content (Home, About, Contact).
    • Created from Pages → Add New.
    • Each page can be customized with blocks (text, images, forms, maps).
  • Posts – for dynamic, time‑sensitive content (blogs, news).
    • Created from Posts → Add New.
    • Automatically show up on the designated Blog page (set under Settings → Reading).
  • Navigation menus – add/remove links to pages, posts, or external URLs via the Navigation block on the editor.

Worked example (from the demo):

  • Homepage: added a logo, updated text “Welcome to the WordPress demo website”, linked a button.
  • About page: created with simple title and paragraph.
  • Contact page: added a contact form and a Google Maps block.
  • Blog page: displayed posts in a three‑column grid.

Customizing Appearance

  • Themes – change the entire look via Appearance → Themes.
    • Content remains intact when switching themes.
    • Recommended: finalize a theme before building content.
  • Styles – adjust colors, fonts, typography globally via the Styles panel.
  • Header & Footer – remain constant across all pages; editable in the template editor.
  • Blocks – drag‑and‑drop elements (images, buttons, galleries, maps, etc.) build pages without code.

Publishing and Maintenance

  • Changes must be saved and published to reflect on the live site.
  • After publishing, edits can be made anytime.
  • Paid plans unlock: custom domain, removal of WordPress.com branding, plugins (SEO, security), custom emails, and advanced user roles.

Intuition: WordPress treats the homepage as a template (often called Home or Front Page), other pages inherit its header/footer, and posts are managed separately. This structure makes it easy to update navigation or design once and have it propagate everywhere.

Key Takeaways

  • WordPress powers >40% of the web; it’s free, open‑source, and requires no coding.
  • WordPress.org (self‑hosted) gives full control; WordPress.com (hosted) is simpler for beginners.
  • Content is split into pages (static) and posts (dynamic, blog‑like).
  • The block editor (drag‑and‑drop) allows inserting and customizing text, images, forms, maps, etc.
  • Themes change the look without losing content; headers/footers are shared across pages.
  • Menus and navigation are managed via the Navigation block and can link to pages, posts, or external URLs.
  • Start with a free WordPress.com site to explore; move to self‑hosted for real‑world professional use.

Using AI & ChatGPT for Code Generation

Large Language Models (LLMs) like ChatGPT and Claude can generate, debug, and optimise code far faster than manual writing. The key to getting reliable, useful output is prompting — how you phrase your request. Knowing the basics of HTML, CSS, and JavaScript (covered in earlier modules) lets you guide the AI, evaluate its suggestions, and fix issues when the output is incomplete or wrong.

Why Prompting Matters

A vague prompt almost always yields unpredictable or broken code.

Prompt styleExampleResult
Too vague“Write me a text animation script.”Works sometimes, fails if your HTML structure differs. Often misses needed elements, uses different styling or logic each time.
Specific“Create a typing animation for these three sentences, loop infinitely, with a 2-second pause before backspacing at 50 ms, using only Vanilla JS.”Reliable, predictable, matches your exact intent.

Key insight: The AI does not know your webpage, your element IDs, or your desired behaviour. The more context you provide, the more likely the generated code will work as is.

Anatomy of a Good Prompt

A high-quality prompt should include:

  • What the code should do – e.g., “type out each character one by one, then delete characters one by one like a backspace”.
  • Structure of your webpage – e.g., “I have an HTML file with a <p id=“animated-text”></p> element”.
  • Constraints – e.g., “Don’t use jQuery”, “Only Vanilla JS”, “Use querySelector instead of getElementById”.
  • Behaviours – e.g., “Pause 2 s after finishing a sentence”, “Loop infinitely”.
  • Step-by-step breakdown – for complex tasks, break the request into smaller parts.

Step‑by‑Step Approach – Worked Example

The transcript walks through building a typewriter effect (from Module 7) using ChatGPT. The lesson: a single vague prompt produces a script that may work, but a broken‑down, iterative process yields a clean, modular, debug‑friendly result.

1. Vague prompt → Unpredictable

Prompt: "Write me a text animation script for my website."

Output: A script that uses getElementById("animated-text") but does not supply the HTML. When pasted into an existing page without that element, nothing works. Adding the element (<p id="animated-text"></p>) might make it run, but the next time you ask, the AI might give a completely different animation (e.g., fade‑in instead of typing).

2. Specific prompt → Works better

Prompt: "Give me a JavaScript that creates a typing animation for these three sentences:
[‘Hello world’, ‘Welcome’, ‘Goodbye’]. Loop through them. After each sentence, pause 2 s,
then delete characters one by one at a faster rate. Use only Vanilla JS."

Output: A self-contained script with sentenceIndex, charIndex, a isDeleting flag, and recursive typeEffect function. Works out of the box.

3. Iterative refinement → Modular, re-usable

Even the good output can be improved. The transcript shows how to guide ChatGPT to:

  • Replace a ternary operator with a clear if-else structure (for readability).
  • Add comments.
  • Switch from getElementById to querySelector (better practice).
  • Add a blinking cursor.
  • Wrap everything inside a DOMContentLoaded listener.
  • Keep functions separate and call them from a startAnimation dispatcher.

Why this works: Because you know the basics (DOM, querySelector, event listeners, function scope), you can tell the AI exactly what changes to make.

The Role of Foundational Knowledge

You do not need to be an expert, but you must understand core concepts to:

  • Guide the prompt – e.g., “Use querySelector because it’s more flexible”.
  • Evaluate output – When ChatGPT suggests “use clearInterval for better control”, you can judge whether it’s truly needed (here, it was not).
  • Debug errors – If the script references an element that doesn’t exist, you know to add it.
  • Break down problems – AI works best on small, logical steps (just like you would write code manually).

Exam tip: The most common mistake is trusting AI output without testing. Always copy the generated code into your project and verify it works. If you don’t understand the code, ask the AI to explain it first.

Best Practices Summary

PracticeWhy
Be specific about desired behaviour, HTML structure, and constraints.Reduces ambiguity; code matches your page.
Break tasks into steps – ask for one function at a time.Easier to debug and refine each piece.
Request comments and clear variable names.Improves readability for you and others.
Use your existing knowledge to correct or guide the AI.Keeps code aligned with best practices (e.g., querySelector over getElementById).
Question and iterate – never accept the first output as final.AI often makes small mistakes; you can fix them iteratively.
Leverage AI to explain unknown syntax (e.g., ternary operator, arrow functions).Fills knowledge gaps while coding.

Key takeaways

  • Vague prompts → random, often broken code. Specific prompts → reliable code.
  • A good prompt includes: task, HTML structure, constraints, behaviours.
  • Know the basics to guide the AI, evaluate its suggestions, and fix errors.
  • Break complex requests into smaller, logical steps.
  • Always test AI-generated code; iterate until it meets your exact needs.

Module Recap: Conclusion and Key Takeaways

The course laid a foundational web development skill set, starting from the fundamentals of how the internet works through the distinction between frontend and backend, then building practical competency in HTML, CSS, and JavaScript for creating interactive web pages. Finally, WordPress was introduced as a content management system (CMS) — a real-world tool for managing sites without deep code.

Core competencies acquired

  • Internet fundamentals — request/response, client-server model, domain names.
  • Frontend markup & styling — HTML for structure, CSS for layout and appearance.
  • Interactivity — JavaScript for dynamic behaviour (DOM manipulation, events).
  • CMS basics — WordPress as an “online-ready” tool for quickly building and managing content-driven sites.

Key takeaways

  • The course built a strong, general base — not just syntax, but the mental model for solving web problems.
  • This foundation opens doors to deeper specialisation: frontend frameworks, backend scripting, or full-stack development.
  • The digital world evolves constantly; the skills learned are transferable — the goal is to keep learning, creating, and innovating.

Transition tip: Treat this module as a launchpad. The WordPress section, in particular, is a stepping stone to managing live sites or exploring e‑commerce, membership, and custom theme development.

HTML Basics and Building Webpages

Introduction to HTML

HTML (HyperText Markup Language) is the foundation of every web page. It defines what content appears and how it is structured. CSS controls visual styling and JavaScript adds interactivity, but HTML alone is sufficient to build a complete, functional website. Without HTML, the other two layers have nothing to work on.

What “HyperText Markup Language” really means

  • HyperText – text that can link to other pages or resources. The first website ever (by Tim Berners‑Lee) consisted entirely of hyperlinked text; clicking a blue link navigates to another document.
  • Markup – extra annotations that tell the browser how to display or organise the content.
    Analogy: In WhatsApp, wrapping text in asterisks (*text*) makes it bold. The asterisks are a simple markup language. HTML works the same way, but uses tags instead of symbols.

HTML tags: the building blocks of a webpage

An HTML tag is a markup instruction enclosed in angle brackets (< >). Tags tell the browser what role a piece of content plays (e.g., heading, paragraph, link). A typical tag comes in an opening and closing pair.

Tag pairPurposeBrowser rendering
<h1>…</h1>Main headingLarge, bold text
<p>…</p>ParagraphNormal body text

Once a browser parses an HTML file, it uses these tags to decide font size, alignment, and hierarchy — no CSS required for basic structure.

Worked example: heading vs. plain text

The lecture demonstrated a simple HTML file:

Some normal text here.
<h1>This is a Heading</h1>
Some more normal text.

When rendered in the browser:

  • The first line appears as ordinary plain text.
  • The <h1>-tagged text is larger, bolder, and visually distinct — it is treated as a top‑level heading.

This shows that markup directly changes how content is displayed without any extra styling files.

Key takeaways

  • HTML = HyperText (links) + Markup (tags for structure).
  • Tags are the core mechanism: they define the role and appearance of content.
  • A complete website can be built with HTML alone; CSS and JavaScript are optional enhancements.
  • The <h1> tag is used for the most important heading; browsers render it larger and bolder by default.
  • Always pair opening and closing tags (e.g., <h1>…</h1>) — missing a closing tag can break the layout.

HTML Elements and Header Tags

HTML elements are the building blocks of web pages. An element consists of an opening tag, content, and a closing tag. For example, <p>Text</p> – the <p> is the opening tag, the content is "Text", and </p> is the closing tag. Some elements (e.g., <br>, <img>) have no closing tag and are called self-closing or void elements.

Heading Tags (<h1> to <h6>)

Heading tags define hierarchical headings, exactly like a book’s title, chapters, sections, and sub-sections. Intuitively, they tell both the browser and the reader: "This text is a heading, not just big bold text."

TagUsageVisual size (typical)
<h1>Main title (one per page recommended)Largest
<h2>Major sections / chaptersLarge
<h3>Sub-sections within an <h2>Medium
<h4>Sub-sub-sectionsSmaller
<h5>Low-level headingsSmall
<h6>Lowest heading levelSmallest

The browser renders each level with a distinct font size and weight, establishing a visual hierarchy.

Purpose: Semantic Structure & SEO

Headings do more than change font size. They:

  • Show relationships between content (e.g., a <h2> module belongs under the <h1> course title).
  • Help search engines (SEO) understand the page’s outline. Skipping levels (e.g., jumping from <h1> to <h3>) is considered poor practice.
  • Improve accessibility for screen‑reader users navigating by headings.

Example: “Website Development” Course Outline

<h1>Website Development</h1>
  <h2>Module 1: Introduction</h2>
    <h3>Video 1: Welcome Notes</h3>
    <h3>Video 2: HTTP and Request Response</h3>
  <h2>Module 2: Product Principles</h2>
    <h3>Video 1: Product Principles</h3>
    <h3>Video 2: Design</h3>
  <h2>Module 3: HTML Basics</h2>
    <h3>Video 1: Intro</h3>
    <h3>Video 2: Heading Tags</h3>

This structure mirrors a table of contents. The <h1> is the course title; <h2>s are modules; <h3>s are videos within each module. Nesting is consistent: no skipped levels.

flowchart TD
    H1["&lt;h1&gt; Website Development"] --> H2a["&lt;h2&gt; Module 1: Introduction"]
    H1 --> H2b["&lt;h2&gt; Module 2: Product Principles"]
    H1 --> H2c["&lt;h2&gt; Module 3: HTML Basics"]
    H2a --> H3a1["&lt;h3&gt; Video 1: Welcome Notes"]
    H2a --> H3a2["&lt;h3&gt; Video 2: HTTP and Request Response"]
    H2b --> H3b1["&lt;h3&gt; Video 1: Product Principles"]
    H2b --> H3b2["&lt;h3&gt; Video 2: Design"]
    H2c --> H3c1["&lt;h3&gt; Video 1: Intro"]
    H2c --> H3c2["&lt;h3&gt; Video 2: Heading Tags"]

Exam tip: Never skip heading levels (e.g., <h1><h3>). This hurts both visual consistency and SEO. Always nest <h2> under <h1>, <h3> under <h2>, etc.

Key Takeaways

  • An HTML element = opening tag + content + closing tag (unless void/self‑closing).
  • Heading tags (<h1>...<h6>) define content hierarchy, not just size.
  • Use one <h1> per page (the main title), then <h2> for major sections, <h3> for sub‑sections, etc.
  • Proper heading structure improves readability, accessibility, and SEO.
  • Do not skip levels – always descend sequentially.

HTML Structure

Every HTML file must follow a specific structure with mandatory elements to render correctly across all browsers. This foundation — called the HTML boilerplate — is a reusable template that ensures all essential parts are present before you add content.

Most code editors, such as VS Code, auto-generate this boilerplate: type ! and press Enter to produce the full structure.

The Document Type Declaration

The DOCTYPE declaration goes first:

<!DOCTYPE html>

This tells the browser you are using HTML5 (the modern version). Every HTML file must begin with this declaration.

The HTML Root Element

After DOCTYPE, the <html> tag wraps the entire document. This is the root element.

<html lang="en">

The lang attribute (e.g., lang="en" for English) is optional in basic usage but helps with accessibility and search engines.

The Head Element

The <head> section contains metadata — information for the browser, not visible on the page. Inside the head you typically find:

  • <meta charset="UTF-8"> — sets the character encoding to support most languages and symbols.
  • <meta name="viewport" content="width=device-width, initial-scale=1.0"> — ensures the page scales correctly on mobile devices (controls how content fits the screen width).
  • <title> — defines the text that appears on the browser tab. For example:
    <title>Intro to Webpages</title>
    

The head elements are children of the head tag (nested inside it). The title text is the only part immediately visible to the user (in the tab).

The Body Element

The <body> section holds all content visible to users: headings, paragraphs, images, links, lists, tables, etc.

<body>
  <h1>This is a webpage</h1>
</body>

Everything added inside the body appears in the browser's main viewport.

Document Hierarchy (Visual)

flowchart TD
    A[<!DOCTYPE html>] --> B[<html lang="en">]
    B --> C[<head>]
    C --> D[<meta charset>]
    C --> E[<meta viewport>]
    C --> F[<title>]
    B --> G[<body>]
    G --> H[Visible content: h1, p, img, etc.]

Indentation

HTML files use indentation (spaces or tabs) to show nesting — which elements are children of which. Proper indentation makes the code readable; it is not required by the browser but is a best practice.

Exam tip: You do not need to memorise the entire boilerplate — know that ! + Enter in VS Code generates it. But you must recognise what each part does. The most commonly tested elements: DOCTYPE, html, head, title, and body.

Key takeaways

  • DOCTYPE <!DOCTYPE html> declares HTML5 version to the browser.
  • <html> is the root element; often includes a lang attribute.
  • <head> holds metadata (charset, viewport, title) — not visible on the page.
  • <title> text appears in the browser tab.
  • <body> contains all visible content (headings, text, images, etc.).
  • The boilerplate can be auto-generated in VS Code (! + Enter).

Indentation in HTML

Indentation is the practice of adding leading spaces (or tabs) at the start of a line to visually show the nesting structure of HTML elements. It does not affect how the page is rendered, but it profoundly improves code readability, organization, and debuggability.

Why Indentation Matters

ReasonExplanation
ReadabilityClean, structured code allows you and others to understand the document hierarchy at a glance – vital as projects grow.
OrganizationThe visual hierarchy clearly shows where each element opens and closes.
DebuggingProper indentation makes it easy to spot unclosed tags (e.g., a missing </head>). Unindented code hides such errors.
CollaborationConsistent indentation across a team ensures everyone can parse the code quickly.

Indented vs. Unindented – A Side‑by‑Side Comparison

<!-- Indented (clear hierarchy) -->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Page Title</title>
  </head>
  <body>
    <h1>Hello World</h1>
  </body>
</html>

<!-- Unindented (structure invisible) -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Page Title</title>
</head>
<body>
<h1>Hello World</h1>
</body>
</html>

In the unindented version, it is difficult to see where <head> ends or whether <meta> has a closing tag. Indentation eliminates that confusion.

How to Apply Indentation

  • Manually: Press <kbd>Tab</kbd> or add spaces before each nested tag.
  • Automatically (recommended): Install Prettier (or a similar code formatter). Right‑click → Format Document (or use the keyboard shortcut). Prettier will re‑indent everything consistently.

Customising Indentation Preferences

SettingOptionsNotes
Tab widthUsually 2 or 4 spacesPersonal preference; many developers use 4.
Use tabs vs. spacesTabs (\t) or spaces ( )Most teams pick one and stick to it.
Setting locationExtensions → Prettier → settings (e.g., tabWidth, useTabs)Adjust to match your team’s style guide.

Nesting and the Parent‑Child Rule

Elements in HTML form a parent‑child (or ancestor‑descendant) relationship. Indentation mirrors this:

graph TD
    html --> head
    html --> body
    head --> meta
    head --> title
    body --> h1
  • Parent elements stay at the same horizontal level (e.g., <head> and <body> are both children of <html>, so they share the same indentation).
  • Child elements are indented one level deeper than their parent.
  • Closing tags should align vertically with their opening tag (e.g., </head> is at the same indentation level as <head>).

Exam tip: Even though indentation is not graded in a browser, an exam or interview question may present unindented code and ask you to spot a missing closing tag. Practise “reading” indentation to catch errors instantly.

Key takeaways

  • Indentation is purely for humans – it has zero effect on rendering.
  • It improves readability, organisation, debugging, and team collaboration.
  • Parent elements sit at the same level; children are indented one level deeper.
  • Use a formatter like Prettier to enforce consistent indentation automatically.
  • Always align opening and closing tags at the same indentation level.
  • Choose tabs or spaces and a tab width (commonly 2 or 4 spaces) and apply it uniformly.

Paragraph Tag

The paragraph element (<p>) is the fundamental HTML building block for grouping and formatting blocks of text on a webpage. It visually separates text into distinct chunks with spacing between them, making content readable and structured.

What the Paragraph Element Does

  • Starts with an opening tag <p> and ends with a closing tag </p>.
  • All text that belongs to the paragraph goes between these two tags.
  • Without it, plain text in HTML collapses into one continuous line, ignoring line breaks in the source code.

Plain Text vs. Paragraph Tags

ScenarioResult
Plain text (no <p> tags)All text runs together into one long line, even if written as multiple lines in the editor.
Text wrapped in <p>…</p>Each paragraph gets a visual space above and below, creating clear separation.

Why It Matters

  • Readability: Separate paragraphs are easier for humans to scan and read.
  • Accessibility: Screen readers use <p> tags to identify where a paragraph begins and ends. This helps visually impaired users navigate and understand content structure.

Practical Example — Placeholder Text

When building a website without final copy, placeholder (dummy) text gives a realistic preview of how the layout will look. Tools like lipsum.com generate text with varied line lengths and word sizes, providing a better sense of final spacing than repeated phrases.

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. ...</p>
<p>Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. ...</p>
<p>Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris ...</p>

Exam tip: The closing </p> tag is optional in some older HTML specifications, but always include it for proper structure and accessibility — many browsers will still render text without it, but screen readers and validators may break.

Key takeaways

  • Use <p> to split text into visually separated blocks.
  • Plain text in HTML runs together; <p> fixes that.
  • Paragraph tags improve readability for sighted users and navigation for screen readers.
  • Placeholder text (e.g., from lorem‑ipsum generators) helps preview layouts without real content.

Self-Closing Tags (Void Elements)

Self-closing tags (also called void elements) are HTML tags that require no closing tag and contain no content. Unlike regular tags (e.g., <p>...</p>) which wrap content between an opening and a closing tag, a self-closing tag is self-contained — it represents an element that doesn’t “wrap” anything.

Regular tagSelf-closing tag
<p>Some text</p><hr /> or <br>
Has opening tag + content + closing tagOnly an opening tag (optionally with a trailing slash)

The forward slash in a self-closing tag (e.g., <hr />) goes at the end, not the start as in a closing tag.

Exam tip: The slash is optional in modern HTML — browsers treat <br>, <br/>, and <br /> identically. However, using the trailing slash is recommended for consistency and readability.


Horizontal Rule <hr>

The <hr> (horizontal rule) element draws a thematic break — a horizontal line — across the page. It visually separates sections of content (e.g., between two paragraphs).

When to use: To divide content where a new section begins (not merely for decoration).

Example (from lecture):

<p>First paragraph text.</p>
<hr />
<p>Second paragraph text.</p>
  • The line extends from left to right edge.
  • No content is placed inside <hr> – it is purely visual.

Caution: Do not overuse <hr>. Too many horizontal rules make the page look cluttered.


Break Element <br>

The <br> (line break) element inserts a new line within the same block of text — it does not start a new paragraph. It is used when you need a line break inside a single paragraph or other block-level element.

When to use:

  • Poetry, addresses, song lyrics
  • Any text where line breaks are part of the content’s meaning

Example (address of IIM Bangalore):

<p>
  IIM Bangalore<br>
  Bilekhahalli, Bannerghatta Road<br>
  Bangalore – 560076
</p>

The rendered output keeps all lines inside one <p> tag, but displays on separate lines.

Exam tip: Never use <br> to add vertical spacing between paragraphs – use CSS margin or a new <p> tag instead. <br> is for structural line breaks within a single phrase.


Key Takeaways

  • Self-closing (void) tags have no content and no closing tag; examples: <hr>, <br>, <img>.
  • <hr> creates a horizontal rule to separate sections – use sparingly.
  • <br> adds a line break inside a paragraph – use for addresses, poetry, etc.
  • The trailing slash is optional in modern HTML but recommended for code clarity.
  • Browsers ignore text placed inside a self-closing tag (it is not meant to hold content).

Ordered and Unordered Lists and Nesting

Lists are a fundamental way to group related items on a webpage. The choice between ordered (<ol>) and unordered (<ul>) depends on whether the sequence of items carries meaning.

  • Unordered list (<ul>) – when the order of items does not matter. Rendered with bullet points.
  • Ordered list (<ol>) – when the sequence is important (e.g., step-by-step directions). Rendered with sequential numbers.

HTML structure

Each list type contains list items (<li>). The tags themselves (<ul>, <ol>) do not display content; only <li> elements produce visible list items.

<!-- Unordered list: order irrelevant -->
<ul>
  <li>Only one guest allowed</li>
  <li>No entry after 6:00 PM</li>
  <li>Wear fancy clothes for DJ night</li>
</ul>

<!-- Ordered list: order matters -->
<ol>
  <li>Arrive at Majestic Metro</li>
  <li>Take Metro to JP Nagar</li>
  <li>Rent a cab towards Vega City Mall</li>
  <li>Take right at Vega City → IIMB</li>
</ol>

Exam tip: The numbering in an ordered list is automatically generated based on the order of <li> elements in the code. Reordering <li> tags renumbers the output.

Nesting lists

Nesting means placing one HTML element inside another. A list can be nested inside a list item to create sub‑lists. This establishes a parent–child relationship in the document tree.

Example – adding warnings under the first step of the directions:

<ol>
  <li>Arrive at Majestic Metro
    <ul>
      <li>Be careful of pickpockets</li>
      <li>Metro closes at 10:00 PM</li>
    </ul>
  </li>
  <li>Take Metro to JP Nagar</li>
  <li>Rent a cab towards Vega City Mall</li>
  <li>Take right at Vega City → IIMB</li>
</ol>

The inner <ul> becomes a child of the first <li>, and its <li> elements are children of that inner <ul>. Nesting can continue further (lists inside lists inside lists).

Relationship diagram

flowchart TD
  A["<ol> (ordered list)"] --> B["<li> Arrive at Majestic Metro"]
  B --> C["<ul> (nested unordered list)"]
  C --> D["<li> Be careful of pickpockets"]
  C --> E["<li> Metro closes at 10:00 PM"]
  A --> F["<li> Take Metro to JP Nagar"]
  A --> G["<li> Rent cab..."]
  A --> H["<li> Take right at Vega City"]

Worked example – IIMB fest webpage

Building a simple invitation page with two sections:

  1. Points to remember (unordered list)
  2. Directions (ordered list with nested warnings)
<h1>IIMB Fest – Welcome!</h1>

<h2>Points to remember</h2>
<ul>
  <li>Only one guest allowed</li>
  <li>No entry after 6:00 PM</li>
  <li>Wear fancy clothes for DJ night</li>
</ul>

<h2>Directions to IIMB</h2>
<ol>
  <li>Arrive at Majestic Metro
    <ul>
      <li>Watch out for pickpockets</li>
      <li>Last metro at 10:00 PM</li>
    </ul>
  </li>
  <li>Take Metro to JP Nagar</li>
  <li>Rent a cab towards Vega City Mall</li>
  <li>Take right at Vega City → IIMB</li>
</ol>

Rendered output: the directions appear numbered, with bullet‑point sub‑notes under the first step.

Comparison: <ul> vs <ol>

Aspect<ul> (unordered)<ol> (ordered)
Default markerBullet pointNumber (1, 2, 3…)
When usedOrder irrelevantOrder matters (steps, rankings)
ExampleTips, features, ingredientsRecipes, directions, top‑10 lists

Exam tip: Nested lists must be placed inside an <li> element, never directly inside another <ul> or <ol>. Incorrect nesting breaks the document structure.

Key takeaways

  • Use <ul> for bullet lists (order unimportant); use <ol> for numbered lists (order required).
  • <li> tags are the only visible content containers inside lists.
  • Nesting is done by placing a full <ul> or <ol> inside an <li>.
  • Nesting creates parent‑child relationships analogous to an outline or tree structure.

Example Webpage: IIMB Fest 2024

A practical demonstration integrates previously learned HTML elements (headings, paragraphs, ordered lists, unordered lists) into a single functioning webpage.

Building the Boilerplate

Every HTML page begins with a boilerplate — the minimal structural template required for a browser to interpret the document correctly.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>IIMB Fest 2024</title>
</head>
<body>
    <!-- Content goes here -->
</body>
</html>
  • <!DOCTYPE html> declares this is an HTML5 document.
  • <html lang="en"> sets the language (English).
  • <meta charset="UTF-8"> ensures text encoding supports all characters.
  • <meta name="viewport"> scales the page to the device width (responsive).
  • <title> defines the browser tab title — not rendered on the page itself.
  • Everything inside <head> is metadata; the user does not see it.

Structuring Visible Content (the <body>)

Content inside <body> is rendered in the browser window. The page builds from top to bottom:

  1. Main heading<h1>IIMB Fest 2024</h1> – the most prominent text.
  2. Introductory paragraph<p>Welcome to the Best Fest in Bangalore.</p>
  3. Sub-heading for instructions<h2>Instructions</h2>
  4. Unordered list (bullet points)<ul> for items with no inherent order.
  5. Sub-heading for directions<h2>Directions to Reach</h2>
  6. Ordered list (numbered)<ol> for sequential steps.

Exam tip: Always match heading levels logically. An <h1> should be the page title; <h2> is a major sub-section. Skipping levels (e.g., <h1> then <h3>) breaks accessibility and semantics.

Adding Lists

The transcript uses two list types from prior videos:

List TypeTagUse CaseExample Content
Unordered (bullet)<ul> + <li>Items without sequenceOnly one guest allowed; No entry after 6 PM; Wear good clothes for DJ night
Ordered (numbered)<ol> + <li>Sequential stepsArrive at Mastic Metro; Be careful of pickpockets; Metro closes at 10 PM; Take metro to JP Nagar; Rent a cab; Take a ride at Vega City; Arrive at IIMB

The ordered list for directions demonstrates a step‑by‑step journey. The unordered list captures rules that have no specific order.

Viewing the Page

The lecturer uses Live Server (a VS Code extension) to auto‑refresh the page on save. The rendered page shows:

  • A bold heading "IIMB Fest 2024".
  • A welcoming paragraph.
  • A bullet‑point list of instructions.
  • A numbered list of directions.

The result is functional but visually plain – styling is deferred to CSS later in the course.

Connection to what comes next

The current page will be extended with anchor elements (<a>) for links and images (<img>). CSS will eventually add layout and beautification.

Key takeaways

  • Every HTML page starts with <!DOCTYPE html> and the <html>, <head>, <body> structure.
  • Use <h1> for the primary page heading; <h2> for major sections.
  • Unordered lists (<ul>) group items without ordering; ordered lists (<ol>) imply sequence.
  • Metadata in <head> (charset, viewport, title) is not rendered but is essential.
  • Tools like Prettier and Live Server improve developer workflow.

Anchor Element

The anchor element (<a>) creates hyperlinks — the foundation of web navigation. Without it, users couldn't jump between pages or resources. Intuitively, it turns a piece of text (or any inline content) into a clickable link.

Syntax & basic behaviour

<a>Visit IIMB</a>

This displays plain text, not a link. To make it functional, an attribute is needed.

The href attribute

href (hypertext reference) specifies the destination URL. It is tag-specific to the anchor element.

<a href="https://www.iimb.ac.in">Visit IIMB</a>

The text Visit IIMB becomes a blue, underlined link. Clicking it navigates to the given URL.

Exam tip: Without the href attribute, the anchor element is just inert text. The href attribute is what turns it into a hyperlink.

Nesting anchor tags inside other elements

An anchor can wrap any inline or block content (headings, list items, etc.).

Wrapping scopeResult
Entire heading <h2>Entire heading becomes a link
Entire list item <li>Whole item (including bullet) becomes clickable
Single word inside a list itemOnly that word is linked

Example:

<li><a href="...">Be careful of pickpockets</a></li>

Only the word "Be careful of pickpockets" is linked; the rest of the item is not.

Attributes: global vs. tag-specific

Attributes give HTML elements extra functionality.

  • Global attributes — apply to nearly every HTML element (e.g., draggable, hidden, class, id).
  • Tag-specific attributes — unique to certain elements (e.g., href for <a>, src for <img>).

Best practice: use official documentation (MDN) rather than memorising every attribute.

Examples of global attributes from the lecture

  • draggable="true" — allows the element to be dragged.
    <li draggable="true">Only one guest is allowed</li>
    
  • hidden="until-found" — hides the element until the browser finds a text match (e.g., via Ctrl+F).
    <li hidden="until-found">Wear good clothes</li>
    
    Searching for "wear" reveals the item.

The two most important global attributes, class and id, will be covered later (critical for CSS/JavaScript).


Key takeaways

  • The anchor element <a> creates hyperlinks only when its href attribute is present.
  • href is a tag-specific attribute; global attributes like draggable and hidden work on most elements.
  • An anchor can wrap entire elements (headings, list items) or just a part of them.
  • Never memorise all attributes – use MDN documentation to look them up.
  • class and id are essential global attributes that unlock styling and scripting.

Image Tag (<img>)

The image tag (<img>) embeds images — static photos, animated GIFs — into a webpage. It is a void element (no closing tag) because its content is the image itself, not text.

Attributes

AttributePurposeExample
srcSource – URL or file path to the imagesrc="https://..." or src="./images/photo.webp"
altAlternative text – fallback text if image fails, used by screen readers and SEOalt="IIMB logo"
heightHeight – sets image height in pixels (width adjusts automatically unless width also set)height="40"
widthWidth – sets image width in pixelswidth="100"

Exam tip: alt text is required for accessibility and SEO. If the image is purely decorative, use alt="" (empty) — never omit the attribute.

Image sources

  • Online (URL): Provide a direct link to the hosted image (e.g., from placeholder.co or picksome.photos).
    <img src="https://via.placeholder.com/150" alt="placeholder">

  • Local (relative path): Use the ./ notation to specify the file relative to the HTML document.
    <img src="./images/dj.gif" alt="DJ night"> – assumes an images/ folder in the same directory.

File formats & WebP

  • GIF – supports animation but larger file sizes.
  • JPEG/PNG – static images, larger sizes.
  • WebP – modern format by Google, produces smaller files while maintaining good quality, supports both static and animated images. Recommended for faster loading.

Practical example: Adding a logo and a GIF

<!-- Logo before heading -->
<img src="https://iimblogo.url/logo.png" alt="IIMB logo" height="40">

<!-- GIF inside a list item -->
<li>DJ Night
  <br>
  <img src="./images/dj.gif" alt="DJ night" height="100">
</li>

The height attribute prevents the logo from overwhelming the heading; the <br> places the GIF on a new line.

Key takeaways

  • <img> is a void element: no closing tag.
  • src specifies the image location (URL or local path).
  • alt provides fallback text and improves accessibility/SEO.
  • Use height and width to control image dimensions.
  • Prefer WebP for smaller file sizes and faster loading.

HTML Comments

HTML comments are invisible notes embedded in the source code. They are never rendered in the browser — only developers see them (via “View Page Source” or an editor). Their job: to document, remind, or temporarily disable code without affecting the page.

Syntax

<!-- This is a comment. It will not appear in the browser. -->
  • Start with <!--
  • End with -->
  • Everything between is ignored by the browser

Exam tip: Comments must be placed inside the HTML file. They do not hide CSS or JavaScript — they only hide the HTML markup they wrap.

Why use comments?

PurposeExample
Notes & reminders<!-- TODO: add a contact form later -->
DebuggingTemporarily comment out a <li> to see if it causes a layout problem.
DocumentationExplain a tricky section: <!-- anchors inside list items make the whole bullet clickable -->
CollaborationLeave instructions for teammates: <!-- Sarah: please check the link target -->

Worked example (from the lecture)

Original code — a note that shows up in the browser (bad):

<p>For reference: If I add anchor around list item, the entire list item including the bullet point becomes a link</p>

Fix — wrap it in a comment:

<!-- For reference: If I add anchor around list item, the entire list item including the bullet point becomes a link -->

Now it disappears from the rendered page.

VS Code shortcut

  • Windows/Linux: Ctrl + /
  • Mac: Cmd + /

Select the line(s) you want to comment/uncomment and press the shortcut.

Key takeaways

  • Comments use <!-- ... --> and are invisible in the browser.
  • Use them for notes, reminders, debugging (temporarily disable code), and collaboration.
  • They do not hide content from users who view the source.
  • The editor shortcut (Ctrl+/ or Cmd+/) makes toggling comments fast.
  • Comments keep code clean and help future you (or your team) understand intent.

Inline Comments

Inline elements share horizontal space with other elements, unlike block elements which occupy the full available width of their parent container. This distinction is fundamental to HTML layout and controls how content flows on the page.

Block vs Inline – The Core Difference

A block-level element always starts on a new line and takes up the entire horizontal space available, stretching from left to right. An inline element occupies only the space needed for its content, allowing subsequent elements to sit beside it on the same line.

PropertyBlock elementsInline elements
Horizontal spaceFull width availableOnly the width of content
Line break before/afterAlways starts on a new lineNo automatic line break
Typical examples<h1>–<h6>, <p>, <hr>, <div><a>, <img>, <span>, <strong>
Can containInline elements or other blocksOnly other inline elements (or text)

Worked example (from demo):
Placing two <h1> elements and an <h2> side by side in code causes each to appear on its own line in the browser because they are blocks. Below them, an <img> and an <a> tag placed consecutively appear on the same line because they are inline.

When inspected in Chrome DevTools, the hover highlight for block elements spans the entire browser width, while the highlight for inline elements only covers the element’s bounding box.

Generic Containers: <div> and <span>

These are neutral, semantically empty elements used purely for grouping and styling.

  • <div> – A generic block container. Wrapping any content inside <div> forces that content onto a new line and causes the div to occupy full width.

  • <span> – A generic inline container. It does not change layout; it allows targeting a specific portion of text or inline content without affecting flow.

Example – <div> effect:
Wrapping an anchor tag <a href="...">IIMB link</a> with <div> pushes the link to the next line because the div is a block element.

Example – <span> effect:
Inserting <span> around a word inside a paragraph <p> produces no visual change; the span simply marks that portion for later styling or scripting.

<!-- Block element wrapping inline content -->
<div>
  <a href="https://www.iimb.ac.in">IIMB link</a>
</div>

<!-- Span within a paragraph -->
<p>Some sample text. <span>This is the second line.</span></p>

Exam tip: Use <div> for structural sections (like headers, footers, columns) and <span> when you need to style a small piece of text within a sentence. Mixing them up can break your layout.

Key Takeaways

  • Block elements (<h1>, <p>, <div>, <hr>) occupy the full width and stack vertically.
  • Inline elements (<a>, <img>, <span>) sit side‑by‑side and only take the space they need.
  • <div> is a generic block container; <span> is a generic inline container.
  • Neither <div> nor <span> has default styling; they are purely structural.
  • Use Chrome DevTools hover highlighting to quickly identify whether an element is block or inline.

Forms

Forms are HTML elements that collect user input and send it to a server for processing. Every login page, search bar, or checkout flow relies on a form. A form itself is an invisible container – it only renders content through the input elements and labels placed inside it.

The action attribute

The action attribute tells the browser which URL to send the collected data to.
When a form is submitted (e.g., by pressing Enter in a search field), the browser builds a request URL by taking the action URL and appending a query string containing the form data.

  • Example from Amazon: the search form has action="/s" and a text input named k. Submitting laptops takes the browser to /s?k=laptops.

Exam tip: The form’s action does not need to be a full URL – it can be a relative path. The data is encoded as key=value pairs in the query string (GET method unless specified otherwise).

Common input types

HTML provides many input types, each triggering a specific browser control (text box, color picker, numeric spinner, etc.). Not all types are supported in every browser, but modern browsers handle most consistently.

type attributeRendered asUse case
textSingle-line text boxUsername, search term
emailText box with email format hintEmail address
numberNumeric spinner (with up/down arrows)Age, quantity
colorColor pickerFavourite colour
passwordObscured text boxPassword input
submitButton that submits the formForm submission (next video)

The name attribute is essential – it becomes the key in the query string sent to the server. Without a name, the input’s value is not transmitted.

Input attributes

Every input element can carry:

  • type – specifies the kind of input control.
  • name – the key used when submitting the data (e.g., username, email).
  • id – a unique identifier for the element, used for linking labels and for CSS/JavaScript.

Labels

A label is a textual description associated with a specific input. Clicking the label automatically focuses or activates the linked input – improving accessibility and usability.

Two ways to associate a label with an input:

  1. for attribute – set for to the id of the target input.

    <label for="username">Enter username</label>
    <input type="text" id="username" name="username">
    
  2. Wrapping – place the input inside the label tag. No for needed.

    <label>Enter username
        <input type="text" name="username">
    </label>
    

Both render identically. The for method is more explicit and works even when the label and input are not adjacent in the markup.

Important: The label must be placed near its input in the HTML – they do not magically rearrange. Use <br> or <p> to control vertical layout.

<form action="/submit-form-info">
    <label for="username">Enter username</label>
    <input type="text" id="username" name="username"><br><br>

    <label for="email">Enter your email</label>
    <input type="email" id="email" name="email"><br><br>

    <label for="age">Mention your age</label>
    <input type="number" id="age" name="age"><br><br>

    <label for="favcolor">Pick your favourite color</label>
    <input type="color" id="favcolor" name="color">
</form>

Form structure diagram

flowchart TD
    A[Form element] --> B[action attribute]
    A --> C[Input elements]
    C --> D[type]
    C --> E[name]
    C --> F[id]
    A --> G[Labels]
    G --> H["for = id"]
    G --> I["Wrapping input inside label"]

Key takeaways

  • A form is a container; nothing is visible until you add inputs.
  • The action attribute defines where the data is sent (URL or relative path).
  • Every input should have a name – without it, the input’s value is not submitted.
  • Common input types include text, email, number, color, password, and submit.
  • Labels improve usability; associate them via for (matching input id) or by wrapping the input.
  • Inputs without name are invisible to the server – a frequent beginner mistake.

Buttons in HTML Forms

A button is the primary way users interact with a form — submitting data, resetting fields, or triggering custom actions. Intuitively: every click needs a purpose; the type attribute tells the browser what that purpose is.

The button element

Syntax:

<button type="submit|button|reset">Visible Text</button>

The text between the opening and closing tags becomes the button's label. The type attribute controls its default behavior.

Button types and their behavior

type valueDefault actionUse case
submit (or omitted)Submits the form to the URL in the action attributeStandard form submission
buttonNo default action; does nothing by itselfCustom JavaScript-driven actions
resetResets all form fields to their initial valuesClearing a form (not covered in this lecture)

Important: If type is not specified, the browser defaults to type="submit". This can cause unintended form submissions if a developer forgets to set the type.

Inside vs. outside a form

  • Button inside a form – A submit button submits the form it belongs to. A button type button does nothing until JavaScript is attached.
  • Button outside a form – Even with type="submit", a button that is not inside any <form> element has no default submit behavior. It exists solely for JavaScript-based actions.

Exam tip: The most common exam trap — a button with no type attribute defaults to submit, even if the developer intended it to be a plain button. Always explicitly set type="button" to prevent accidental form submission.

Key takeaways

  • The <button> element always requires a closing tag; the text inside is the label.
  • Default type is submit when inside a form.
  • type="button" removes the default submit action — useful for custom JavaScript.
  • Buttons outside a form never submit anything, regardless of type.
  • Understanding button types is essential for controlling form behavior and enabling interactive web applications.

The name Attribute in HTML Forms

Every form input that sends data to a server needs a name attribute. Without it, the user’s input is invisible to the backend.

Intuition: a form is like a delivery slip. The name is the label on the blank (e.g., “email”), and the value is what the user writes in that blank. The server can only read data that has a label.

How form data is sent

When a form is submitted (GET method by default), the browser collects every <input> that has a name attribute and assembles key-value pairs:

<key> = <value>

These pairs are appended to the form’s action URL as a query string, starting with ?, each pair separated by &.

Structure:

action-url?name1=value1&name2=value2&...

Exam tip: The name attribute is what appears as the key in the query string. The id attribute is for CSS/JavaScript — it is not sent to the server.

Worked example

Given this form:

<form action="/submit-form-info">
  <input name="username" value="">
  <input name="email" value="">
  <input name="age" value="">
  <input name="color" type="color">
  <button type="submit">Submit</button>
</form>

User fills:

  • username → govind
  • email → govind.iimb.ac.in
  • age → 99
  • color → #aabbcc

On submit, browser navigates to:

/submit-form-info?username=govind&email=govind.iimb.ac.in&age=99&color=%23aabbcc

Notice special characters (like #) are URL-encoded (%23).

What happens when name is missing

If an input has no name attribute, its value is never sent in the request.

Example: Remove name="email" from the form above.

Submitted query string:

/submit-form-info?username=govind&age=99&color=%23aabbcc

The email field is completely absent — the server receives no data for that input.

Submission flow

flowchart LR
  A[User fills inputs] --> B[Browser collects name=value pairs]
  B --> C{Every input has a name?}
  C -->|Yes| D[Append to URL as query string]
  C -->|No| E[Missing inputs are skipped]
  D --> F[Server reads keys to process data]

Why backend developers care

Server-side code (PHP, Python, Node.js, etc.) references form data by the name value. If the name is missing or misspelled, the server cannot retrieve that piece of data.

name presentData sent to serverServer can process
YesYesYes
NoNoNo

Key takeaways

  • The name attribute labels an input’s value as a key in the key‑value pair sent to the server.
  • Form data is transmitted via the query string (in GET) as ?key1=value1&key2=value2.
  • Inputs without a name attribute are omitted from the request.
  • Every input that should be processed by the backend must have a unique, meaningful name.
  • Special characters in values are URL‑encoded automatically.

Forms: Building a Registration Form

HTML forms allow users to input data and send it to a server. Intuitively, think of a form as a container that collects information (e.g., name, email) and packages it into key=value pairs appended to the URL (or sent via POST). Every input field needs a name (the key) and a value (the user’s entry or a fixed option) to be transmitted.

Form Structure

The <form> element defines the container. Two key attributes:

  • action – the URL where data is sent (here "/register" placeholder).
  • methodGET (default, seen in URL) or POST (not shown, but implied).

Inside the form, each input is paired with a <label> for accessibility. The label’s for attribute matches the input’s id.

<form action="/register">
  <!-- inputs and button go here -->
  <button type="submit">Register</button>
</form>

Exam tip: A form with only a submit button and no inputs does nothing – data must come from named input elements.


Text Input & Validation: type="text", required, minlength, maxlength

Collect a participant’s name using a text input. Use required (Boolean attribute) to prevent submission when empty. Enforce length with minlength and maxlength.

<label for="name">Enter your name</label>
<input type="text" id="name" name="name" required minlength="2" maxlength="12">
  • required – browser shows a popup: “Please fill out this field”.
  • minlength="2" – “Please lengthen this text to 2 characters or more”.
  • maxlength="12" – prevents typing beyond 12 characters.
  • Validation is client-side (browser built-in); appearance varies by browser.

Email Input: type="email"

For capturing participant email addresses that must contain an @ symbol. The type="email" attribute invokes built-in email validation.

<label for="email">Enter your email</label>
<input type="email" id="email" name="email">
  • Submitting govi (no @) → “Please include an '@' in the email address.”
  • On valid submission, the @ is URL-encoded as %40.

Dropdown (Select) Menu: <select> + <option>

Use a dropdown to limit T‑shirt size choices. The <select> element’s name attribute becomes the key; each <option> has a value sent as the value.

<label for="tshirt-size">Select t-shirt size</label>
<select id="tshirt-size" name="tshirt-size">
  <option value="">Please select an option</option>
  <option value="38">38</option>
  <option value="40">40</option>
  <option value="42">42</option>
  <option value="44">44</option>
</select>
  • Options render in the order written in the HTML.
  • If <option> lacks a value attribute, nothing is submitted for that choice.
  • The name of the <select> is the key; the value of the chosen <option> is the value.

Checkbox: type="checkbox"

Use a checkbox to obtain agreement (e.g., to fest rules). To make it mandatory, add required.

<label for="terms">Do you agree to all conditions?</label>
<input type="checkbox" id="terms" name="terms" value="agreed" required>
  • Unchecked: the name key is omitted entirely from the submission.
  • Checked: sends terms=agreed (if value is set) or terms=on (default).
  • With required, browser prevents submission until the box is ticked.

Radio Buttons: type="radio"

Allow mutually exclusive selection, e.g., “Student” vs. “Alumni”. All radio buttons in the same group must share the same name attribute. Provide explicit value attributes to send meaningful data.

<label for="alumni">Alumni</label>
<input type="radio" id="alumni" name="attendee-type" value="alumni">
<label for="student">Student</label>
<input type="radio" id="student" name="attendee-type" value="student">
  • Same name ensures only one radio can be selected at a time.
  • If value is missing, the sent value is on (unhelpful).
  • The for label linkage allows clicking the label to select the radio.

How the Submission URL Works (GET method)

When the form is submitted via GET, all key=value pairs are appended to the action URL:

/register?name=Govind&email=govind%40gmail.com&tshirt-size=42&terms=agreed&attendee-type=alumni
  • Keys come from the name attribute of each input/select.
  • Values come from the value attribute (or user typed text for text/email).
  • @ is encoded as %40.
  • Unchecked checkboxes and unselected radio buttons do not appear.
flowchart LR
  A[User fills form] --> B{Client-side validation}
  B -->|Fail| C[Browser shows error]
  B -->|Pass| D[Form submitted]
  D --> E[Data appended to URL as key=value]
  E --> F[Server receives data]

Exam tip: The name attribute is essential – without it, the input’s data is never sent. For checkboxes and radios, always provide a meaningful value attribute.


Worked Example: Complete Registration Form

<form action="/register">
  <!-- Name -->
  <label for="name">Enter your name</label>
  <input type="text" id="name" name="name" required minlength="2" maxlength="12">
  <br><br>

  <!-- Email -->
  <label for="email">Enter your email</label>
  <input type="email" id="email" name="email">
  <br><br>

  <!-- T-shirt size dropdown -->
  <label for="tshirt-size">Select t-shirt size</label>
  <select id="tshirt-size" name="tshirt-size">
    <option value="">Please select</option>
    <option value="38">38</option>
    <option value="40">40</option>
    <option value="42">42</option>
    <option value="44">44</option>
  </select>
  <br><br>

  <!-- Checkbox -->
  <input type="checkbox" id="terms" name="terms" value="agreed" required>
  <label for="terms">Do you agree to all conditions?</label>
  <br><br>

  <!-- Radio buttons -->
  <input type="radio" id="alumni" name="attendee-type" value="alumni">
  <label for="alumni">Alumni</label>
  <input type="radio" id="student" name="attendee-type" value="student">
  <label for="student">Student</label>
  <br><br>

  <button type="submit">Register</button>
</form>

Submission sample (if alumni selected):

/register?name=Govind&email=govind%40iimb.ac.in&tshirt-size=42&terms=agreed&attendee-type=alumni

Key takeaways

  • A form sends data as key=value pairs; keys come from name attributes, values from user input or value attributes.
  • required, minlength, maxlength, and type‑specific validation (email, number) provide client‑side checks.
  • Use <select> with <option> for dropdowns; the value attribute determines what is sent.
  • Checkboxes send nothing when unchecked; use required to force agreement.
  • Radio buttons with the same name enforce single selection; always set a value for each.
  • Labels linked by for (matching id) improve usability and accessibility.

HTML Tables

HTML tables organise data into rows and columns — like a spreadsheet in the browser. Use them whenever you need to display tabular data: product comparisons, statistics, schedules.
Crucial rule: tables are for data, not for page layout (use CSS for layout).


Table Structure

Every table is built from three core elements nested in a strict hierarchy:

flowchart TD
    A[`<table>`] --> B[`<tr>` (row)]
    B --> C[`<th>` header cell or `<td>` data cell]
    B --> D[more cells]
    A --> E[more `<tr>` rows]
  • <table> — the container.
  • <tr> — a table row. Rows are stacked vertically.
  • <td> — a data cell.
  • <th> — a header cell (automatically bold and centred; semantically marks a row/column heading).

Browsers often auto-insert <tbody> around data rows, but you do not need to write it explicitly.

Exam tip: Always use <th> for headers — this is both semantic and helps accessibility. Never style a <td> to look like a header.


Basic Table (no spanning)

NameHeight (cm)Height (in)
Raja18073.5
Ram16567.5
Mohan17270.0
<table>
  <tr>
    <th>Name</th>
    <th>Height (cm)</th>
    <th>Height (in)</th>
  </tr>
  <tr>
    <td>Raja</td>
    <td>180</td>
    <td>73.5</td>
  </tr>
  <tr>
    <td>Ram</td>
    <td>165</td>
    <td>67.5</td>
  </tr>
  <tr>
    <td>Mohan</td>
    <td>172</td>
    <td>70.0</td>
  </tr>
</table>

Each <tr> contains the same number of cells. Header row uses <th>, data rows use <td>.


Spanning Cells: rowspan and colspan

Sometimes a cell needs to stretch across multiple rows or columns — exactly like merging cells in Excel.

NameHeight
in cmin inches
Raja18073.5
Ram16567.5
Mohan17270.0
  • colspan="n" — cell spans n columns horizontally.
  • rowspan="n" — cell spans n rows vertically.

Code for the table above:

<table>
  <tr>
    <th rowspan="2">Name</th>
    <th colspan="2">Height</th>
  </tr>
  <tr>
    <th>in cm</th>
    <th>in inches</th>
  </tr>
  <tr>
    <td>Raja</td>
    <td>180</td>
    <td>73.5</td>
  </tr>
  <tr>
    <td>Ram</td>
    <td>165</td>
    <td>67.5</td>
  </tr>
  <tr>
    <td>Mohan</td>
    <td>172</td>
    <td>70.0</td>
  </tr>
</table>

When you use rowspan or colspan, omit the cells that would have been in the merged area. The total number of logical columns per row must stay consistent.

Exam tip: Count columns carefully. In the example above, the first row has 2 cells (rowspan + colspan), the second row has 2 cells (both <th>), and each data row has 3 <td> — but because the first cell of each data row is already occupied by the rowspan from row 1, you only write <td> twice per data row. Mistaking the count is a common error.


Real‑World Example: IIMB Fest Event Schedule

Add a schedule table to the IIMB Fest website (below the forms, separated by <hr>):

<h2>Event Schedule</h2>
<table>
  <tr>
    <th>Timings</th>
    <th>Event</th>
    <th>Venue</th>
  </tr>
  <tr>
    <td>9:00 AM</td>
    <td>Opening Ceremony</td>
    <td>Main Auditorium</td>
  </tr>
  <tr>
    <td>10:00 AM</td>
    <td>Panel Discussion</td>
    <td>Seminar Hall</td>
  </tr>
  <tr>
    <td>12:00 PM</td>
    <td>Lunch</td>
    <td>Cafeteria</td>
  </tr>
  <tr>
    <td>2:00 PM</td>
    <td>Cultural Activities</td>
    <td>Amphi Theater</td>
  </tr>
</table>
TimingsEventVenue
9:00 AMOpening CeremonyMain Auditorium
10:00 AMPanel DiscussionSeminar Hall
12:00 PMLunchCafeteria
2:00 PMCultural ActivitiesAmphi Theater

Key Takeaways

  • Tables are built from <table>, <tr>, <td> (data), and <th> (headers).
  • Rows are defined with <tr>; cells go inside rows.
  • Use rowspan to merge cells vertically and colspan to merge horizontally.
  • Tables are for tabular data only — never use them for page layout.
  • Always include proper header cells (<th>) for accessibility and clarity.
  • Styling (borders, colours, spacing) is done with CSS, not HTML.

Semantic HTML

Semantic HTML uses meaningful tags that describe the purpose of content, not just its appearance. Instead of generic containers like <div> or <span>, you use tags such as <header>, <footer>, <main>, <section>, <nav>, <article>, and <form>. These make the structure of a webpage clear to browsers, developers, search engines, and assistive technologies.

Why semantic HTML matters

BenefitExplanation
AccessibilityScreen readers and assistive tech can interpret content better — e.g., a <nav> tells the reader "this is a navigation region".
SEOSearch engines give more weight to content inside semantic tags (e.g., <h1> for the top heading) and index pages more effectively.
Code maintainabilityDevelopers instantly understand what each block is supposed to do — finding, updating, and collaborating becomes much easier.

Semantic vs. non-semantic HTML

Non-semanticSemanticPurpose
<div><header>, <footer>, <section>, <nav>, <main>, <article>Defines a structural region
<span><em>, <strong>, <time>, <summary>Adds inline meaning

Definition – semantic in programming: the meaning of a piece of code.
In HTML, an <h1> element is semantic because it tells the browser (and screen reader) that the wrapped text is the top-level heading.

Key semantic elements

ElementTypical use
<header>Top of a page/ section — logo, main heading, introductory navigation; consistent across pages
<nav>A block of navigation links (e.g., <a> links to other pages)
<main>The primary content of the page (should appear only once)
<section>Groups related content into logical, reusable blocks
<article>A self-contained composition (e.g., a blog post, news item)
<footer>Bottom of a page/ section — author info, copyright, links
<form>Groups form inputs (already semantic itself)
<time>Represents a date or time in a machine-readable way

Transforming the IIMB Fest page

Walkthrough of adding semantic tags to the example webpage (IIMB Fest). The result has no visual change — all improvements are in the underlying code structure.

Step 1: Wrap top content in <header>

<header>
  <img src="..." alt="IIMB Logo">
  <h1>IIMB Fest</h1>
  <p>Welcome to the annual fest...</p>
</header>
  • The three top elements (image, main heading, introductory paragraph) become one logical unit.

Step 2: Wrap primary content in <main>

<main>
  <!-- all sections from first <h2> to table end -->
</main>
  • <main> explicitly marks the central content of the page; only one <main> per page.

Step 3: Split main content into <section>s

Logical grouping:

SectionContent
Section 1Instructions (heading + ordered list)
Section 2Directions (heading + unordered list)
Section 3Registration form (heading + <form>)
Section 4Event schedule (heading + <table>)
<main>
  <section>
    <h2>Instructions</h2>
    <ol>...</ol>
  </section>
  <hr>
  <section>
    <h2>Directions</h2>
    <ul>...</ul>
  </section>
  <section>
    <h2>Registration</h2>
    <form>...</form>
  </section>
  <section>
    <h2>Event Schedule</h2>
    <table>...</table>
  </section>
</main>
  • Sections make code easier to read and reuse; each has a distinct heading.

Step 4: Add semantic table elements

Replace the plain <table> with structure:

<table>
  <thead>   <!-- group header row -->
    <tr>
      <th>Event</th>
      <th>Date</th>
      <th>Time</th>
    </tr>
  </thead>
  <tbody>   <!-- group main data rows -->
    <tr><td>Inauguration</td><td>Oct 10</td><td>10:00</td></tr>
    <tr><td>Workshop</td><td>Oct 11</td><td>09:00</td></tr>
    <tr><td>Concert</td><td>Oct 12</td><td>19:00</td></tr>
    <tr><td>Closing</td><td>Oct 13</td><td>17:00</td></tr>
  </tbody>
  <!-- <tfoot> can be added for summary rows -->
</table>
  • <thead> – row(s) that act as column headers.
  • <tbody> – the main data.
  • <tfoot> – optional footer (e.g., totals, notes).

Exam tip: Semantic table elements (<thead>, <tbody>, <tfoot>) improve accessibility and are frequently tested. The browser still renders the same visual table, but screen readers can announce header cells properly.

Final structure diagram

flowchart TD
    body[<body>] --> header[<header>]
    body --> main[<main>]
    main --> section1[<section> - Instructions]
    main --> section2[<section> - Directions]
    main --> section3[<section> - Registration]
    main --> section4[<section> - Event Schedule]
    section4 --> table[<table>]
    table --> thead[<thead>]
    table --> tbody[<tbody>]
  • No visual change – only code structure improvements.

Key takeaways

  • Semantic HTML uses meaningful tags (<header>, <main>, <section>, etc.) instead of generic <div>.
  • Benefits: accessibility (screen readers), SEO (better indexing), and code maintainability.
  • Common semantic elements: <header>, <nav>, <main>, <section>, <article>, <footer>, <form>, <time>.
  • Tables have semantic children: <thead> (header row), <tbody> (data rows), <tfoot> (footer row).
  • Adding semantics improves the meaning of the page without changing its appearance.

File Paths

File paths are the addresses that tell a web browser or program where a file (image, CSS, HTML, etc.) lives inside a project. There are two styles: absolute paths (full route from the root) and relative paths (route from the current working file).

Intuition: Directions to a location

  • Absolute path – start from the root (e.g., “India” → Karnataka → Bangalore → Bannerghatta Road → IIM Bangalore). Unchanging, works from anywhere.
  • Relative path – start from your current location. If you are already in Bangalore: “Bannerghatta Road → IIM Bangalore”. If in Chennai: “Go from Chennai to Bangalore → Bannerghatta Road → IIM Bangalore”. Shorter, flexible.

Absolute vs. Relative Paths

AttributeAbsolute PathRelative Path
Starts fromRoot of filesystem (e.g., C:\ on Windows, / on Mac/Linux)Current file’s directory
ExampleC:\Users\Desktop\project\image.jpg./image.jpg or ../parent-folder/image.jpg
Dependency on machineTied to one machine’s folder structurePortable across machines
LengthLong, includes full hierarchyShort, only necessary segments
Use in web hostingMay break because server root differsWorks both locally and on any server

Syntax of Relative Paths

Special CharactersMeaningExample
. (single dot)Current directory./image.jpg → file in same folder as the HTML file
.. (double dots)Parent directory (one level up)../folder/image.jpg → one folder up, then into folder/
No prefixAlso means current directory (but explicit ./ is clearer)image.jpg works like ./image.jpg

Worked Example: Referencing images in a project

Given the folder structure:

Desktop/
├── folder-in-parent/
│   └── image-one.jpg
└── website-development/   ← (project folder)
    ├── 3.17-file-paths.html   ← (current file)
    ├── same-folder-image.jpg
    └── images/
        └── sub-folder-image.webp
Target FileRelative Path (from HTML file)Absolute Path (Windows example)
same-folder-image.jpg./same-folder-image.jpgC:\Users\...\website-development\same-folder-image.jpg
sub-folder-image.webp./images/sub-folder-image.webpC:\Users\...\website-development\images\sub-folder-image.webp
image-one.jpg (in parent)../folder-in-parent/image-one.jpgC:\Users\...\Desktop\folder-in-parent\image-one.jpg

Exam tip: In HTML, <img src="..."> with a relative path is recommended over absolute because it keeps the project portable. Live servers often block access to files outside the project root; absolute paths may fail.

Why the parent-folder image didn’t render in VS Code’s live server?

Live servers (e.g., VS Code’s) restrict access to files outside the project directory for security. The relative path ../ breaks because the server’s root is the project folder, not the desktop. Opening the HTML file directly from the file system (double-click) bypasses this restriction.

Why relative paths are recommended

  • Portability – Share the project folder; everyone can use the same paths regardless of their machine’s root structure.
  • Flexibility – If the whole project is moved from Desktop/ to Documents/, relative paths still work (absolute paths would break).
  • Simplicity – Short, no need to type the full C:\... for every file.
  • Web hosting – Relative paths adapt to the server’s root; absolute paths tied to a local drive will not.

Exam tip: The only time you may need an absolute path is when linking external resources from a different domain (URLs like https://example.com/image.jpg). For local project files, always use relative paths.

Key takeaways

  • Absolute path – starts from filesystem root, universal but brittle.
  • Relative path – starts from current file, uses . for current directory and .. for parent.
  • Relative paths are portable, flexible, and server-friendly.
  • In live server environments, .. may not be allowed to go above the project root.
  • Stick to relative paths for all local file references in your HTML.

Multi-Page Websites & Navigation

A multi-page website consists of several HTML files, each serving a distinct purpose (e.g., homepage, events, registration). This replaces the single-page approach used in small projects. Real-world sites like Amazon or Wikipedia use multiple pages to organize content effectively.

Why multi-page?

  • Improves content organization (each page has a clear role).
  • Enhances user experience (users navigate to relevant pages).
  • Essential for professional, scalable websites.

Folder Structure & Relative Paths

All pages are stored in a single folder (or nested sub-folders). Resources (images, videos) are placed in sub-folders (e.g., images/). Relative file paths link pages and resources.

Path patternMeaningExample
./Current folder./events.html
images/filename.jpgSub-folder within currentimages/dj.jpg
../Parent folder (not used here)

Exam tip: Relative paths keep links functional even when the site is hosted elsewhere. Avoid absolute paths like C:\... for deployment.

Creating Pages (Home, Events, Register)

  1. Create a project folder (e.g., final-website-multipage/).
  2. Create three HTML files: home.html, events.html, register.html.
  3. Use the same base HTML (from previous lectures on semantics) for all pages, then remove sections not needed for that page.

Worked example:

  • Start with the semantic HTML template from the previous video (header, main with sections, footer).
  • For home.html: keep header, directions/introduction; remove event schedule and registration form.
  • For events.html: keep header and event schedule section; remove directions and registration.
  • For register.html: keep header and registration form; remove everything else.
  • Rename <title> per page: “IIMB Fest – Home”, “IIMB Event Details”, “IIMB – Register”.

Result: three clean, focused web pages that share a consistent header design.

Linking Pages with Anchor Tags

The <a> element (anchor tag) creates clickable links. The href attribute specifies the target page using a relative path.

<a href="./events.html">Click here to see events</a>
<a href="./register.html">Click here to register</a>
  • The dot-slash ./ explicitly states “same folder as the current page”.

Place these links inside a <nav> element (semantic tag for navigation blocks) within the <header> for consistency.

Navigation flow (conceptual):

flowchart LR
    A[home.html] -- a href="./events.html" --> B[events.html]
    A -- a href="./register.html" --> C[register.html]
    B -- a href="./home.html" --> A
    C -- a href="./home.html" --> A

Each page should include a “back to homepage” link so users can return easily.

Navigation Consistency

  • Reuse the same header (and footer) across all pages to maintain visual cohesion.
  • Place navigation in the same location (inside <header>) on every page.
  • Use <nav> for semantic clarity – it has no visual effect but improves accessibility and code structure.

Exam tip: Navigation must be present on every page, and links should always be functional (check relative paths). A common exam question: “Why did the image not load on the homepage?” → Answer: the relative path to the image folder was wrong (e.g., missing images/ sub-folder).

Key Takeaways

  • Multi-page websites group content into separate HTML files for better organization.
  • Relative paths (./filename.html) link pages; resources like images need correct sub-folder references.
  • Anchor tags <a href="..."> enable navigation; wrap them in <nav> for semantics.
  • Remove irrelevant sections from each page to avoid duplication while keeping headers/footers the same.
  • Always provide a “back to homepage” link on every sub-page.

Hosting Website

Web hosting is the process of making a website accessible to anyone anywhere on the internet. Until hosted, the site exists only on the local computer. Hosting uploads the site's files to a web server – a special computer connected to the internet 24/7. Once hosted, anyone in the world can view it.

Why host?

  • Public availability – share with friends, family, or potential employers.
  • Accessibility – site is live and can be viewed anytime.
  • Impressive – showcases your skills by having a live project.

Pre‑hosting Checklist

TaskReason
All website files in one folderKeeps structure clean; required by hosting platforms.
Required resources (images, CSS, etc.) inside that same folderRelative links will work correctly.
Rename home page to index.htmlindex.html is the standard name for the main homepage; GitHub (and most servers) expects this file to display the site root.

Exam tip: Forgetting to rename home.html to index.html is the most common reason GitHub Pages fails to show a site. Always do this before uploading.

After renaming, update any internal links that pointed to the old filename. In the transcript example:

  • home.html becomes index.html → update links in events.html and register.html to redirect back to index.html.

Hosting with GitHub Pages (step‑by‑step)

GitHub Pages is a free hosting service. The process is:

flowchart TD
    A[Create a GitHub account] --> B[Create a new repository]
    B --> C[Set repository to PUBLIC]
    C --> D[Upload files – not the folder itself]
    D --> E[Commit to main branch]
    E --> F[Settings > Pages > select main branch /root]
    F --> G[Wait 2–3 minutes for deployment]
    G --> H[Site live at username.github.io/repo-name]

Detailed steps:

  1. Log in to GitHub (or create an account).
  2. Create a new repository – give it a name (e.g., IIMB-Fest-website-demo).
    • Add an optional description.
    • Choose Public – free hosting requires public repositories.
    • Optionally add a README file (not required).
  3. Upload files:
    • Click Add fileUpload files.
    • Important: Do not upload the parent folder. Navigate inside your project folder and upload only the individual files (including index.html and the images subfolder).
    • This ensures index.html is at the root of the repository.
  4. Commit changes – enter a message (e.g., “upload first time”) and commit directly to the main branch.
  5. Enable GitHub Pages:
    • Go to SettingsPages.
    • Under Branch, select main and leave the folder as / (root).
    • Click Save.
  6. Wait 2–3 minutes – GitHub deploys the site. A green banner will appear with the live URL: https://<username>.github.io/<repository-name>/.

Exam tip: The URL pattern is always username.github.io/repo-name. If you see a 404, double‑check that index.html exists at the root of the repository and that the repository is set to Public.

The final live site will function exactly as it did locally: all internal links and images work because the file structure was preserved.


Key takeaways

  • Web hosting makes a site publicly accessible via a web server.
  • Rename the main page to index.html and update all cross‑references.
  • Use GitHub Pages for free hosting – repository must be Public.
  • Upload the files themselves (not the enclosing folder) so index.html sits at the repo root.
  • After setting main branch in Settings → Pages, wait ~2–3 minutes for deployment.
  • The live URL follows the pattern username.github.io/repo-name.

Resume Website Project

This assignment is your first real-world HTML build: a personal resume website. Its purpose is to apply everything you’ve learned about HTML to create a live, shareable page that tells your professional story. The focus is on planning, meaningful structure, and deployment.

Plan Before You Code

A good website starts with a clear objective. Ask yourself:

  • What story do you want to tell? (skills, career goals, personality)
  • What sections matter most? (experience, projects, hobbies)
  • How will you make it visually appealing and impactful? (layout, content)

Sketch a design plan: decide the layout, section ordering, and content preparation. Good planning is the foundation.

flowchart LR
  A[Define your story] --> B[Sketch layout & sections]
  B --> C[Prepare content & assets]
  C --> D[Code HTML]
  D --> E[Deploy to GitHub Pages]
  E --> F[Share link]

Required Sections – Minimum Content

Your resume website must include:

SectionDescription
HeaderYour name and a tagline (e.g., “Web Developer & Designer”)
PhotoA picture – “a picture speaks louder than words”
Summary / ObjectiveDescribes you and your career goals
Work ExperienceList each job: company name, job title, duration, key responsibilities/achievements
EducationSchools attended, degrees obtained, graduation dates
ProjectsCool things you’ve built (even class assignments). For each: title, brief description, technologies/tools used
Hobbies / ExtracurricularOptional but encouraged

Use Semantic HTML

Make your code meaningful. Use the following tags to structure your page:

  • <header> – for the page header (name + tagline)
  • <section> – to organize each major part (experience, education, etc.)
  • <footer> – for closing notes
  • <article> – for individual job entries or projects (self-contained content)

Exam tip: Semantic tags improve accessibility, SEO, and maintainability. They are a high-yield concept in any HTML assessment.

Go Beyond – Experiment and Extend

  • Explore the MDN Web Docs for new tags you haven’t seen in class. (e.g., <figure>, <time>, <address>)
  • Multi-page website: Create a separate page for projects or contact details. Use a <nav> bar to link pages.
  • Tables for structured data: e.g., a skills table or a certifications table. Tables add clarity to tabular information (languages, tools, certificates).

Deploy on GitHub Pages

Your resume must be live on the web.

  1. Host the site using GitHub Pages (as demonstrated in earlier videos).
  2. Once live, share the link with your instructor/class.

There is no single right way to do this – your website should reflect you: your interests, achievements, and story.


Key takeaways

  • Plan your story, layout, and content before coding.
  • Required sections: header + tagline, photo, summary/objective, work experience, education, projects, (optional) hobbies.
  • Use semantic elements (<header>, <section>, <article>, <footer>).
  • Enhance with multi-page, tables, and new tags from MDN.
  • Deploy via GitHub Pages and share the link.

Introduction to CSS and Styling

Introduction to CSS

CSS (Cascading Style Sheets) brings a website to life with visual appearance. If HTML is the skeleton of a page, CSS adds the “skin” – colors, fonts, spacing, layout, and overall style. It separates content (HTML) from presentation (how it looks), making code cleaner, maintainable, and scalable.

What “Cascading Style Sheets” means

  • Style sheets – A set of rules that define how elements on a webpage should look. Each rule specifies properties (e.g., color, font size, margin) and their values.
  • Cascading – Like a waterfall flowing from top to bottom, styles are applied in layers, from the most general to the most specific rules. The cascade determines which rule wins when multiple rules target the same element. (Detailed coverage in a later video.)

The syntax of a CSS rule

A CSS rule consists of a selector and a declaration block:

selector {
  property: value;
}
PartRoleExample
SelectorTargets which HTML element(s) to styleh1
PropertyThe visual characteristic to changecolor
ValueThe specific setting for that propertypurple

Example – The following rule turns the text of every <h1> element purple:

h1 {
  color: purple;
}

This is the simplest form; later modules will introduce more powerful selectors and properties.

Why CSS matters

  • Without CSS, a webpage is functional but bland – like a colouring book with no colours.
  • Early web developers used HTML tags (e.g., <font>) for styling, which cluttered code and made large projects unmanageable.
  • CSS was born in 1996 as a dedicated solution to separate style from structure, enabling efficient, scalable design.

What CSS can do

Think of CSS as adjectives that describe HTML nouns. HTML says “here’s a button”; CSS says “this is a purple, large, rounded button”. Core capabilities covered in this module:

  • Selectors – pinpoint any element (or group of elements) on a page.
  • Properties – change colours, fonts, sizes, backgrounds, borders, margins, padding, and more.
  • The Box Model – how margins, borders, padding, and content combine to form layout.
  • Positioning & Alignment – control where elements sit on the screen.

Exam tip: “Cascading” is a key exam concept. Remember: general rules (e.g., body) apply first, then more specific rules (e.g., h1) override them. The cascade answers “which style wins?”.

What’s coming (Modules 4 & 5)

  • Module 4: Selectors, basic styling, box model, layout, positioning.
  • Module 5: Animations, transitions, responsive design (making pages adjust to different screen sizes).

Key takeaways

  • CSS = Cascading Style Sheets – separates content from presentation.
  • A rule has a selector and a { property: value; } block.
  • The cascade resolves conflicting styles by order of specificity and source.
  • CSS was introduced in 1996 to replace messy HTML styling.
  • It controls colours, fonts, spacing, layout, and much more – turning HTML “bones” into polished websites.

Ways to Add CSS to HTML

CSS (Cascading Style Sheets) is applied to HTML documents through three distinct methods. Each serves a different purpose and is chosen based on project scale, reusability, and workflow. The three methods are inline CSS, internal CSS, and external CSS.


Inline CSS

Inline CSS applies styles directly to a single HTML element using the style attribute. The style attribute is a global attribute – it can be added to any opening HTML tag. Inside, you write property–value pairs (e.g., color: blue). This method is quick for testing or making small, one‑off adjustments.

<h1 style="color: blue;">This is the heading</h1>
  • Targets only the specific element it is placed on.
  • Not reusable – if the same style is needed elsewhere, it must be repeated.
  • Best reserved for prototyping, debugging, or overriding other styles temporarily.

Internal CSS

Internal CSS places all styles inside a <style> tag in the <head> section of the HTML file. The CSS rules target elements by selectors (e.g., p for all paragraph elements) and apply consistently across the entire page.

<head>
  <style>
    p {
      color: green;
    }
  </style>
</head>
  • All <p> elements on the page will have green text.
  • Keeps styles in the same file but separates them from content.
  • Ideal for single‑page websites where no external file is needed.

External CSS

External CSS separates styles into a dedicated .css file. This file is linked to the HTML using a <link> tag in the <head>. The rel attribute must be "stylesheet", and the href attribute points to the file’s path.

<head>
  <link rel="stylesheet" href="style.css">
</head>

Contents of style.css:

h2 {
  color: red;
}
  • Most scalable method – the same .css file can be reused across multiple pages.
  • Changes in one file update the entire site’s appearance.
  • Separates structure (HTML) from presentation (CSS), making code cleaner and easier to maintain.

Comparison & Decision Guide

MethodWhere styles are writtenScopeUse when
Inlinestyle attribute of an elementSingle elementQuick test, one‑off tweak
Internal<style> in <head>One HTML pageSingle‑page site, all styles local
ExternalSeparate .css fileAny page that links the fileMulti‑page sites, reusability
flowchart LR
  A[Need to style HTML?] --> B{How many pages?}
  B -->|One page, small| C[Internal CSS]
  B -->|Multiple pages| D[External CSS]
  B -->|One element only| E[Inline CSS]

Exam tip: Inline CSS has the highest specificity – it overrides both internal and external rules for the same property on the same element. However, it is the least maintainable.


Key takeaways

  • Three methods: inline (via style), internal (<style> in <head>), external (.css file linked with <link>).
  • Inline = fastest for a single element, but zero reusability.
  • Internal = good for a single page, keeps styles inside the HTML file.
  • External = industry standard for multi‑page sites; separates concerns and enables reuse.
  • The <link> tag requires rel="stylesheet" and href pointing to the .css file.
  • Use the appropriate method based on project size and style reusability needs.

Syntax and Selectors

CSS syntax is the formal structure of every CSS rule. It tells the browser which HTML element to style and how to style it. The fundamental pattern:

selector {
  property: value;
}
  • Selector – identifies the HTML element(s) to style (e.g., h2).
  • Curly braces { } – enclose all style declarations for that selector.
  • Property – the aspect you want to change (e.g., color, font-size).
  • Value – the setting you assign to the property (e.g., red, 16px).
  • Semicolon – separates multiple property–value pairs inside the same braces.

Multiple declarations can be added for one selector:

h2 {
  color: red;
  background-color: green;
}

Exam tip: Every declaration must end with a semicolon. Missing it causes the next rule to fail – a common rookie mistake.


Selector Types

Selectors are how CSS “talks to” HTML. Each type has a specific syntax and use case.

SelectorSyntaxTargetsExample
ElementtagnameAll elements of that tagp { color: green; }
Class.classnameAll elements with that class attribute.orange { color: orange; }
ID#idnameThe single element with that id attribute#main { color: blue; }
Universal*Every element in the document* { margin: 0; }
Attributeelement[attribute] or element[attribute="value"]Elements with a specific attribute (or value)input[type="text"] { border: 1px solid black; }

Element Selector

The simplest: write the tag name. It selects all instances of that tag.

h2 {
  background-color: green;
}
<h2>Second heading</h2>  <!-- styled -->
<p>Sample text</p>       <!-- not styled by h2 -->

Class Selector

The class attribute is a global HTML attribute that groups elements together for shared styling. Class names are reusable across different tag types.

CSS syntax: a dot (.) followed by the class name.

<p class="orange">This is orange</p>
<p class="orange">Another orange paragraph</p>
.orange {
  color: orange;
  font-weight: bold;
}

All elements with class="orange" (regardless of tag) receive the styles.

ID Selector

The id attribute must be unique within a document – it identifies a single element.

CSS syntax: a hash (#) followed by the ID value.

<h1 id="main-element">First heading</h1>
#main-element {
  color: blue;
  text-align: center;
}

Exam tip: IDs are one-of-a-kind. Using the same ID twice is invalid HTML and may cause unpredictable styling.

Universal Selector

* applies styles to every element. Useful for resetting default browser margins/paddings.

* {
  margin: 0;
  padding: 0;
}

The universal selector overrides default spacing for all elements (though it can be affected by later, more specific rules – that’s the cascade, covered in another lesson).

Attribute Selector

Targets elements based on the presence of an attribute, or the exact value of that attribute.

SyntaxMeaning
element[attr]Element has the attribute (any value)
element[attr="value"]Element has attribute with that exact value

Example – target by attribute value:

<input type="text" placeholder="Do not enter your name">
<input type="email" placeholder="Enter your email">
input[type="text"] {
  border: 5px solid darkmagenta;
}

Only the text input gets the purple border.

Example – target by attribute presence (any value):

<button draggable="true">Click me</button>
button[draggable] {
  color: pink;
}

The button is styled because it has the draggable attribute, regardless of its value.


When to Use Class vs. ID

  • Class – for reusable styles that apply to multiple elements (teams).
  • ID – for a single, unique element (individual).
flowchart LR
A[Need to style multiple elements?] -->|Yes| B[Use class]
A -->|No, one unique element| C[Use ID]

Exam tip: Class selectors are more flexible and recommended for most styling. Reserve IDs for JavaScript hooks or very specific, one-off styling.


Key Takeaways

  • CSS syntax: selector { property: value; } – every declaration ends with a semicolon.
  • Element selector – targets all elements of a given tag.
  • Class selector (.name) – targets any element with that class attribute; reusable.
  • ID selector (#name) – targets a single unique element.
  • Universal selector (*) – targets every element; great for resets.
  • Attribute selector ([attr] or [attr="val"]) – targets elements by attribute presence or exact value.
  • Use classes for reusable groups, IDs for unique elements.

Tools and References

CSS is vast — there are dozens of properties just for text (e.g., letter-spacing, line-height, text-transform) and many ways to achieve the same visual effect (e.g., multiple border properties). The goal is not to memorise everything, but to understand the fundamentals and know where to find answers.

Key Resources

ResourceWhat it providesHow to use it
MDN Web Docs (Mozilla Developer Network)Detailed explanations for every CSS property, with code examples and rendered previewsSearch for any property (e.g., box-shadow) and read the complete reference
Google (or any search engine)Quick answers for specific problems, tutorials, and videosSearch phrases like "CSS rounded corners" to find step‑by‑step guides
Online CSS generators (e.g., color pickers)Pre‑written CSS code for common effects (colours, gradients, shadows)Pick colours, copy the generated rule, and paste into your stylesheet

Workflow: How to approach a CSS problem

flowchart LR
  A[Understand CSS fundamentals] --> B[Stuck on a style?]
  B --> C{Know the property?}
  C -->|Yes| D[Write it directly]
  C -->|No| E[Search MDN or Google]
  E --> F[Experiment with examples]
  F --> D
  B --> G[Use online generator for quick code]
  G --> D
  D --> H[Build and test]

Exam tip: Interviewers or exams rarely test rote recall of property names. Instead, they assess your ability to find the right property and apply it correctly. Become fluent with MDN’s CSS reference — it’s your primary cheat sheet.

Practical Advice

  • Master the basics: Syntax, selectors, the cascade — these never change.
  • Look it up when you get stuck: Even professional developers search for properties daily.
  • Use tools without guilt: Colour pickers, gradient generators, and shadow tools save time and reduce errors.
  • Build often: The more you code, the more familiar the common properties become.

Key takeaways

  • CSS has hundreds of properties; memorising all of them is neither expected nor efficient.
  • MDN Web Docs is the definitive reference — every property includes syntax, examples, and live previews.
  • Google and online CSS generators are legitimate, everyday tools for real‑world development.
  • Focus on fundamentals (syntax, selectors, layout) and learn to find the rest on demand.

Colors in CSS

CSS provides multiple ways to define colors to set the foreground (text) color and the background color of elements. Understanding these representations lets you precisely control the visual tone of a webpage.

Color Properties

PropertyPurposeExample
colorSets the text color (foreground)color: blue;
background-colorSets the background of the elementbackground-color: lightblue;

The shorthand background property can also set gradients and images. Stick to background-color for solid colors.

Color Representation Methods

CSS accepts three common ways to specify a color:

  1. Named colors – Simple, browser‑recognised words (e.g., red, teal, beige, aqua).
  2. Hexadecimal (hex) codes – A six‑character code preceded by # (e.g., #FF5733).
  3. RGB notationrgb(red, green, blue) where each value is an integer 0–255 (e.g., rgb(255, 87, 51)).
MethodSyntaxExampleUse Case
Namedcolor: red;Simple, fast prototyping
Hexcolor: #FF5733;Compact, most common in production
RGBcolor: rgb(255, 87, 51);When you want to adjust numeric values

How Hex and RGB Relate

The RGB color system is an additive model – red, green, and blue light combine to create colors.

  • Zero of all three → black.
  • Full (255) of all three → white.
  • Equal amounts of red and green → yellow; adding blue → becomes white.

Hexadecimal is just another way to write the same three numbers (0–255 for each channel) in base‑16.

  • Digits: 0‑9 and a‑f (16 total).
  • Example: decimal 255 → FF; decimal 150 → 96; decimal 200 → C8.
  • So a hex code like #FF5733 means R=255, G=87, B=51.

Exam tip: A hex code is exactly an RGB triplet written in base‑16 – no magic! You can convert any RGB value to hex and vice versa.

Color Tools and Palettes

  • Color pickers (built into browsers or online) let you visually select a color and copy its hex or RGB value.
  • Palette websites (e.g., Color Hunt) provide pre‑matched harmonious color sets. Click to copy a hex code, then paste it into your CSS with a #.

Worked Examples (from the lecture)

ElementCSS appliedEffect
<h1>color: blue; background-color: aqua;Blue text on light blue background
<p>color: #XXXXXX; (hex from palette)Text color set to palette colour
<button>color: rgb(…, …, …);Greenish text (random numbers)
<input>color: red; background-color: #XXXXXX;Red typed text, custom background inside the box
<html>background-color: beige;Entire page background beige (cascades but can be overridden by specific element backgrounds)

Notable behaviours demonstrated:

  • The color property on an <input> affects only the typed text, not the placeholder text.
  • Background colors cascade – adding a background to <html> shows behind elements that do not have their own background set (but specific background‑color rules override it). This is part of the cascading nature of CSS.

Key Takeaways

  • color controls text colour; background-color controls the element’s background.
  • Three main ways to define colors in CSS: named, hex, and RGB.
  • Hex codes are compact base‑16 representations of RGB values – no need to memorise conversion, just copy from a picker.
  • Use color pickers and palettes (e.g., Color Hunt) to quickly choose harmonious colours.
  • Placeholder text inside <input> is not affected by the color property – that requires the ::placeholder pseudo‑element.

CSS Fonts

Fonts are central to web design — they control readability, tone, and visual hierarchy. CSS offers a suite of properties to adjust typeface, size, thickness, slant, and alignment. Use them to make text both expressive and accessible.

1. Font Size (font-size)

Controls how large or small text appears. Units fall into two categories:

Absolute units — fixed size, unaffected by context.

  • px (pixels): 1px=196inch0.26mm1\text{px} = \frac{1}{96}\text{inch} \approx 0.26\text{mm}. Renders identically regardless of device.
  • pt (points): 1pt=172inch0.35mm1\text{pt} = \frac{1}{72}\text{inch} \approx 0.35\text{mm}. Common in print; also works on screen.

Relative units — size depends on another element.

  • em: Multiplied by the parent element’s font-size. If parent is 20px20\text{px}, 2em 2×20=40px\Rightarrow 2 \times 20 = 40\text{px}.
  • rem: Multiplied by the root element’s (<html>) font-size. If root is 30px30\text{px}, 1.5rem 1.5×30=45px\Rightarrow 1.5 \times 30 = 45\text{px}.

Named sizes — keywords like small, medium, large. Imprecise; only for prototyping.

Exam tip: em compounds when elements are nested (each child multiplies its parent). rem stays consistent — always relative to the root. Use rem for predictable, responsive sizing.

Worked example (from the lecture):

ElementRuleParent/Root sizeComputed size
<h1>font-size: 60px60px
Parent <div>font-size: 20px20px
Child (.em-based)font-size: 2emparent = 20px2×20=40px2 \times 20 = 40\text{px}
Root <html>font-size: 30px30px
Child (.rem-based)font-size: 1.5remroot = 30px1.5×30=45px1.5 \times 30 = 45\text{px}

Table: Font-size units compared

UnitTypeRelative toUse case
pxAbsoluteFixed, pixel-perfect control
ptAbsolutePrint styling
emRelativeParent’s font-sizeCompound scaling (use with care)
remRelativeRoot font-sizeConsistent, responsive layouts
NamedKeywordBrowser defaultQuick prototyping only

2. Font Weight (font-weight)

Controls the thickness of characters.

  • Keywords: normal (400), bold (700), lighter, bolder
  • Numerical values: 100 (thin) → 900 (heavy). 400 = normal, 700 = bold.
  • Not all typefaces support every weight; missing values fall back to the nearest available.

Example:
h1 { font-weight: 800; }
.em-based { font-weight: 500; }


3. Font Family (font-family)

Selects the typeface (e.g., Arial, Times New Roman). Always provide a font stack — a comma‑separated list of fallbacks.

p {
  font-family: 'Gill Sans', Calibri, 'Trebuchet MS', sans-serif;
}

The browser tries the first font; if unavailable, moves down the list. End with a generic fallback (serif, sans-serif, monospace).

Google Fonts — load custom fonts via a <link> in the document <head>, then reference the font name in CSS.

Example (from lecture):

<link href="https://fonts.googleapis.com/css2?family=Bokor&display=swap" rel="stylesheet">
h1 {
  font-family: 'Bokor', sans-serif;
}

This ensures the same look across browsers and devices.

flowchart LR
  A[Request font] --> B{Is 'Bokor' available?}
  B -->|Yes| C[Render 'Bokor']
  B -->|No| D{Next in stack?}
  D -->|Yes| E[Try 'sans-serif' fallback]
  D -->|No| F[Browser default]

4. Font Style (font-style)

Controls slanting of text.

  • normal — upright.
  • italic — uses the italic version of the typeface (if it exists).
  • oblique — artificially slants the upright glyphs. May take an optional angle (e.g., oblique 15deg).

Use italic for emphasis. Example:
.em-based { font-style: italic; }


5. Text Alignment (text-align)

Horizontal alignment of text within its container.

ValueEffect
leftAligns text to the left edge (default for LTR languages)
rightAligns to the right edge
centerCenters text horizontally
justifyStretches each line so both left and right edges are flush (adds or removes space between words)

Justify creates a clean, book‑like block but can produce awkward gaps on short lines.
Example: p { text-align: justify; }


Key takeaways

  • font-size uses absolute (px, pt) or relative (em, rem) units. Prefer rem for responsive design.
  • em scales relative to the parent; rem scales relative to the root — avoid nested em traps.
  • font-weight uses keywords or numeric values (100–900); 400 = normal, 700 = bold.
  • font-family should always include a font stack with a generic fallback.
  • Google Fonts are loaded via <link> and referenced by name — they ensure cross‑browser consistency.
  • font-style (italic/oblique) and text-align (left, center, right, justify) control slant and horizontal alignment.
  • Font choices affect readability and tone — experiment but always test fallbacks.

CSS Inspection

CSS inspection refers to using the browser’s developer tools to examine, debug, and experiment with CSS in real time. Instead of guessing why a style doesn’t look right, you open the tools and see exactly which rules are applied, which are overridden, and what the final rendered values are.

Opening Chrome Developer Tools

Three equivalent methods:

MethodAction
MenuThree dots → More Tools → Developer Tools
KeyboardCtrl+Shift+I (Windows) / Cmd+Option+I (Mac) – also F12
Right-clickRight‑click any element → Inspect (directly shows that element’s HTML)

The Elements Tab: Styles Panel

Once DevTools is open, the Elements tab shows the HTML structure. Selecting an element (either by clicking in the HTML tree or using the element‑picker icon in the top‑left of DevTools) reveals the Styles panel on the right.

The Styles panel displays:

  • All CSS rules that apply to the selected element, in order of specificity.
  • The source file and line number for each rule. Clicking a file link jumps directly to the source code.
  • Which rules are overridden (shown with a strikethrough). For example, font-size: 2em crossed out when a later rule sets font-size: 60px.
  • An inline edit capability – you can type a new property (e.g. color: chocolate) and see the change live on the page.

    Important: These edits are temporary. They disappear on page refresh and do not modify your source files. Use them for rapid experimentation only.

Computed Tab

The Computed tab (next to Styles) solves the confusion of overridden rules. It aggregates all resolved styles into one clean list, showing the final value for every property after cascading and inheritance. This is the definitive answer to “what value does this element actually get?”

Box Model Visualisation

Both the Styles panel (at the bottom) and the Computed tab display a box model diagram for the selected element. It shows:

┌───── Margin ─────┐
│ ┌── Border ──┐   │
│ │ ┌ Padding ┐ │   │
│ │ │ CONTENT │ │   │
│ │ └─────────┘ │   │
│ └─────────────┘   │
└───────────────────┘

Each region is labelled with its current pixel (or other unit) value. This is invaluable for diagnosing spacing and layout issues.

CSS Overview Tool

A separate, aggregate tool that summarises all CSS used on a page:

  1. Open DevTools → three‑dot menu (⋮) → More Tools → CSS Overview.
  2. Click Capture overview.

It reports:

  • Colors used (with count)
  • Fonts used
  • Unused declarations (or other diagnostics)

Useful when reverse‑engineering a design from a live website or auditing your own project for consistency.

Exam tip: The Computed tab is the fastest way to find the final value of a property when multiple rules conflict. Always look there before debugging specificity.

Key takeaways

  • Open DevTools with Ctrl+Shift+I, F12, or right‑click → Inspect.
  • The Styles panel shows all applied rules, source links, and overridden (strikethrough) values.
  • Live editing is temporary – use it to test, then update your source file.
  • The Computed tab gives the final resolved values, ignoring overridden rules.
  • The box model diagram helps visualise margin, border, padding, and content dimensions.
  • CSS Overview captures a summary of colors, fonts, and overall CSS usage on any page.

Box Model

Every element on a webpage is enclosed in an invisible box. The CSS box model defines how the element’s content, padding, border, and margin are sized and how they interact to determine the element’s total space and layout.

flowchart LR
  A[Margin] --> B[Border] --> C[Padding] --> D[Content]
  • Content – the actual text, image, or inner element.
  • Padding – space between content and border; expands the element inward.
  • Border – visible or invisible boundary around padding.
  • Margin – space outside the border; separates the element from others.

Height & Width

height and width set the dimensions of the content area. Units can be absolute (px) or relative (%, vw, etc.).

ExampleCodeResult
Fixed sizeheight: 300px; width: 150px;Box is exactly 300px × 150px.
Percentage widthwidth: 50%;Width = 50% of parent container (e.g., <body>). Resizes with viewport.

Exam tip: Changing height or width affects the content area only – padding, border, and margin add extra space.

Border

border adds a boundary around the element. Shorthand: border: <width> <style> <color>;

Styles: solid, dashed, dotted, double, etc.

Individual side controls: border-width, border-style, border-color accept 1, 2, or 4 values.

Number of valuesApplies to
1All four sides
2Top & bottom (1st), left & right (2nd)
4Top, right, bottom, left (clockwise)

Example (shorthand with 4 values):

border-width: 10px 30px 50px 60px;
border-color: red green blue black;
border-style: dotted double dashed solid;

border-radius rounds the corners.

  • 1 value: all corners.
  • 2 values: first → top-left & bottom-right, second → top-right & bottom-left.
  • 4 values: clockwise from top-left.

Padding

padding creates internal space between content and border.

  • Expands the element’s total size outward from the content.
  • Same 1/2/4 value rules as border.

Example: padding: 20px; adds 20px on all sides.

Margin

margin creates external space outside the border, separating elements.

  • Also uses 1/2/4 value shorthand.
  • Margin collapsing: When two adjacent vertical margins meet, they collapse to the larger value (not the sum).
    • E.g., element A margin-bottom: 30px, element B margin-top: 20px → gap = 30px, not 50px.

Worked Example: Total Width of an Element

Given the first box from the lecture:

margin: 30px;
border: 10px solid black;
padding: 20px;
width: 150px;   /* content width */

Total width (left to right) = margin-left + border-left + padding-left + content width + padding-right + border-right + margin-right
= 30 + 10 + 20 + 150 + 20 + 10 + 30
= 270px.

Exam tip: The box model is additive by default (box-sizing: content-box). To include padding and border inside the declared width, use box-sizing: border-box.


Using <div> for Grouping

The <div> element is a generic block-level container. It groups elements so they can be styled as a unit.

.grouping {
  border: 20px solid green;
  padding: 20px;
  text-align: center;
}

This applies the same border, padding, and alignment to all children (e.g., <h1> and <p> inside the div).


Key takeaways

  • Box model: content → padding → border → margin (inside-out).
  • height/width set content size; use % for responsive layouts.
  • border shorthand: width, style, color. Use 2 or 4 values for side-specific control.
  • padding expands element size; margin creates external spacing; vertical margins collapse.
  • border-radius softens corners.
  • <div> groups content for efficient styling.
  • Inspect elements in DevTools to see the box model visually.

The Cascade

The cascade refers to the order in which CSS rules are applied. When multiple rules target the same element and property, later declarations override earlier ones — "whatever comes later takes priority."

flowchart LR
  A[Earlier rule] -->|overridden by| B[Later rule]

Definition: Cascade = waterfall-like flow. In CSS, styles applied later in source order have higher precedence (at the same specificity level).

Demonstration

Consider an <h1> element and two rules in the same stylesheet:

h1 { color: green; }   /* line 1 */
h1 { color: brown; }   /* line 5 – overrides green */

The heading appears brown. Adding a third rule below (e.g., color: cornflowerblue) overrides both. This principle holds within a single selector (multiple identical properties) and across selectors of equal specificity.

External vs. Internal vs. Inline – Source Order

  • External stylesheets linked in <head> are loaded in order of appearance.
  • Internal styles (<style> in <head>) are treated like another stylesheet — they follow the same cascade.
  • Inline styles (via the style attribute) are considered to "come last" in source order for the element itself, but they also carry higher specificity (see below).

When two stylesheets have selectors of equal specificity, the sheet linked lower in the HTML wins.

Exam tip: Cascade only matters when specificity is tied. Always check specificity first – see next section.

Key takeaways

  • Cascade: later styles override earlier ones within the same specificity level.
  • Applies to both internal and external CSS.
  • Source order (position in HTML / within a file) determines precedence when specificity is equal.

Specificity

Specificity is the algorithm CSS uses to decide which rule "wins" when multiple selectors target the same element. Think of it as a ranking: some selectors are inherently more powerful than others.

Selector hierarchy (lowest → highest)

Selector typeExampleSpecificity weight (MDN notation)
Element / type selectorh1, p, div(0,0,1)
Class / attribute selector.class-a, [type="text"](0,1,0)
ID selector#unique-id(1,0,0)
Inline style (on the element)style="color: red"(1,0,0,0) – always wins over external/internal
!important annotationcolor: green !important;Overrides all of the above (see below)
  • Each higher level overrides any number of lower-level selectors. Ten element selectors cannot beat a single class.
  • When two selectors have the same highest weight, cascade (source order) breaks the tie.

Demonstration with <h2 class="class-abc" id="id-abc">

  1. Element selector wins if only element rules exist; last one in the file applies (cascade).
  2. Add a class selector (.class-abc { color: orange; }). Even if it appears before element selectors in the source, the heading turns orange – class is more specific.
  3. Add an ID selector (#id-abc { color: darkblue; }). Even at the top of the file, it overrides both element and class.
  4. Multiple properties inside the ID selector: cascade still applies — #id-abc { color: darkblue; color: gray; } → gray wins (later).
  5. Two external stylesheets each with an ID selector: the sheet loaded second wins because both have the same specificity (1,0,0), so cascade decides.
  6. Internal style with ID selector: treated as another CSS source. If loaded before the external ID, cascade gives the later one precedence. If moved below (later in the HTML), it overrides.
  7. Inline style (style="color: fuchsia") overrides all external and internal ID/class/element rules – inline has the highest specificity (1,0,0,0).

Exam tip: Inline styles are rarely recommended because they break separation of concerns and are difficult to override. Use them only for quick tests.

Worked example: selector conflict

/* external stylesheet 1 (loaded first) */
h2           { color: green; }        /* (0,0,1) – overridden */
.class-abc   { color: orange; }       /* (0,1,0) – overridden */
#id-abc      { color: darkblue; }     /* (1,0,0) – overridden by later ID */

/* external stylesheet 2 (loaded second) */
h2           { color: blueviolet; }   /* (0,0,1) – ignored */
#id-abc      { color: khaki; }        /* (1,0,0) – wins (higher cascade) */

Result: heading is khaki.

If an inline style is added:

<h2 id="id-abc" class="class-abc" style="color: fuchsia">Heading</h2>

Result: fuchsia – inline specificity of (1,0,0,0) beats any external ID.

Key takeaways

  • Specificity: ID > class > element.
  • Equal specificity → cascade (source order) decides.
  • Inline styles beat all external/internal selectors.
  • !important beats everything (except another !important with later source order).

The !important Keyword

Adding !important to a property declaration forces it to override any other rule, regardless of specificity or cascade — except another !important rule later in source order.

h2 { color: green !important; }   /* this will win over any other 'color' rule */
  • Use sparingly. It makes CSS hard to debug and override.
  • If two rules both have !important, cascade applies again – later one wins.
h2 { color: green !important; }
h2 { color: cornflowerblue !important; }  /* wins because later */

Exam tip: Always try to solve style conflicts by adjusting selector specificity before resorting to !important. Overuse is a code smell.


Putting It All Together – CSS Resolution Order

flowchart TD
  A[Conflicting declarations] --> B{Has !important?}
  B -->|Yes| C[Highest priority group]
  B -->|No| D[Selector specificity]
  D --> E{Highest specificity?}
  E -->|Tie| F[Cascade: later wins]
  E -->|One winner| G[That declaration wins]
  C --> H{Multiple !important?}
  H -->|Tie| F
  H -->|One| G

Complete precedence (from strongest to weakest):

  1. !important declarations (tie → cascade)
  2. Inline styles (no !important)
  3. ID selectors
  4. Class / attribute selectors
  5. Element selectors
  6. Universal selector, inherited values (not covered here)

Key takeaways

  • !important should be a last resort.
  • For all other cases: specificity first, then cascade.
  • Inline styles are the second-strongest non-!important option (but avoid them).
  • When two rules have the same specificity and no !important, the one that appears later in the source order (including style order in HTML) applies.

Combining CSS Selectors

Combining selectors lets you target elements precisely without modifying HTML or adding extra classes/IDs. This keeps styles organized and efficient.

Descendant Selector

Selects elements nested anywhere inside a parent – no matter how deep. Use a space between selectors.

.container p {
  color: orange;
}

Targets all <p> elements within any element with class container, including grandchildren, great-grandchildren, etc. The parent div itself is not selected.

Exam tip: Descendant selectors are the default “combination” – if you forget the space, you get chaining (see below). Always double-check the separator.

Child Selector (>)

Selects only direct children – one level deep. Use the > combinator.

.parent > p {
  color: green;
}

Only <p> elements that are immediate children of .parent are affected. Nested <p> inside another <div> inside .parent is ignored.

graph TD
    A[.parent] --> B[<p> direct child - selected]
    A --> C[<div>] --> D[<p> grandchild - NOT selected]

Adjacent Sibling Selector (+)

Selects an element that appears immediately after a specific element, sharing the same parent.

h2 + h3 {
  color: blueviolet;
}

Only the first <h3> that directly follows an <h2> gets styled. Subsequent <h3> siblings are ignored.

Example HTMLStyled?
<h2>Title</h2><br><h3>Subtitle</h3>Yes (first <h3> after h2)
<h2>Title</h2><br><h3>Second</h3><br><h3>Third</h3>Only the first <h3>

Common use case: styling a <label> that comes right after a checkbox or radio input.

input[type="checkbox"] + label {
  color: dodgerblue;
}

Grouping Selector (,)

Apply the same styles to multiple, unrelated selectors. Separate them with a comma.

#heading4, .heading5class, h6 {
  color: indigo;
}

Reduces repetition and keeps CSS concise.

Exam tip: Grouping does not create a relationship between selectors – it’s purely a shorthand. Each selector still targets its own elements independently.

Chaining Selectors

Write selectors without any space to target an element that must satisfy all conditions simultaneously. Good for selecting a specific element that has both a tag and a class/ID.

button.asd {
  color: red;
}

This matches only <button> elements that also have class asd. An <input> with class asd or a <button> without the class are left unstyled.

graph LR
    A[button] --> B{Has class .asd?}
    B -->|Yes| C[Styled red]
    B -->|No| D[Not styled]

When chaining, it is best practice to start with the element selector (e.g., button) followed by class/ID selectors (.asd, #menu). This improves readability because class and ID prefixes (. and #) clearly mark the start of each condition.

You can chain multiple classes and an ID:

div.container.main#menu { ... }
/* matches a <div> with classes container AND main, AND id="menu" */

Key Takeaways

  • Descendant (space): targets any descendant, any depth.
  • Child (>): targets only direct children.
  • Adjacent sibling (+): targets the next immediate sibling.
  • Grouping (,): apply same rule to multiple selectors.
  • Chaining (no space): element must match all selectors in the chain.
  • Chaining is ideal for applying a variation to a specific element without extra HTML classes/IDs.
  • Always choose the simplest combination that does the job – avoid overspecificity.

Pseudo-Classes and Pseudo-Elements

Pseudo‑class selectors and pseudo‑element selectors target elements based on their state or internal parts without requiring extra HTML markup. They transform static pages into interactive, polished interfaces.

Pseudo‑Class Selectors

A pseudo‑class is a keyword added to a selector (with a single colon :) that specifies a special state of the selected element. Examples: :hover, :active, :nth-of-type(), :checked, :visited, :enabled, :disabled.

:hover

Triggered when the user’s pointer hovers over an element. Commonly used for buttons, links, or any interactive feedback.

button:hover {
  color: chocolate;
  background-color: lightgreen;   /* actual colour used in lecture */
  text-decoration: underline;
}

Effect: The button changes colour and gains an underline only while the mouse cursor is over it.

:active

Applies styles when the element is being activated – typically while the mouse button is pressed down.

button:active {
  color: aqua;
  background-color: black;
}

Sequence: Normal → :hover:active (on click) → back to normal after release.

:nth-of-type()

Targets elements by their position among siblings of the same type. The argument can be a number, a keyword (odd, even), or an algebraic expression like An+B.

ArgumentSelects
3Only the 3rd element
2nEvery 2nd element (2, 4, 6, …)
3nEvery 3rd element (3, 6, 9, …)
7nEvery 7th element (7, 14, 21, …)
li:nth-of-type(3n) {
  background-color: khaki;
}

Result: List items 3, 6, 9, 18, … get a khaki background.

Exam tip: :nth-of-type(3) selects only the third element; :nth-of-type(3n) selects every third element. The n makes the formula iterative.


Pseudo‑Element Selectors

A pseudo‑element is a keyword added with a double colon :: that lets you style a specific part of the selected element. Examples: ::first-letter, ::first-line, ::selection.

::first-letter

Styles the first letter of a block‑level element (e.g., paragraph, heading).

p::first-letter {
  font-size: 60px;
  color: blue;
}

Effect: The initial character becomes large and blue, like a drop‑cap.

::first-line

Styles the first line of a block‑level element (the actual line as it wraps in the browser).

p::first-line {
  color: cadetblue;
}

Only the text on the first visual line receives the colour; subsequent lines remain unaffected.

::selection

Applies styles to the portion of an element that the user highlights (selects). Can be set globally or scoped to specific elements.

::selection {
  background-color: orange;
}
p::selection {
  background-color: darksalmon;
  text-decoration: underline;
}

Effect: Selecting any text shows an orange background; selecting text inside a <p> uses darksalmon with an underline.


Pseudo‑Class vs. Pseudo‑Element — Quick Comparison

AspectPseudo‑ClassPseudo‑Element
What it targetsA state of the elementA part or fragment of the element
SyntaxSingle colon :Double colon :: (legacy single‑colon also works for some)
Examplea:visitedp::first-letter
TriggerUser interaction or DOM positionStructural part of the element

Key Takeaways

  • Pseudo‑classes (:hover, :active, :nth-of-type()): style an element based on its state or position.
  • Pseudo‑elements (::first-letter, ::first-line, ::selection): style a specific part of an element.
  • :nth-of-type(An+B) accepts formulas: 2n = even, 3n = every third, etc. Without n, it selects only the nth occurrence.
  • Pseudo‑elements often use double colons (::) to distinguish them from pseudo‑classes, though older browsers may accept single colon.
  • Both require no extra HTML classes or IDs — purely CSS‑driven interactivity and typographic control.

CSS Inheritance

Inheritance is the mechanism by which certain CSS properties are automatically passed from a parent element to its child elements, unless the child has that property explicitly set. Intuitively: set a text color on <body> and every piece of text inside the page picks it up – no extra work needed.

Default inheritance from the nearest defined parent

When a property is inherited, a child element looks for the closest ancestor that has that property defined. If no ancestor has it, the default browser style applies.

Example – given this HTML:

<body>
  <h1>Heading</h1>
  <section>
    <h2>Subheading</h2>
    <p>Paragraph text</p>
  </section>
  <div>
    <h3>Div heading</h3>
    <input type="text">
    <button>Click</button>
  </div>
</body>
  1. Set color: goldenrod on <body> → all text inside inherits goldenrod.
  2. Then set color: blue on <section><h2> and <p> inside the section become blue (inherited from the closer parent). <h1>, <h3>, <input>, and <button> remain goldenrod because they still inherit from <body> – the section rule does not affect them.

The paragraph inspects as “inherited from section” (overriding “inherited from body”).

Exam tip: Inheritance doesn’t override explicit styles on the child – it only kicks in when no value is set on the child. Specificity and direct styling still win.

Elements that do not inherit by default

Form elements like <input> and <button> do not inherit text styling (color, font-family) from their parent by default. In the example, the button remained black (default user-agent style) even though <body> had color: goldenrod.

Forcing inheritance with the inherit keyword

You can explicitly tell an element to inherit any property using the inherit keyword.

button {
  color: inherit;   /* now takes the parent's goldenrod */
}

After adding this rule, the button’s text turns goldenrod. Developers use inherit to make form elements consistent with surrounding text.

Which properties are inherited?

There is no universal rule – you must check each property. The MDN documentation lists “Inherited” in the “Formal definition” section of every property.

Commonly inheritedCommonly not inherited
colormargin
font-family, font-sizeborder
letter-spacingpadding
text-alignwidth, height
visibilitybackground

Exam tip: The easiest way to know: if a property describes the appearance of text, it’s usually inherited. If it describes the layout or box of the element, it’s usually not inherited.

Recap with a decision tree

flowchart TD
  A[Parent property set] --> B{Is it an inherited property?}
  B -->|Yes| C{Does child have a direct value?}
  C -->|No| D[Child inherits parent value]
  C -->|Yes| E[Child uses its own value]
  B -->|No| F[Child uses own default or explicit value]
  D --> G[Child can override with inherit keyword if property is non-inherited]
  F --> G

Key takeaways

  • Inheritance allows child elements to automatically get a property’s value from the nearest ancestor that defines it.
  • Properties like color, font-family, and letter-spacing are inherited; margin, border, padding are not.
  • The inherit keyword forces any property (even non-inherited ones) to take the parent’s computed value – useful for form elements.
  • Elements inside <form> (inputs, buttons) often do not inherit by default; use inherit to align them.
  • MDN’s “Formal definition” section is the authoritative source for a property’s inheritance behavior.

The <span> Element for Inline Styling

The <span> element is an inline container that wraps around a portion of text (or other inline content) without breaking the flow of the document. Unlike a block-level <div> which takes the full width, <span> sits within the line, allowing precise CSS styling of only that fragment.

Intuitively: you want to colour one word red, underline a phrase, or enlarge the first letter – <span> gives you a handle to attach a class or ID and apply styles exactly where you want, without affecting surrounding text.

Comparing <span> and <div>

ElementDisplay typeDefault behaviourUse case
<span>InlineWraps content; stays within the lineStyling a word, phrase, or inline image
<div>BlockStarts on a new line; takes full widthStructuring sections, containers

Exam tip: <span> is the go‑to for “I need to style just this bit of text inside a paragraph.” It does not add any line breaks or semantic meaning – it’s purely a styling hook.

Worked example: Highlighting “highlighted heading”

HTML (inside a <h1>):

<h1>This is a <span class="highlight">highlighted heading</span></h1>

CSS:

.highlight {
  color: blue;
}

Result: only the words inside the <span> turn blue. The rest of the heading remains its original colour.

Using <span> for word‑ or line‑level styling

GoalApproachCSS applied
Style the first word of a paragraphWrap the first word in <span class="first-word">font-size: 2em; color: brown;
Style the first few linesWrap those lines (including spaces) in <span class="first-lines">text-decoration: underline; background-color: aqua;

Compared to CSS pseudo‑elements like ::first-letter or ::first-line, <span> gives more precise control – you can target arbitrary text fragments, not just the first letter/line.

How it works in practice

flowchart LR
    A[HTML text] --> B{Wrap fragment in <span>?}
    B -->|Yes| C[Attach class or id]
    C --> D[Write CSS rules for .class or #id]
    D --> E[Only wrapped fragment gets styled]

No extra markup, no layout shift – the inline flow continues unchanged.

Key takeaways

  • <span> is an inline, non‑semantic container for styling fragments.
  • It does not break the text flow or create new lines.
  • Use a class or ID on <span> to target it with CSS.
  • More flexible than pseudo‑elements for arbitrary text selection (e.g., first word, first two lines).
  • Works on any inline content, including images or other elements.

Display Property

The display property controls whether an element behaves as a block or inline box. Intuitively: block elements claim their own horizontal line; inline elements sit next to each other like words. By changing display, you override the default behavior of any element.

Default flow: block vs. inline

By default:

  • Block-level elements (e.g., <div>, <p>) stack vertically and take up the full available width.
  • Inline elements (e.g., <span>, <a>) flow along the same line as adjacent content.
PropertyBlock elementInline element
WidthTakes entire parent widthShrinks to content
StackingAlways new lineStays on same line
Box modelRespects width, height, margin, padding fullyIgnores height, vertical margin; horizontal padding/margin only shift content on that line

Changing display values

Syntax: display: block | inline | inline-block | none;

Example (from lecture)

HTML: <div class="block">...</div> and <span class="inline">...</span>.

With .block { display: inline; } and .inline { display: block; }:

  • The <div> no longer spans full width — it becomes inline.
  • The <span> takes full width — it becomes block.

Key insight: The display property overrides an element’s native behaviour; any element can become any box type.

Box-model behavior: inline vs. block

When adding height, width, padding, margin:

  • Block element: all properties are respected. Padding and margin push surrounding content both horizontally and vertically.
  • Inline element: height and vertical margin are ignored. Padding is applied visually but does not push content above or below — it only affects that line. This makes inline elements unsuitable for layout control.

Inline-block: the hybrid

A third value, display: inline-block, combines the best of both:

  • The element stays inline (it aligns with text and other elements on the same line).
  • It respects all box-model properties (width, height, margin, padding) on every side.
ValueStays inline?Respects width/height?Respects vertical margin?
blockNoYesYes
inlineYesNoNo
inline-blockYesYesYes

Practical example

Three <div> boxes (class box) with height: 100px; width: 100px; margin: 20px;:

  • display: block → stacked vertically.
  • display: inline → side by side but dimensions collapse to content (100px ignored).
  • display: inline-block → side by side, dimensions respected.

Exam tip: Use inline-block for buttons, badges, or icons that need to sit beside text while having explicit width/height.

Display: none

display: none completely removes the element from the rendered page — it leaves no trace, as if the element never existed (unlike visibility: hidden which still occupies space).

Use case

Hide a button until a user completes an action (e.g., form fill). The button exists in the HTML and can be shown later via JavaScript by switching display to block or inline-block.

<button type="button" class="hidden-btn">Click me</button>
.hidden-btn { display: none; }

Key difference: The element is invisible and does not affect layout; perfect for dynamic toggling.

Key takeaways

  • display overrides an element’s default box type: block, inline, inline-block, or none.
  • Block elements take full width, stack vertically, and respect all box-model properties.
  • Inline elements flow horizontally; they ignore height and vertical margin.
  • Inline-block gives inline flow with full box-model control — ideal for aligned, dimensioned components.
  • display: none hides an element completely; it is removed from layout and can be toggled by JavaScript.

Position Property

The position property controls how an element is placed in the document — relative to its normal flow, a parent, the viewport, or the scroll position. It takes one of five values: static, relative, absolute, fixed, or sticky. Together with the offset properties top, right, bottom, left, you can fine-tune placement.

flowchart LR
    A[position] --> B{Value?}
    B --> C[static]
    B --> D[relative]
    B --> E[absolute]
    B --> F[fixed]
    B --> G[sticky]
    C --> H[Default; no offset effect]
    D --> I[In flow; shifted from original position; space preserved]
    E --> J[Removed from flow; positioned relative to closest *positioned* ancestor or initial containing block]
    F --> K[Removed from flow; positioned relative to viewport; fixed on scroll]
    G --> L[In flow until scroll threshold; then behaves like fixed]

Static (position: static)

Default for all elements. The element follows normal document flow — block elements stack vertically, inline elements flow horizontally. Offset properties (top, left, etc.) have no effect; they are ignored.

MDN: The static property prevents top, left, etc. from having any effect. The element remains in its natural position.

Relative (position: relative)

The element stays in the normal flow (its original space is preserved), but you can shift it relative to its own original position using offset properties.

  • top: 50px moves the element down by 50px.
  • left: 50px moves it to the right by 50px (positive left adds space on the left side).
  • Negative offsets move in the opposite direction.

The original space remains occupied — other elements do not reflow into the gap.

Example:
A green box with position: relative; top: 50px; left: 50px; appears 50px down and 50px right from where it would have been, while its original footprint stays empty.

Absolute (position: absolute)

The element is removed from normal flow — no space is reserved for it. It is positioned relative to the closest positioned ancestor (an ancestor whose position is not static). If no such ancestor exists, it positions relative to the initial containing block (typically the <html> element).

Offset properties (top, left, etc.) specify the distance from the edges of that containing block.

Key behaviour:

  • Other elements ignore the absolute element; they may overlap.
  • The containing block must be positioned (e.g., relative, absolute, fixed, or sticky) for the absolute child to nest inside it.

Example:
A child div with position: absolute; top: 50px; left: 100px; inside a parent with position: relative; will be offset 50px from the top and 100px from the left of the parent’s content box. Without the parent being positioned, it would be relative to the document root.

Fixed (position: fixed)

The element is removed from normal flow and positioned relative to the viewport. It stays fixed in place even when the page is scrolled.

  • Offset properties (top, left, right, bottom) are relative to the viewport edges.
  • Commonly used for persistent navigation bars, back-to-top buttons, or sticky headers.

Example:
A fixed element with top: 100px; left: 500px; remains 100px from the top and 500px from the left of the viewport, unaffected by scrolling.

Sticky (position: sticky)

A hybrid: the element behaves as relative until a specified scroll threshold is reached, then becomes fixed relative to the viewport (or its scrolling container). It stays “stuck” as long as its parent container is visible.

  • Must have at least one offset property (e.g., top: 50px) to define the sticky point.
  • The element remains in the normal flow and its original space is preserved – when it becomes fixed, it “sticks” but the reserved space remains.
  • Important: The element’s parent must contain enough scrollable content for the sticky behaviour to work. If the parent is too short, the element will never reach its sticky point.

Exam tip: Always ensure the sticky element’s parent has overflow content (or sufficient height) that can be scrolled; otherwise, sticky will appear broken.

Example:
A heading with position: sticky; top: 0; inside a tall scrollable <div> will scroll normally until its top reaches the top of the viewport, then it “sticks” there while the rest of the content scrolls underneath.

Summary Table

ValueIn normal flow?Offset relative toSpace preserved?Page scroll effect
staticYes— (offsets ignored)YesScrolls normally
relativeYesIts own original positionYesScrolls normally
absoluteNoClosest positioned ancestor (or initial containing block)NoScrolls with document (unless in fixed ancestor)
fixedNoViewportNoStays fixed
stickyYes, until thresholdOwn flow, then viewportYesScrolls until threshold, then sticks

Worked Example (Conceptual)

Given three sibling boxes inside a container:

  • Box 1: static (default) → sits at top-left of container.
  • Box 2: relative; top: 30px; left: 20px; → moves down 30px and right 20px from where it would normally be; its original spot remains empty (visible as a gap).
  • Box 3: absolute; top: 0; right: 0; → container must have position: relative; otherwise Box 3 would go to document right‑top corner; it sits at top‑right corner of container, overlapping any content.

Key Takeaways

  • Use static for default flow; offsets are ignored.
  • relative keeps the element in flow but lets you nudge it; original space is preserved.
  • absolute removes the element from flow; position relative to the nearest positioned ancestor.
  • fixed pins the element to the viewport – stays on screen during scroll.
  • sticky toggles between relative and fixed at a defined scroll threshold; requires a scrollable parent.
  • The offset properties top, right, bottom, left only work when position is not static.

Float and Clear

Float and clear are CSS properties originally designed to wrap text around images—like a newspaper layout. Intuitively: you want an image on the side and let the text flow naturally around it. Float was not intended for overall page layout; use Flexbox or CSS Grid for that. Understanding float/clear, however, builds a solid CSS foundation.

The float Property

  • Purpose: Takes an element out of the normal document flow and positions it to the left or right, allowing inline content (e.g., text) to wrap around it.
  • Values: left | right | none (default)
  • Effect: The floated element stays part of the page but no longer participates in the normal flow—subsequent content “flows” around it.
/* Float an image to the left */
img {
  float: left;
}

Common pitfall: Because floated elements are removed from normal flow, they can cause overlapping or collapsed parent containers. This is why float is tricky for layouts.

The clear Property

  • Purpose: Applied to a non-floated element (e.g., a paragraph) to prevent it from wrapping around a floated element. It forces the element to start below any floated elements on the specified side.
  • Values: left | right | both | none (default)
ValueEffect
leftClears only left-floated elements; element starts below them.
rightClears only right-floated elements.
bothClears both left and right floats; element starts on a new line below.
/* Force a paragraph to appear below any left-floated elements */
#p-other {
  clear: left;
}

How they work together

flowchart LR
    A[Floated element] -->|float: left/right| B[Element removed from normal flow]
    B --> C[Next content wraps around it]
    C --> D{Has clear?}
    D -->|clear: left/right/both| E[Content starts below the float]
    D -->|no clear| F[Content continues wrapping]

Real example (from the lecture)

Given an image floated left and two paragraphs:

  • Without clear: Both paragraphs wrap around the image.
  • With clear: left on the second paragraph: That paragraph starts below the image (on the left side), ignoring the float.
  • With clear: both: The element is forced below all floats on either side.

Caveat: float for layout is obsolete

Floated layouts are fragile—elements overlap, containers collapse, and responsive design becomes painful. Modern CSS provides Flexbox and Grid for robust, predictable layouts. Float should only be used for its original purpose: text wrapping around media.

Exam tip: If a question asks about the original purpose of float, answer wrapping text around images, not layout. And remember that clear is applied to the following element, not the floated one.

Key takeaways

  • float: left/right moves an element out of normal flow so text wraps around it.
  • clear: left/right/both forces a non-floated element to start below any floated elements.
  • Float was designed for newspaper-style text wrapping, not page layout.
  • For layout, use Flexbox or Grid.
  • Floated elements can cause unpredictable overlapping and container collapse.

Styling a Website with CSS

CSS (Cascading Style Sheets) controls the visual presentation of a web page. The goal is to apply styles consistently while making minimal changes to the HTML structure. Styling begins by inspecting the target design — colours, fonts, and layout — then replicating them through selectors, the box model, and pseudo-classes.

Extracting design specs

Use the CSS Overview tool in Chrome DevTools to capture the design system of a reference website:

  1. Right-click → Inspect → three-dot menu → More tools → CSS Overview.
  2. Capture an overview to see lists of text colours, background colours, font families, font sizes, and unused declarations.

Example: the IIMB website uses Times New Roman as font, and specific hex colours (e.g., #72828, #aabbcc).

Exam tip: The CSS Overview tool is not a standard exam requirement, but understanding how to extract colours and fonts from any page is a practical skill often tested in applied coding tasks.

Structuring the header

A header containing a logo image and a heading can be wrapped in a <div> with a class (e.g., main-div). Style it using the class selector (.main-div).

.main-div {
  border-bottom: 5px solid #72828;
  padding: 20px;
}

To align logo and heading side by side, set the immediate children (image and <h1>) to display: inline-block and use vertical-align: middle.

.main-div > * {
  display: inline-block;
  vertical-align: middle;
}

Spacing can be added via padding on the <h1>. For centering the header content, use calc() to subtract the logo width from 50%:

.main-div h1 {
  padding-left: calc(50% - 400px); /* approximate centering */
}

Exam tip: calc() is a powerful CSS function; you can combine any units. However, for production layouts, Flexbox or Grid are preferred (covered in the next module).

Global typography

Set a default font for the entire page using the element selector on html or body:

html {
  font-family: Times New Roman, serif;
}

Style headings and paragraphs with colour, font-size, and text alignment. Use the descendant selector to target elements after a specific parent (e.g., p immediately after .main-div):

.main-div + p {
  font-size: x-large;
  text-align: center;
  color: #72828;
}

Navigation interactivity

The navigation bar (<nav>) can be centred, padded, and its anchor links styled as buttons.

  1. Style the <nav> element: text-align: center; padding: 40px;
  2. Style the <a> tags inside <nav> using nav a selector.
nav a {
  display: inline-block;          /* allows padding */
  padding: 20px 10px;
  border: 3px solid red;
  border-radius: 30px;           /* rounded corners */
  background-color: #aabbcc;
  color: white;
  font-weight: bold;
}

Add interactivity with pseudo-class selectors:

Pseudo-classTriggerExample
:hoverMouse over elementChange background to a lighter colour, text to white
:activeWhile element is being clickedChange background to a darker colour
nav a:hover {
  background-color: lightblue;
  color: white;
}
nav a:active {
  background-color: darkblue;
}

These styles apply to all pages because the same CSS file is linked to every HTML file, and the selector (nav a) matches all navigation links.

Table styling

Tables use <th> (header cells) and <td> (data cells). Default behaviour shows separate borders with gaps — use border-collapse: collapse on the <table> element to merge them.

table {
  border-collapse: collapse;
  text-align: center;
  width: 100%;
}
th {
  border: 2px solid #72828;
  background-color: #aabbcc;
  color: white;
}
td {
  border: 1px solid #72828;
  padding: 10px;
}

Exam tip: border-collapse applies only to the <table> (or inline-table) element, not to <th> or <td>. Applying it to individual cells will have no effect.

Set column width using width on <th> or <td>, and adjust cell spacing with padding.

Form and button styling

Style <input>, <select>, and <button> elements to match the theme.

  • For input fields: border: 2px solid #72828
  • Apply to both <input> and <select> using a group selector: input, select { ... }
input, select {
  border: 2px solid #72828;
}
form {
  color: #72828;
}

Style the submit button (<button>):

button {
  background-color: #aabbcc;
  color: white;
  padding: 20px;
  border: none;
  border-radius: 20px;
  font-weight: bold;
}

Add hover and active effects with the same pseudo-class pattern as the navigation links.

Background and layout adjustments

Apply a background colour to the entire page using the body selector. Remove the default margin on body to eliminate white edges.

body {
  background-color: #e0e0e0;
  margin: 0;
}

To prevent the header from inheriting the background, give the .main-div a white background. Use the main element (already present in HTML) to add padding for content below the header.

.main-div {
  background-color: white;
}
main {
  padding: 10px;
}

The box model is referenced whenever inspecting sizes in the DevTools – padding, border, and margin can be observed and adjusted directly.

Exam tip: The box model (content → padding → border → margin) is fundamental. When styling, always check the computed dimensions in the Elements panel to debug unexpected spacing.

Key takeaways

  • Use CSS Overview in DevTools to extract a design’s colours and fonts.
  • Style with class selectors (.class) and element selectors (e.g., html, body).
  • Align elements side-by-side with display: inline-block and vertical-align: middle.
  • Add interactivity via :hover and :active pseudo-classes.
  • Tables require border-collapse: collapse on the <table> to remove gaps.
  • Use calc() for dynamic spacing; prefer Flexbox/Grid in production.
  • Always check the box model in DevTools to understand padding, border, and margin contributions.

Introduction to Web Development

Introduction to Web Development

This module lays the theoretical foundation for understanding how the internet works and how websites come to life. Before building anything, it is essential to grasp the core concepts: the internet as a global network, the browser as the access tool, the client–server model, DNS (Domain Name System), IP addresses, and the physical infrastructure (underwater cables). The module also introduces the two sides of development – frontend (user-facing) and backend (server-side) – and the broader societal impact of the web.

Tips for Learning Web Development

Effective learning requires a mindset shift. Follow these strategies to build real skill, not just passive knowledge.

  • Watch first, then code. Do not write code while watching the video. Focus on understanding the element being taught.
  • Pause and try on your own. After watching, pause the video and write the code yourself. If stuck, search your book or online. This builds problem-solving ability.
  • Embrace frustration. Getting stuck is normal. Take a break, clear your mind, and return with a fresh perspective.
  • Use resources. Search online, read the provided book, ask on forums – do not give up.
  • Understand, don’t memorise. Coding is about understanding how elements work together, not memorising every line.
  • Troubleshoot independently. Attempt to fix issues on your own before checking the solution.

Exam tip: The single most important habit is pausing and coding from scratch. This trains the same debugging mindset used by professional developers.

What is the Internet?

At its core, the internet is a massive network of wires and connections linking computers worldwide. When a computer in Mumbai sends a message to one in New York, the data travels through these physical wires.

Key Concepts

  • Clients and Servers
    • Server: A computer that is always online and stores/sends information (e.g., YouTube videos, Instagram reels).
    • Client: Your device (phone, tablet, laptop) that requests data from servers.
  • IP Address (Internet Protocol address): Every device connected to the internet has a unique numeric address (e.g., 132.431.53.134). It acts like a home address for computers and servers.
  • ISP (Internet Service Provider): The company that provides internet access (e.g., Jio, Airtel, BSNL in India). It forwards requests from your browser to the DNS server.
  • DNS (Domain Name System): Acts as the internet’s phonebook. Humans use domain names (e.g., youtube.com), but browsers use IP addresses. DNS translates domain names into IP addresses.
TermRoleExample
ClientRequests dataYour laptop running Chrome
ServerStores and sends dataYouTube’s server
IP AddressUnique identifier for devices132.431.53.134
ISPProvides internet connectionJio, Airtel, BSNL (in India)
DNSTranslates domain names → IPsyoutube.com → server IP

What Happens When You Load a Website?

  1. You type youtube.com into your browser (e.g., Chrome).
  2. The browser does not know the server’s location → it asks your ISP for help.
  3. The ISP forwards the request to a DNS server.
  4. The DNS server looks up the IP address of youtube.com and sends it back to the browser.
  5. The browser now knows the IP address and can connect directly to YouTube’s server to load the webpage.
flowchart LR
  A[Browser: type youtube.com] --> B[ISP]
  B --> C[DNS Server]
  C --> D[Returns IP address of YouTube server]
  D --> A
  A --> E[YouTube Server]
  E --> A[Loads webpage]

Physical Infrastructure: Underwater Sea Cables

Data travels across oceans through massive underwater sea cables laid on the ocean floor, connecting countries and continents. These cables transmit data at nearly the speed of light, enabling global communication in milliseconds. (A map can be viewed at submarinecablemap.com.)

Key takeaways

  • The internet is a global network of physical wires; computers communicate via clients and servers.
  • Every device has a unique IP address; servers are always online.
  • DNS translates human-friendly domain names into machine-readable IP addresses.
  • ISPs and DNS servers are intermediaries that help browsers find the correct server.
  • Physical data transfer across continents uses underwater sea cables (speed-of-light latency).

Web Browser

A web browser is any application that fetches and displays web pages, letting you navigate the internet. Popular examples: Chrome, Firefox, Safari, Edge. When you visit a website, the browser sends a request to the server for the files that make up the page — then interprets and renders them into the visual interface you see.

How a web page loads

  1. User enters a URL (or clicks a link).
  2. Browser sends a request to the server.
  3. Server responds with a set of files:
    • HTML – structure and content
    • CSS – styling and layout
    • JavaScript – interactivity and dynamic behaviour
    • Other resources – images, fonts, etc.
  4. Browser processes these files sequentially (HTML first, then CSS and JS, then assets) to construct the final rendered page.
flowchart LR
  A[Browser] -- "Requests files" --> B[Server]
  B -- "Sends HTML, CSS, JS, images" --> A
  A -- "Renders page" --> C[Displayed web page]

Files that form a web page

File TypeRole
HTMLDefines the structure and content (headings, paragraphs, links)
CSSControls presentation (colours, fonts, spacing, responsive layout)
JavaScriptAdds interactivity (animations, form validation, API calls)
Other (images, fonts, etc.)Embedded media and typography resources

Each file plays a unique role; the browser assembles them in real time to produce the complete page.

Key takeaways

  • A web browser is an application for viewing and navigating the internet.
  • It loads a website by requesting files from a server.
  • The essential file types are HTML, CSS, JavaScript, and additional assets like images and fonts.
  • These files are combined and rendered by the browser to create the visual webpage.

HTML, CSS and JavaScript

Web pages are built from three core technologies that work together: HTML, CSS, and JavaScript. Each plays a distinct role — structure, style, and behaviour — and a browser combines them to render a complete, interactive page.

HTML – Structure and Content

HTML (HyperText Markup Language) provides the skeleton of a web page. It defines the content to be displayed (text, images, links) and organises it into a logical hierarchy: headings, paragraphs, lists, sections, and more.

  • Think of HTML as the outline the browser uses to understand the page’s structure.
  • On a blog, the HTML file holds the article text, titles, and image references — but looks plain on its own, without colours or styling.

CSS – Style and Design

CSS (Cascading Style Sheets) controls the visual presentation of HTML elements. It adds colour, fonts, spacing, layout, background effects, and even animations.

  • CSS transforms a raw HTML skeleton into something visually appealing.
  • You can target any HTML element (e.g., a text block) and change its colour, boldness, background, or position.
  • Styling ranges from small font-size tweaks to the entire page layout.

JavaScript – Interactivity and Logic

JavaScript is a programming language that brings the page to life with dynamic behaviour. While HTML and CSS handle static content and presentation, JavaScript enables:

  • Interactivity – e.g., a button that shows a pop-up message when clicked.
  • Logic – e.g., an online shopping cart that recalculates the total price as items are added or removed.
  • The core idea: “When this, do that” – JavaScript executes functions in response to events.

How the Browser Puts It All Together

When you load a website, the browser receives the HTML, CSS, and JavaScript files from a server. It then stitches them together:

flowchart LR
    A[Server] --> B[HTML: structure & content]
    A --> C[CSS: style & layout]
    A --> D[JavaScript: interactivity & logic]
    B --> E[Browser]
    C --> E
    D --> E
    E --> F[Final interactive web page]

The browser processes each file in order — first the HTML to build the document, then CSS to style it, and finally JavaScript to add dynamic features. The result is what you see on your screen.

Exam tip: A common question asks which technology does what. Remember the analogy:
HTML = skeleton, CSS = skin/clothes, JavaScript = muscles that move. Never mix them up.

Key takeaways

  • HTML defines the content and structure of a web page.
  • CSS handles the visual styling (colours, fonts, layout).
  • JavaScript adds dynamic behaviour and logic (click actions, calculations).
  • The browser requests all three files, then combines them to display a functional page.
  • Each technology is essential; without one, the page would be incomplete (plain, unstyled, or static).

HTTP Request

When you type a URL, your browser must ask a server for files. But browsers and servers are built by different companies, run on different devices. How do they understand each other? They need a common language—a protocol. HTTP (Hypertext Transfer Protocol) is that language for the web. An HTTP request is the formal message your browser sends to the server to initiate this conversation.

What HTTP is

HTTP = Hypertext Transfer Protocol. A set of rules (grammar) that defines how data is formatted and transmitted between browsers and servers. It ensures any browser can talk to any server, regardless of device or network.

How it fits into the request–response cycle

  1. User types flipkart.com in the browser.
  2. Browser sends an HTTP request to Flipkart's server.
  3. Server processes the request and responds with files: HTML, CSS, JavaScript, and other resources.
  4. Browser interprets these files and renders the webpage.

HTTP is the middleman that makes steps 2 and 3 work universally.

Other protocols – a comparison

HTTP is one of many application-layer protocols. Each serves a specific purpose.

ProtocolFull NamePurpose
HTTPHypertext Transfer ProtocolTransfer web pages and data
HTTPSHypertext Transfer Protocol SecureEncrypted (secure) version of HTTP
FTPFile Transfer ProtocolTransfer files between computers
SMTPSimple Mail Transfer ProtocolSend email messages

Exam tip: Know that HTTPS is the secure variant of HTTP. The transcript explicitly calls it “the secure version”. Do not confuse FTP (file transfers) with SMTP (email).

Key takeaways

  • HTTP is the protocol that governs browser–server communication.
  • An HTTP request is the browser’s formal message asking for resources.
  • The protocol guarantees interoperability across different devices and networks.
  • Other protocols (HTTPS, FTP, SMTP) exist for security, file transfer, and email respectively.
  • The request–response cycle: browser requests → server returns HTML/CSS/JS → browser renders page.

Frontend and Backend

The web application is split into two main sides. The frontend is everything the user sees and interacts with in the browser (layouts, buttons, images). The backend is the hidden machinery that stores, processes, and serves data. The two communicate via the request-response cycle using HTTP.

flowchart LR
    A[Browser / Frontend] -- HTTP request --> B[Server / Backend]
    B -- "retrieve / store data" --> C[(Database)]
    C -- data --> B
    B -- HTTP response --> A

Frontend (Client‑Side)

  • What it is: The user interface (UI) — everything rendered in the browser.
  • Technologies: HTML (structure), CSS (styling, colors, fonts, layout), JavaScript (interactivity, dynamic behaviour).
  • Goal: Provide an appealing, smooth visual experience. Clicking a button, scrolling, or watching a video all happen on the frontend.

Backend (Server‑Side)

  • What it is: Everything that happens behind the scenes — data storage, processing, retrieval, user management, authentication, transaction handling.
  • Technologies: Languages like Python, Java, Ruby, or JavaScript‑based frameworks like Node.js. Backend code runs on a server.
  • Goal: Power the features the frontend presents to users (e.g., logins, course tracking, personalised feeds).

When a Backend Is Needed

Not every website requires a backend. The need depends on complexity.

TypeExampleBackend needed?Reason
Simple static siteIIMB DBE website (info only)NoJust display text, images, and static content.
Dynamic / heavy appIIMBx e‑learning platform, social media, e‑commerce, NetflixYesUser logins, course tracking, personalised data, complex interactions.

Backend handles:

  • Data storage and retrieval (e.g., profiles, uploaded files)
  • User authentication and management
  • Complex processing (e.g., transactions, recommendations)

Course Focus: Frontend Web Publishing

This course concentrates on web publishing – building and styling static websites using frontend technologies only (HTML, CSS, JavaScript). You will learn to create interactive, attractive sites for blogs, portfolios, small businesses – no backend required.

Exam tip: “Static” = no backend, content fixed; “dynamic” = backend processes data and serves personalised content. Know the difference and examples.

Why learn JavaScript here? JavaScript is the bridge – mastering it in the frontend gives a strong foundation for later exploring backend development (e.g., Node.js).


Key takeaways

  • Frontend = browser UI (HTML, CSS, JavaScript); backend = server‑side data processing (Python, Java, Ruby, Node.js).
  • The request-response cycle and HTTP connect frontend and backend.
  • Simple sites (e.g., information pages) can be purely frontend; dynamic apps (e‑commerce, social media) require a backend.
  • This course covers frontend web publishing – no backend; JavaScript learned now prepares you for future backend work.

The Beginning of the Digital Age (Early 1990s)

The modern internet began in the early 1990s with Tim Berners-Lee inventing HTTP and HTML — the foundational technologies that enabled information sharing and browsing. Before this, networks existed only within research institutes and government. Websites were basic, text-based, and static. Early browsers like Netscape Navigator and Internet Explorer let people explore the web, but content was largely one-way.

Businesses recognised the potential and rushed to establish an online presence, sparking the dot-com boom. Venture capitalists invested heavily in any venture with a .com name, assuming every such business would become a global giant (e.g., Peck.com, Boo.com).

Key takeaways

  • Tim Berners-Lee introduced HTTP and HTML, enabling the World Wide Web.
  • Early websites were static and text-only, accessed via Netscape Navigator or Internet Explorer.
  • The dot-com boom was driven by hype and easy venture capital.

The Dot-Com Boom and Bust (Late 1990s–2000)

The rapid growth of internet-based businesses created a bubble. Companies launched websites believing any .com would make money. Around 2000 the dot-com bubble burst, causing a market crash. Businesses built on hype without real substance disappeared. Those with a sound business plan and a unique or well-defined market niche survived and thrived — e.g., Amazon and Google. In India, early players like Rediff (email & news) and Naukri (job search) were part of this wave.

Key takeaways

  • The bubble burst eliminated companies with no real business model.
  • Survivors (Amazon, Google) had clear value propositions and sustainable plans.
  • Indian examples: Rediff and Naukri.

Post-Crash Maturation & Rise of Digital Business (2000s)

After the crash, digital businesses matured, becoming user-focused. Global platforms like Google, Facebook, and YouTube redefined search, social connection, and content sharing. In India:

  • MakeMyTrip (founded 2000) transformed travel booking.
  • Shaadi.com brought matchmaking online.
  • Flipkart (founded 2007) started as an online bookstore and expanded into a full e-commerce platform.

Key takeaways

  • Focus shifted from hype to real user value.
  • Indian startups addressed local needs (travel, matrimony, e-commerce).
  • Flipkart’s growth showed the potential of Indian e-commerce.

Mobile & Social Media Era (2010s)

The launch of the iPhone in 2007 made internet access mobile and always available via apps. In India, Reliance Jio (2016) offered affordable data plans, bringing fast internet to millions and accelerating digital adoption. WhatsApp became India’s primary messaging app; Paytm led digital payments. Social media platforms (Facebook, Instagram, Twitter) connected people in real time, influencing trends, culture, and politics. Businesses used these platforms for direct customer engagement and real-time brand loyalty.

Key takeaways

  • Smartphones (iPhone) made internet ubiquitous; apps became the primary interface.
  • Reliance Jio dramatically lowered data costs, expanding Indian internet users.
  • Social media enabled direct business-to-consumer engagement.

UPI & India’s Digital Payment Revolution

The Unified Payments Interface (UPI), launched in 2016, revolutionised cashless transactions. Apps like PhonePe, Google Pay, and Paytm adopted UPI, making payments quick and seamless. Today UPI processes billions of transactions monthly, positioning India as a global leader in digital payments.

Key takeaways

  • UPI made digital payments instant, simple, and interoperable.
  • Apps like PhonePe and Google Pay drove mass adoption.
  • India became a world leader in digital payment volume.

Cloud Computing, Big Data & the Modern Indian Digital Ecosystem

As digital businesses scaled, cloud computing (AWS, Microsoft Azure, Google Cloud) removed the need for physical servers. Indian startups like Swiggy (food delivery), Zomato, and Ola (cab booking) leveraged cloud and data analytics to deliver real-time services without heavy infrastructure investment. Big data — collected from searches, social media, and transactions over 30+ years — became a crucial resource for training modern AI systems and delivering personalised services.

Key takeaways

  • Cloud computing enabled startups to scale without owning servers.
  • Big data drives AI and personalisation.
  • Indian startups (Swiggy, Zomato, Ola) exemplify cloud-powered local services.

Internet’s Lasting Impact on Businesses & Daily Life

The internet now touches every industry: retail, entertainment, education, finance. Traditional businesses have moved online; digital-first companies like Swiggy, Hotstar (streaming), and Zerodha (stock trading) have created entirely new markets. Digital marketing, e-commerce, and cloud services are essential for all businesses — even small ones need an online presence to reach customers. Since the 1990s, the internet has transformed how people communicate, learn, shop, work, and do business globally and in India.

Exam tip: The dot-com bust is a classic case study: survivorship depended on real business models, not hype. Know the distinction between survivors (Amazon, Google) and failures (Peck.com). Also note UPI as a uniquely Indian innovation that accelerated digital payments.

Key takeaways

  • The internet has reshaped every major industry globally and in India.
  • Digital-first companies (Swiggy, Hotstar, Zerodha) created new markets.
  • Modern businesses require an online presence regardless of size.

JavaScript DOM Manipulation

What is the DOM?

The Document Object Model (DOM) is the bridge between JavaScript and a webpage. It is a structured, object-oriented representation of the HTML content that the browser creates when a page loads. The DOM treats the HTML document as a tree of nodes, where each HTML element becomes a JavaScript object.

Without the DOM, JavaScript would have no way to interact with the page. With the DOM, we can:

  • Change text and attributes without reloading
  • Show or hide elements based on user actions
  • Create animations and effects
  • Build interactive components (forms, sliders, etc.)

Examples from real sites — Amazon’s live cart count, social media comment updates, reaction buttons — all rely on JavaScript manipulating the DOM.

Exam tip: The DOM is language-independent (used by Python, Ruby, etc.), but in web development we interact with it purely through JavaScript in the browser.

DOM Tree Structure

Every time an HTML page is loaded, the browser builds a tree of objects. Each HTML element becomes a node; relationships between nodes (parent, child, sibling) define the tree’s hierarchy.

graph TD
    document["document (root)"] --> html["html"]
    html --> head["head"]
    html --> body["body"]
    head --> title["title"]
    head --> meta["meta"]
    body --> h1["h1"]
    body --> p["p"]
    p --> ol["ol"]
    ol --> li1["li"]
    ol --> li2["li"]
    ol --> li3["li"]
    body --> h2["h2"]
    body --> p2["p"]
  • The document object is the top-level entry point (parent of everything).
  • Every node has properties like children, parentNode, nextSibling.
  • Each node is a full JavaScript object with its own properties and methods.

The Document Object

The document object is created automatically by the browser when the page loads. It can be accessed directly in the console or in scripts.

console.log(document);           // shows the HTML representation
console.dir(document);           // shows the JavaScript object with all properties

console.dir(document) reveals a massive object with properties such as:

PropertyDescription
titleThe page <title> text
bodyThe <body> element object
childrenHTMLCollection of top-level children (usually <html>)
allAll elements in the document
URLCurrent page URL
anchorsCollection of anchor (<a>) elements
headThe <head> element object
formsCollection of <form> elements

These properties themselves are objects that can be drilled into with dot notation:

document.body.children          // HTMLCollection of <header>, <main>, <script>, etc.
document.body.children[0]       // first child of <body>
document.title                  // returns the page title string

Navigating the DOM

Because the DOM is a tree, you can traverse it step by step:

document.body.children          // direct children of <body>
document.body.children[1]       // second child (often <main>)
document.body.children[1].children[0]  // first child of <main>

Each node also has properties for relationships:

  • parentNode
  • firstChild
  • lastChild
  • nextSibling
  • previousSibling

Exam tip: children returns only element nodes (ignoring text/whitespace). Use childNodes to get all node types.

Manipulating Elements (Quick Examples)

Once you have a reference to a DOM node, you can change its content or style in real time.

Change text content:

document.body.children[1].children[0].innerText = "Haha you are hacked!";

Change background color:

document.body.style.backgroundColor = "yellow";

Change inner HTML (includes tags):

element.innerHTML = "<strong>New content</strong>";

These simple manipulations show the power of the DOM: no page reload needed.

Key takeaways

  • The DOM is a tree of JavaScript objects representing the HTML structure.
  • document is the entry point – everything starts from it.
  • Every element is an object with properties (e.g., title, body, children) and methods (e.g., style, innerText).
  • Use console.dir(document) to explore the live DOM object.
  • Navigate using dot notation and index-based children.
  • Manipulation is immediate – change text, HTML, or CSS on the fly.

Connecting JavaScript to HTML

To manipulate a web page with JavaScript, you must first link the JS code to the HTML document. Without this connection, the browser cannot run your scripts or interact with the DOM.

Three ways to embed JavaScript

MethodHow it worksBest forPitfalls
InlineCode placed directly inside an HTML element’s event attribute, e.g., onclick="alert('Hi')"Quick tests of single-line actionsMixes logic with markup; quotation mark conflicts; unreadable as project grows
InternalCode written inside a <script> tag in the HTML file (in <head> or <body>)Small projects or one-off scriptsStill couples JS with HTML; not reusable across pages
ExternalCode in a separate .js file, linked via <script src="file.js">All real-world projectsRequires correct file path and placement

Exam tip: Never use inline JavaScript in production. It violates separation of concerns, becomes unmanageable, and confuses quote nesting — exactly like mixing inline CSS into HTML.

Where to place the <script> tag

Script placement determines when the JS code runs relative to the HTML elements it needs to interact with.

flowchart TD
  A[Script placed in <head>] --> B[JS runs before HTML body loads]
  B --> C{Target element exists?}
  C -->|No| D[Error: cannot read property of null]
  C -->|Yes – e.g. script in <body> after elements| E[Works fine]

  F[Script placed at bottom of <body>] --> G[HTML loads first]
  G --> H[All elements exist when JS runs]
  H --> I[Safe to query and manipulate DOM]
  • Best practice: place the <script> tag just before the closing </body> tag. This ensures all DOM nodes are created before JS tries to access them.
  • Result: no null-reference errors and faster perceived load time (HTML renders first, JS executes after).

Worked example: script in <head> vs. <body>

Given HTML with <h1>Original</h1> and a script that tries to change it:

<!-- BAD: script in <head> -->
<head>
  <script>
    document.querySelector('h1').innerText = 'Changed'; // runs before <h1> exists → null error
  </script>
</head>

<!-- GOOD: script at bottom of <body> -->
<body>
  <h1>Original</h1>
  <!-- ... -->
  <script>
    document.querySelector('h1').innerText = 'Changed'; // works fine
  </script>
</body>

Key takeaways

  • Inline JS is quick but messy — avoid beyond one-liners.
  • External JS (separate .js file) is the cleanest, most reusable method.
  • Place <script> at the bottom of <body> to guarantee all elements are loaded.
  • Placing scripts in <head> frequently causes null errors when the script attempts to access DOM elements that don't exist yet.

Selecting DOM Elements

Before you can modify a web page, you must select the element(s) you want to interact with. JavaScript provides several methods on the global document object to do this.

Old-style selectors (still valid but less flexible)

MethodReturnsExampleNotes
document.getElementById('id')Single elementdocument.getElementById('main-paragraph')IDs must be unique; fast
document.getElementsByClassName('class')HTMLCollection (live, array-like)document.getElementsByClassName('main-div')Index with [0] to get first
document.getElementsByTagName('tag')HTMLCollectiondocument.getElementsByTagName('li')Use index to access specific item

HTMLCollection is a live collection – it updates automatically when the DOM changes. It does not have forEach or other array methods (though you can convert it with Array.from).

Modern, powerful selector: querySelector and querySelectorAll

These methods accept any CSS selector string, making them far more flexible.

MethodReturnsExample
document.querySelector(selector)First matching element (or null)document.querySelector('.main-div')
document.querySelectorAll(selector)NodeList (static, array-like)document.querySelectorAll('li img')

NodeList is static (does not update when DOM changes) and supports forEach directly.

CSS selector examples (same as in stylesheets)

// By ID (use #)
document.querySelector('#main-paragraph')

// By class (use .)
document.querySelector('.main-div')

// By tag name
document.querySelector('h1')

// Descendant
document.querySelectorAll('.main-div img')

// Complex: image inside an li
document.querySelectorAll('li img')

Exam tip: Prefer querySelector and querySelectorAll over old methods. They are more powerful, easier to remember (use CSS syntax you already know), and cover every selection scenario.

Assigning selections to variables

Once selected, you can store the element reference in a variable and reuse it.

const paragraph = document.getElementById('main-paragraph');
paragraph.innerText = 'Modified text';
paragraph.style.backgroundColor = 'brown';

Why use const for DOM elements?
Variables assigned to objects (including DOM elements) store a reference to the object, not a copy. Using const prevents accidental reassignment of the variable to a different element, but still allows you to change the element's properties.

const arr = [1, 2];
arr[0] = 23;    // allowed – array content changes
// arr = [3,4];   // error – cannot reassign a const

const heading = document.querySelector('h1');
heading.innerText = 'New'; // allowed
// heading = somethingElse; // error – keeps reference stable

Key difference: HTMLCollection vs. NodeList

  • getElementsByClassName / getElementsByTagNameHTMLCollection (live, no forEach)
  • querySelectorAllNodeList (static, has forEach)

Worked example: changing the first image’s alt text

const images = document.querySelectorAll('img'); // NodeList
images[0].alt = 'ha ha ha';   // change alt of first image

Key takeaways

  • Select by ID with getElementById or querySelector('#id') – always returns a single element.
  • Select by class/tag with getElementsByClassName/getElementsByTagName returns an HTMLCollection.
  • Best practice: use querySelector (first match) and querySelectorAll (all matches) for any CSS selector.
  • Store selections in variables – prefer const for stability (the element reference is fixed, properties remain changeable).
  • All selection methods are called on document (e.g., document.querySelector()).

DOM Traversing

DOM traversal is the ability to navigate the relationships between elements in the DOM tree — moving to an element's parent, children, or siblings. Think of the DOM as a family tree: each element is a node connected to others. Traversal methods let you target elements based on their position, essential for dynamic web interactions.

Parent Access

  • parentElement – returns the immediate parent HTML element of the selected element.
    • Chaining .parentElement repeatedly climbs the tree: element.parentElement.parentElement gives the grandparent.
const h2 = document.querySelector('h2');
h2.parentElement;           // <section>
h2.parentElement.parentElement; // <main>

Note: The root of the tree is document; its parent is null.

Children Access

  • children – returns a live HTMLCollection of only HTML child elements (ignores text nodes, comments).
    • To get all child nodes including text, use childNodes (rarely needed for traversal).
const body = document.querySelector('body');
body.children;   // [<header>, <main>, <script>, ...]
  • firstElementChild – first child element.
  • lastElementChild – last child element.
  • childElementCount – number of child elements (equivalent to children.length).
body.firstElementChild;  // <header>
body.lastElementChild;   // <script>
body.childElementCount;  // 3 (example)

Sibling Access

  • nextElementSibling – the next sibling element (following the same parent).
  • previousElementSibling – the previous sibling element.

Chaining these moves horizontally through the tree.

const divMain = document.querySelector('.main');
divMain.nextElementSibling;          // <p>
divMain.nextElementSibling.nextElementSibling; // <button>
divMain.previousElementSibling;      // null (if first child)

Visualising Traversal

flowchart TD
    A["element"]
    A --> B["parentElement"]
    A --> C["children"]
    A --> D["firstElementChild"]
    A --> E["lastElementChild"]
    A --> F["nextElementSibling"]
    A --> G["previousElementSibling"]
    C --> H["childElementCount"]
    style A fill:#e1f5fe,stroke:#01579b
    style B fill:#fff9c4,stroke:#f57f17
    style C fill:#fff9c4,stroke:#f57f17
    style D fill:#fff9c4,stroke:#f57f17
    style E fill:#fff9c4,stroke:#f57f17
    style F fill:#fff9c4,stroke:#f57f17
    style G fill:#fff9c4,stroke:#f57f17
    style H fill:#f0f4c3,stroke:#827717

Worked Example: Climbing the Tree

Given the HTML structure from the lecture:

<body>
  <header>
    <div class="main">...</div>
    <p>...</p>
    <button>...</button>
  </header>
  <main>
    <section>...</section>
    <section>...</section>
  </main>
</body>
// Start with the first <li> inside a list
const li = document.querySelector('li');
li.parentElement;                     // <ul>
li.parentElement.parentElement;       // <section> or parent container
li.children;                          // [<br>, <img>] (HTMLCollection)
li.nextElementSibling;                // next <li> (if any)
li.previousElementSibling;            // previous <li> (if any)

Property Summary

PropertyReturnsUse
parentElementSingle elementClimb one level up
childrenLive HTMLCollectionAll child elements
firstElementChildSingle elementFirst child
lastElementChildSingle elementLast child
childElementCountNumberCount children
nextElementSiblingSingle elementMove forward
previousElementSiblingSingle elementMove backward

Exam tip: children returns only elements, not text nodes. If you need all nodes (including whitespace), use childNodes. But for traversal, always prefer the element-specific properties — they are robust and what exam questions expect.

Key Takeaways

  • parentElement climbs up; children, firstElementChild, lastElementChild go down.
  • nextElementSibling / previousElementSibling move sideways among siblings.
  • childElementCount gives the number of child elements quickly.
  • Chaining these methods navigates the tree in any direction (up, down, sideways).
  • All methods return null or empty collections when nothing exists — always check before further chaining.

Modifying Styles and Attributes with JavaScript

JavaScript + the DOM lets you change how a page looks and behaves on the fly — reacting to user actions, time, or any condition. At its core: you grab an element and rewrite its visual presentation or its HTML attributes.

The style Property – Direct Inline Changes

Every DOM element has a .style property that reflects its inline styles. You can read or set any CSS property, but the property names must be written in camelCase (not hyphenated):

CSS propertyJavaScript .style access
background-colorelement.style.backgroundColor
font-familyelement.style.fontFamily
font-sizeelement.style.fontSize
borderelement.style.border

Example – turn the navbar background blue:

const navBar = document.querySelector('nav');
navBar.style.backgroundColor = 'blue';

Values are always strings; include units where needed:

navBar.style.border = '2px solid black';

Limitation: .style only sees and modifies inline styles — it ignores styles from external or internal CSS sheets. If you try to read a property that comes from a stylesheet, you get null.

Why it’s problematic – Mixes presentation (CSS) with logic (JS), harder to maintain, and cannot read the full computed style of an element.


The classList API – The Right Way to Style

Instead of writing inline styles, define your styles in CSS classes and toggle them with JavaScript. The classList property gives you a DOMTokenList (array-like object) of all classes on an element.

Key methods:

MethodEffect
element.classList.add('class-name')Adds a class
element.classList.remove('class-name')Removes a class
element.classList.toggle('class-name')Adds if absent, removes if present
element.classList.contains('class-name')Returns true/false

Example workflow:

.sample {
  color: green;
  background-color: red;
  text-decoration: solid;
}
const section = document.querySelector('section');
section.classList.add('sample');       // applies the green/red style
section.classList.remove('sample');    // removes it
section.classList.toggle('sample');    // toggles
console.log(section.classList.contains('sample')); // false (after removal)

Exam tip: Always prefer classList over .style for production code. It keeps styles in CSS, makes debugging easier, and lets you reuse the same class across many elements.


Working with Other Attributes

Every HTML attribute (e.g., href, src, id, alt) can be read or changed using two generic methods:

  • element.getAttribute('attribute-name') – returns the current value.
  • element.setAttribute('attribute-name', 'new-value') – sets the value (overwrites existing).

Example – change the first link’s href:

const firstLink = document.querySelector('a');
console.log(firstLink.getAttribute('href'));   // e.g., "events.html"
firstLink.setAttribute('href', 'https://govind.com');
firstLink.setAttribute('id', 'new-id');         // also works for any attribute

Warning: Using setAttribute('style', ...) overwrites ALL inline styles – avoid it for styling. Use classList instead.


Text Content: innerText , textContent , innerHTML

Three properties control what text (and HTML) lives inside an element. They differ in what they read and how they treat markup.

PropertyWhat it returnsSecurity concernUse case
innerTextVisible text only (respects CSS display:none)SafeReading or setting plain visible text
textContentAll raw text, including hidden text and whitespaceSafeWhen you need the full raw string (e.g., for comparison)
innerHTMLText plus any nested HTML tags; parses them as elementsDangerous with user input (XSS)When you must insert structured HTML (only with trusted content)

Example – given a list item <li>Only one guest allowed <br> <img src="..."></li>:

const li = document.querySelector('li');
console.log(li.innerText);      // "Only one guest allowed" (no br, no image text)
console.log(li.textContent);    // "Only one guest allowed \n " (includes newline)
console.log(li.innerHTML);      // "Only one guest allowed <br> <img src="...">"

// Setting:
li.innerText = 'Any number of guests';   // Replaces everything (including br/img) with plain text
li.innerHTML = '<span>Hi</span>';        // Inserts a <span> element

Exam tip: Never use innerHTML with user-generated input (comments, search queries). Use innerText or textContent to avoid cross-site scripting (XSS) vulnerabilities.


Key takeaways – Styles & Attributes

  • .style gives access to inline styles only; property names use camelCase.
  • classList is the preferred way to style via JS – .add(), .remove(), .toggle(), .contains().
  • Use getAttribute() and setAttribute() for any HTML attribute except style.
  • setAttribute('style', ...) overrides all inline styles – avoid.

Key takeaways – Text Content

  • innerText – visible text only.
  • textContent – all raw text, including hidden.
  • innerHTML – parses HTML; only use with trusted content.
  • Setting any of these replaces all children of the element.

DOM Manipulation: Creating, Appending, Removing, and Inserting Elements

DOM manipulation lets you dynamically add, remove, or rearrange elements on a page. Instead of hard‑coding everything in HTML, you use JavaScript to modify the DOM tree at runtime – the engine behind interactive apps and single‑page interfaces.

Creating Elements

Before you can insert an element, you must create it. The method document.createElement(tagName) returns a new, empty DOM node of the given tag (e.g., 'p', 'div', 'span'). It exists only in memory until attached to the page.

Example

const newParagraph = document.createElement('p');
newParagraph.innerText = 'This P was added with JavaScript';

The element is now a node object with an innerText property, but it is not yet visible in the document.

Appending Elements

Once created, an element must be attached to a parent node. Two primary methods exist: appendChild() and the newer, more flexible append().

appendChild(parentNode, childNode)

  • Appends one child node to the end of the parent’s children list.
  • The child must be a node (e.g., a p element created with createElement).
  • Cannot insert text strings directly.
const section1 = document.querySelector('section');
section1.appendChild(newParagraph);

append(parentNode, ...nodesOrStrings)

  • Adds one or more children or strings to the end of the parent.
  • Strings are converted to text nodes automatically – they are not parsed as HTML.
  • More versatile than appendChild.
const newPara2 = document.createElement('p');
newPara2.innerText = 'Second dynamic paragraph';
section1.append(newPara2, 'Some random text', '<span>this is treated as text, not HTML</span>');
MethodAccepts multiple children?Accepts text strings?Returns
appendChildNo (one node at a time)NoThe appended child node
appendYesYes (as text)undefined

Removing Elements

Two ways to delete an element from the DOM: directly on the element itself, or via its parent.

remove() on the Target Element

Simply call element.remove(). No parent reference needed – the element is detached from the DOM.

const listItem1 = document.querySelector('li'); // first <li>
listItem1.remove(); // gone from the page

removeChild() on the Parent Element

Requires both the parent and the child node you want to remove.

const ul = document.querySelector('ul');
const firstChild = ul.firstElementChild;
ul.removeChild(firstChild);

Key difference: remove() is cleaner when you already have a reference to the element; removeChild() forces you to know the parent.

Inserting Elements at Specific Positions

Appending always puts a child at the end. To control exactly where an element appears, use insertBefore() or insertAdjacentElement().

insertBefore(parentNode, newNode, referenceNode)

  • Inserts newNode before referenceNode (which must be a child of the parent).
  • referenceNode is the sibling before which the new node goes.
const ul = document.querySelector('ul');
const listItem2 = ul.children[1]; // second <li>
const newP = document.createElement('p');
newP.innerText = 'Inserted before second list item';
ul.insertBefore(newP, listItem2);

insertAdjacentElement(position, targetElement, newElement)

  • Inserts newElement at a position relative to targetElement – no parent required.
  • Four position strings (case‑sensitive):
PositionMeaning
'beforebegin'Before the target element itself (outside)
'afterbegin'Inside the target, before its first child
'beforeend'Inside the target, after its last child
'afterend'After the target element itself (outside)
flowchart LR
    subgraph "targetElement"
        direction TB
        A1["afterbegin (inside, before first child)"]
        A2["content"]
        A3["beforeend (inside, after last child)"]
    end
    B["beforebegin (outside, before target)"]
    C["afterend (outside, after target)"]

Example – inserting before and inside:

const li1 = document.querySelector('#adjacent li:first-child');
const pBefore = document.createElement('p');
pBefore.innerText = 'Added beforebegin';
li1.insertAdjacentElement('beforebegin', pBefore);

const li2 = document.querySelector('#adjacent li:nth-child(2)');
const pAfterBegin = document.createElement('p');
pAfterBegin.innerText = 'Added afterbegin';
li2.insertAdjacentElement('afterbegin', pAfterBegin);

Comparison of insertion methods:

MethodUses parent?PositionsCan insert multiple nodes?
append / appendChildYesOnly end of childrenOnly append can do multiple
insertBeforeYesBefore a specified childNo
insertAdjacentElementNo (relative to an element)Four exact positionsNo (but call repeatedly)

Exam tip: insertAdjacentElement is the most flexible for precise positioning. Remember the four position strings – they are often tested. Note that 'beforeend' is inside the element at the end, while 'beforebegin' is outside before it.

Key Takeaways

  • Use document.createElement(tagName) to create a new element in memory.
  • appendChild() appends a single node to a parent; append() can add multiple nodes and text strings.
  • element.remove() deletes the element directly; parent.removeChild(child) needs both references.
  • insertBefore(parent, new, ref) places a node before a sibling child.
  • insertAdjacentElement(position, target, new) gives four precise placement options relative to the target element.
  • Always ensure the target elements exist in the DOM before manipulating them – check for null if using querySelector.

Event Listeners

Events are signals sent by the browser to JavaScript that something has happened – a user clicked, typed, hovered, or a page finished loading. They are the core mechanism behind interactivity: without events, a webpage is static; with events, JavaScript can react and update the DOM.

How the browser handles events (the flow)

  1. User triggers an action – e.g., clicks a button, presses a key, scrolls.
  2. Browser detects the action – creates an event and fires it on the target element.
  3. JavaScript responds – runs code attached to that event (the listener).

Intuition: Think of events as “when something happens, do something else.” The browser shouts “Hey, button clicked!”, and your JavaScript wakes up and runs the code you wrote for that moment.

Three ways to attach event handlers

MethodExampleProfile
Inline HTML (old, messy)<button onclick="alert('Clicked!')">Hard to maintain, mixes HTML & JS, avoid
DOM property (better, still not ideal)button.onclick = function() { … }Only one handler per event type; overwrites previous
addEventListener (gold standard)button.addEventListener('click', handler)Multiple handlers per event, clean separation, modern

Exam tip: Interviewers love to ask why addEventListener is preferred over the other two. Always mention: it allows multiple listeners, works with all event types uniformly, and doesn’t override existing handlers.

Inline example (don’t use)

<button onclick="alert('I was clicked')">Click me</button>

Property example (not recommended)

const button = document.querySelector('button');
button.onclick = function() {
  alert('I was clicked');
};

This works, but if you later assign another onclick, it replaces the first.

addEventListener – the modern way

Syntax:

element.addEventListener(type, listener);
  • type – a string naming the event (e.g. 'click', 'mouseover', 'keydown').
  • listener – a callback function that runs when the event occurs. This function automatically receives an event object as its first argument.

Worked example (background colour change)

Given a <button> in the HTML:

<button type="button">Change background</button>

Step 1 – Define the handler function (using classList is best practice):

function changeBg() {
  document.body.classList.add('bg-blue');
}

With CSS:

.bg-blue { background-color: blue; }

Step 2 – Attach the listener:

const button = document.querySelector('button');
button.addEventListener('click', changeBg);

Now clicking the button applies the class.

Alternative – anonymous function (also works):

button.addEventListener('click', function() {
  document.body.style.backgroundColor = 'cyan';
});

Alternative – arrow function (modern):

button.addEventListener('click', () => {
  document.body.style.backgroundColor = 'cyan';
});

Exam tip: Named functions are more readable and reusable; anonymous functions are convenient for one-off logic. Arrow functions do not have their own this (important for certain contexts like object methods).

The Event Object

When the listener runs, JavaScript automatically passes an event object as the first argument to the callback. You can name it anything (common names: e, event, evt).

button.addEventListener('click', function(e) {
  console.log(e);           // entire event object (e.g., PointerEvent)
  console.log(e.target);    // the element that triggered the event
  console.log(e.currentTarget); // the element the listener is attached to
});
  • e.target – the element that was actually clicked (useful if you have nested elements).
  • e.currentTarget – the element the listener is attached to (often the same, but differs with event delegation).

Common event types (selected)

CategoryEventsWhen fired
Mouseclick, dblclick, mouseover, mouseout, mousedown, mouseup, contextmenu (right-click)Cursor interactions
Keyboardkeydown, keyup, keypress (deprecated)Key presses
Formsubmit, change, input, focus, blurForm field interactions
Document / WindowDOMContentLoaded, load, scroll, resizePage lifecycle
Touchtouchstart, touchend, touchmoveTouchscreen devices

A full reference is maintained on MDN: Event reference.

Exam tip: For mouse events, remember click = mousedown + mouseup on the same element. For keyboard events, keydown fires repeatedly while holding a key; keyup fires once on release.

Key takeaways

  • An event is a signal that something happened; event listeners let JavaScript react.
  • Three attachment methods exist; addEventListener is the gold standard.
  • addEventListener(type, listener)type is a string, listener is a callback.
  • The callback receives an event object providing details (e.g., e.target).
  • Named functions, anonymous functions, and arrow functions all work as listeners.
  • Always separate JS from HTML; never use inline onclick attributes in production.

Painting Website

This project ties together HTML, CSS, and JavaScript (DOM manipulation, events, loops) to build an interactive painting canvas. The goal: hover over a grid of pixel‑divs and color them, but only while holding the Alt key — simulating a brush. The project also demonstrates event delegation for performance when handling thousands of child elements.

1. HTML Structure

Minimal markup: a color input, a paragraph of instructions, and a container <div> that will hold the pixel grid. All pixels are created dynamically with JavaScript.

<h1>Painting Canvas</h1>
<label for="color">Select Color</label>
<input type="color" id="color" value="#000000">
<p>Press Alt + move over canvas to paint</p>
<div class="container"></div>

2. CSS Grid Canvas

The container is turned into a responsive grid. Each grid cell is a “pixel” — a <div> with class .pixel. The grid uses 1fr columns so the canvas scales.

.container {
  border: 2px solid black;
  display: grid;
  grid-template-columns: repeat(150, 1fr);
  width: 75vw;
  height: 60vh;
}

Why 150 columns? Creates small square cells. With 5000 total pixels, we get about 30 rows.

3. JavaScript: Creating Pixels Dynamically

A loop generates 5000 <div> elements, each with a unique id and class pixel. They are appended to the container.

const canvas = document.querySelector('.container');
for (let i = 0; i < 5000; i++) {
  const pixel = document.createElement('div');
  pixel.setAttribute('id', i + 1);
  pixel.setAttribute('class', 'pixel');
  canvas.appendChild(pixel);
}

4. Adding Event Listeners (Inefficient Approach)

The naive way: attach a mouseover listener to every pixel inside the loop. When the event fires, a function runs that:

  1. Checks if the Alt key was pressed (event.altKey).
  2. Reads the current value of the color input (document.querySelector('#color').value).
  3. Sets the background-color of the pixel that triggered the event (using event.currentTarget).
pixel.addEventListener('mouseover', function(e) {
  if (e.altKey) {
    const color = document.querySelector('#color').value;
    e.currentTarget.style.backgroundColor = color;
  }
});

Why e.currentTarget? It refers to the element on which the listener was attached — in this case, the individual pixel. e.target would also work here because there’s no nesting inside the pixel.

5. The Better Way: Event Delegation

Attaching 5000 listeners is wasteful. Instead, use event bubbling — set a single listener on the parent container. Events that occur on any child pixel bubble up to the container. Then inside the handler, use e.target to identify the actual pixel that was hovered.

canvas.addEventListener('mouseover', function(e) {
  if (e.altKey && e.target.classList.contains('pixel')) {
    const color = document.querySelector('#color').value;
    e.target.style.backgroundColor = color;
  }
});

Event Bubbling vs. Capturing

flowchart LR
    A[Pixel clicked] --> B[Pixel event handler]
    B --> C[Container event handler]
    C --> D[Body event handler]
    style A fill:#ddd
    style B fill:#ddd
    style C fill:#9cf
    style D fill:#9cf
  • Events bubble from the target element up through its ancestors.
  • e.target = the element that originally triggered the event (the pixel).
  • e.currentTarget = the element with the event listener (the container, in the delegation version).

Exam tip: Event delegation is the standard way to handle events on many dynamic children. It saves memory and works even for elements added after the listener is attached.

6. Conditional Painting (Alt Key)

Only color a pixel when the Alt key is held down. This prevents accidental scribbling. The property e.altKey is true if the Alt key was pressed when the event fired.

if (e.altKey) {
  // apply color
}

7. Worked Example (Step‑by‑Step Flow)

  1. User selects a color (e.g., green) from the <input type="color">.
  2. User holds the Alt key and moves the mouse over the canvas.
  3. A mouseover event fires on a pixel div.
  4. The event bubbles to the container, which has the listener.
  5. The handler checks: e.altKey === true and e.target is a .pixel.
  6. It reads document.querySelector('#color').value (which is "#00ff00" at that moment).
  7. It sets e.target.style.backgroundColor = "#00ff00".

8. Key Concepts Summarised

ConceptExplanation
Event object (e)Contains properties like target, currentTarget, altKey, button.
e.targetThe element on which the event originally occurred (the pixel).
e.currentTargetThe element on which the listener was attached (container in delegation).
Event bubblingDefault behaviour where an event propagates from child to parent elements.
Event delegationTechnique of listening on a parent for events that bubble from children, improving performance and allowing dynamic elements.

9. Connection to Previous Modules

  • HTML/CSS: Grid layout, selectors, styling.
  • Module 6 (JS Basics): variables, loops (for), functions, callback functions (used as event handlers).
  • Module 7: DOM selection (querySelector), element creation (createElement), attribute setting (setAttribute), appending children, modifying inline styles.

Key Takeaways

  • Use a <div> container with CSS grid to create a pixel canvas.
  • Generate grid cells dynamically with a loop to avoid hard‑coding HTML.
  • Apply color only when a modifier key (e.g., Alt) is held — check event.altKey.
  • Event delegation (listener on the parent) is far more efficient than attaching listeners to every child.
  • e.target (the originated element) vs e.currentTarget (the listener’s element) is a common exam distinction.
  • This project integrates loops, functions, DOM manipulation, and events — typical of interactive web pages.

Overview: The Typewriter Effect

The goal is to display sentences one by one, each typed out character by character, then erased character by character before the next sentence appears. A blinking cursor sits at the end of the typed text. The animation starts automatically when the page loads — no user interaction required.

The key insight: this is a continuous loop that must not block the browser. We achieve it by combining recursive functions (a function calling itself with a delay) and JavaScript’s asynchronous timing methods (setTimeout, setInterval).


The Building Blocks

ComponentHTML ElementPurposeCSS Class Used
Static prefix<span> (e.g. "IIMB")Always visible
Animated text<span id="animated">Holds the typed/erased string
Blinking cursor<span id="cursor">Vertical bar (``) that toggles visibility

Delay functions in JavaScript

  • setTimeout(fn, delay) – Executes fn once after delay milliseconds.
  • setInterval(fn, delay) – Executes fn repeatedly every delay milliseconds.

Both accept a callback function as an argument. They do not block the main thread — they run asynchronously. Without this, an infinite loop would freeze the page.


Step-by-step Construction

1. Blinking Cursor with setInterval

const cursor = document.querySelector('#cursor');

function toggleCursor() {
  cursor.classList.toggle('hidden');   // toggles display: none
}

setInterval(toggleCursor, 500);        // blink every 0.5s
  • The .hidden class sets display: none.
  • setInterval keeps calling toggleCursor → cursor appears and disappears.

2. Wait for DOM to be ready

document.addEventListener('DOMContentLoaded', startAnimation);
  • The event DOMContentLoaded fires when the HTML is fully parsed.
  • Only then do we start the animation (calling startAnimation, which triggers both cursor blinking and the typewriter).

3. Typewriter Logic: Recursion with setTimeout

The problem: a regular for loop would print all characters instantly — no delay.
Solution: use a recursive function that calls itself via setTimeout.

Data

  • sentences = ["Lay the foundation to web development.", "The best institute in the world.", "Learn to live your life happily and keep being curious."]
  • sentenceCounter (0..2 → cycles with modulo)
  • charCounter (0..length-1)

State diagram (conceptual)

flowchart TD
  A[Add characters] --> B{charCounter < sentence.length?}
  B -- Yes --> C[Append next character to animated span]
  C --> D[Increment charCounter]
  D --> E[setTimeout A, 100ms]
  B -- No --> F[Pause 2s, then call Remove characters]
  F --> G[Remove characters]
  G --> H{charCounter > 0?}
  H -- Yes --> I[Slice off last character]
  I --> J[Decrement charCounter]
  J --> K[setTimeout G, 20ms]
  H -- No --> L[Reset charCounter = 0, increment sentenceCounter]
  L --> M[setTimeout A, 100ms]
  M --> A

Key implementation details

  • Printing: animatedSpan.textContent += sentence[sentenceCounter][charCounter]
  • Erasing: animatedSpan.textContent = animatedSpan.textContent.slice(0, -1)
  • textContent (not innerText) preserves spaces correctly.
  • Use setTimeout inside the recursive call — never setInterval for one-shot steps. The lecture initially used setInterval by mistake, causing infinite rapid re‑calls.

4. Achieving the infinite loop with modulo

When a sentence is fully erased, we need to move to the next sentence:

sentenceCounter = (sentenceCounter + 1) % sentences.length;
  • % (modulo) keeps the counter within 0..2, wrapping back to 0 after the last sentence.

Worked example: First iteration

Initial state: sentenceCounter = 0, charCounter = 0, sentences[0] = "Lay..."

  1. addCharacters runs:

    • charCounter (0) < "Lay...".length → true
    • Append sentences[0][0]"L"
    • charCounter++ → 1
    • setTimeout(addCharacters, 100)
  2. After 100ms:

    • Append "a""La"
    • charCounter = 2
    • setTimeout(addCharacters, 100)

… continues until charCounter reaches 37 (length of first sentence).

  1. Then: charCounter >= length

    • setTimeout(removeCharacters, 2000) → pause 2 seconds
  2. removeCharacters:

    • charCounter = 37 > 0
    • Slice off last char → "Lay ... developmen"
    • charCounter-- → 36
    • setTimeout(removeCharacters, 20)

… fast removal at 20ms per character until charCounter = 0.

  1. When charCounter = 0:
    • sentenceCounter = (0 + 1) % 3 = 1 → next sentence
    • charCounter = 0
    • setTimeout(addCharacters, 100)

The cycle repeats forever.


Asynchronous behaviour

  • setTimeout and setInterval are non‑blocking. The JavaScript event loop schedules them; the main thread continues running other code (e.g. user clicks).
  • Without asynchronous delay, an infinite loop would freeze the browser tab.

Exam tip: The difference between setTimeout (one‑shot) and setInterval (repeated) is a common trick question. In recursive animation we use setTimeout inside the function to create a controlled delay between steps. Confusing them leads to bugs like the “super fast” loop demonstrated in the lecture.


Connecting the pieces

The final animation runs two independent async loops:

  1. Cursor blinksetInterval, simple toggle every 500ms.
  2. Typewriter – recursive setTimeout chain for add/erase, with state updated via counters and modulo.

Both are started synchronously inside startAnimation(), triggered by DOMContentLoaded.


Key takeaways

  • Typewriter animations are built character‑by‑character using recursive setTimeout, not synchronous loops.
  • setInterval is appropriate for repeated actions (blinking); setTimeout for one‑shot delays inside recursion.
  • Modulo arithmetic (%) elegantly cycles through an array without extra checks.
  • textContent correctly handles whitespace; innerText sometimes omits it.
  • Asynchronous timing keeps the page responsive — the animation does not block user interactions.
  • Professional result achieved with just a few concepts: DOM selection, class toggle, string slicing, counters, and delay functions.
Study this interactively — ask questions and quiz yourself — in the study app, or see how it connects across the degree in the concept map.