MAD Study Hub

Home / MAD1 / Week 2

Week 2 · HTML and CSS: building and styling pages

Official syllabus line: Webpages written in HTML and CSS
About 95 minQuiz 1 material (see exam radar)BSCS2003 (+ project BSCS2003P) · Thejesh G N, Nitin Chandrachoodan
Before you start: MAD1 week 1 (what a browser and a server do, what a URL is).

The one-minute story

Think of it like this

A web page is a house. HTML is the bricks and rooms: it says "this is a heading, this is a list, this is a door (link), this is a picture". CSS is the paint, furniture and layout: "make the walls blue, put the sofa on the left". Later, JavaScript is the electricity: lights that switch on when you press a button.

Keep the jobs apart. HTML says what something is. CSS says how it looks. If you paint with bricks (styling inside the HTML) you will suffer when you want to repaint the whole house.

Bootstrap is a ready-made furnished interior: you pick "blue button" and "three equal columns" from a catalogue instead of painting every wall yourself.

By the end of this week you can:

  • write a complete HTML page with headings, lists, links, images, tables and forms;
  • tell block elements from inline elements and use semantic tags;
  • write CSS with the right selector and predict which rule wins (specificity, order);
  • calculate the size of a box (content, padding, border, margin);
  • build a simple layout with display: flex;
  • use Bootstrap through its CDN link, with grid and utility classes.

Words you need

Words you need
  • HTML - HyperText Markup Language: tags that describe the structure of a page.
  • Element - an opening tag, content and a closing tag, such as <p>Hello</p>.
  • Attribute - extra information inside the opening tag, such as href="a.html".
  • CSS - Cascading Style Sheets: rules that style elements.
  • Selector - the part of a CSS rule that picks which elements to style.
  • Declaration - one property: value; pair.
  • Specificity - the score that decides which of two clashing rules wins.
  • Box model - every element is a box: content, padding, border, margin.
  • Block / inline - elements that start on a new line and take the full width / elements that sit inside a line of text.
  • Semantic tag - a tag whose name says its meaning (nav, footer) rather than just its looks.
  • Pseudo-class / pseudo-element - a selector for a state (:hover) / for a part of an element (::before).
  • Flexbox - a CSS layout mode that arranges children in a row or column.
  • Bootstrap - a CSS (and JS) library of ready-made classes and components.
  • CDN - a public server that hosts libraries so you can link them by URL.

Idea 1: Creating and serving an HTML document

An HTML file is plain text. Save this as index.html in a new folder:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>My first page</title>
</head>
<body>
  <h1>Hello, web</h1>
  <p>This is my first page.</p>
</body>
</html>

Open a terminal in that folder and serve it:

python -m http.server 8000

Visit http://localhost:8000/. The server sends index.html for /. You can also just double-click the file, but then the address starts with file:// and no server is involved.

PartWhat it does
<!DOCTYPE html>Tells the browser "this is modern HTML"
<html lang="en">The root of everything; lang helps screen readers
<head>Information about the page (not shown): title, character set, links to CSS
<title>The text on the browser tab
<body>Everything you see on the page
The idea

The three languages of the front end. HTML defines the content and structure, CSS defines the styling, JavaScript adds behaviour. JavaScript is an add-on for extra features, not a required part of every page. A page may load a script from a file like this:

<script src="app.js"></script>

Scripts are linked with src, stylesheets with <link rel="stylesheet" href="...">, images with <img src="...">, and page links with <a href="...">.

Elements can be nested (a list inside a body) but must close in reverse order: <p><b>Hi</b></p>, never <p><b>Hi</p></b>. Some tags have no content and no closing tag (void elements): <br>, <hr>, <img>, <input>, <meta>, <link>.

<h1>Main title</h1>            <!-- h1 to h6, h1 is biggest -->
<h2>Section</h2>
<p>A paragraph with <b>bold</b>, <i>italic</i> and <br> a line break.</p>
<hr>                           <!-- a horizontal line -->

<ul>                           <!-- unordered: bullets, order does not matter -->
  <li>Rice</li>
  <li>Dal</li>
</ul>
<ol>                           <!-- ordered: numbers, order matters -->
  <li>Wash</li>
  <li>Boil</li>
</ol>

<a href="https://example.com">An external link</a>
<a href="page2.html">A link to another file</a>
<a href="#reviews">Jump to the element with id reviews</a>

<img src="cat.png" alt="A sleeping cat" width="200">
  • Lists. ul has bullets, ol has numbers, and both hold li items. A recipe needs ul for ingredients (order irrelevant) and ol for the steps (order matters). This exact choice appeared in a past paper.
  • Links. The href value can be a full URL, a relative file path, or #id to jump inside the page (that is the fragment from week 1).
  • Images. src is the file, alt is the text for screen readers and for when the image fails to load.

Tables

<table border="1">
  <thead>
    <tr><th>Course</th><th>Credits</th></tr>
  </thead>
  <tbody>
    <tr><td>MAD1</td><td>4</td></tr>
    <tr><td>DBMS</td><td>4</td></tr>
  </tbody>
</table>

tr is a row, th a header cell, td a data cell. A cell can span several columns with colspan="2" or rows with rowspan="2".

Block and inline elements

BlockInline
Starts a new line?YesNo
WidthFull line by defaultOnly as wide as its content
Can you set width/height?YesNo
Examplesdiv, p, h1-h6, ul, li, table, formspan, a, b, i, img, input, button

Use div (block) and span (inline) as neutral containers that carry no meaning of their own.

Semantic tags

header, nav, main, section, article, aside, footer. They look like plain boxes but say what the content is, which helps search engines, screen readers, and your own reading.

<body>
  <header><h1>Study Hub</h1></header>
  <nav><a href="/">Home</a> <a href="/about">About</a></nav>
  <main>
    <article><h2>Post</h2><p>Text...</p></article>
  </main>
  <footer>Copyright 2026</footer>
</body>
Your turn: 1. Build a page

Write a body that shows a heading "Menu", an unordered list of two dishes, and a link "Home" that goes to index.html.

Need a hint?

Use h1, ul with li, and a href.

Show the full solution
<h1>Menu</h1>
<ul>
  <li>Idli</li>
  <li>Dosa</li>
</ul>
<a href="index.html">Home</a>

Idea 3: Forms and input types

A form is how a browser sends data to the server. The action is the URL to send to, and method is GET or POST (week 1).

<form action="/signup" method="post">
  <label for="u">Name</label>
  <input type="text" id="u" name="uname" required>

  <input type="email" name="mail" placeholder="you@example.com">
  <input type="password" name="pwd" minlength="6">
  <input type="number" name="age" min="5" max="99">
  <input type="date" name="dob">

  <input type="radio" name="level" value="fd"> Foundation
  <input type="radio" name="level" value="dip"> Diploma
  <input type="checkbox" name="agree" value="yes"> I agree

  <select name="city">
    <option value="che">Chennai</option>
    <option value="blr">Bengaluru</option>
  </select>

  <textarea name="note" rows="3"></textarea>
  <button type="submit">Send</button>
</form>
Input typeGives you
text, passwordOne line of text (password shows dots)
email, url, number, dateThe same, plus built-in checks and a suitable keyboard
radioPick one in a group (same name)
checkboxTick any number
submit / button type="submit"Sends the form
hiddenA value sent without being shown
fileUpload a file (needs enctype="multipart/form-data")
The idea

The name attribute is the key the server receives. Browsers send name=value pairs. An input with no name is not sent at all. The id is for CSS, JavaScript and <label for="...">; it is never what the server sees. In week 3 you read the values with request.form["uname"] (POST body) or request.args["uname"] (GET query string).

HTML5 validation. Attributes such as required, type="email", min, max, minlength and pattern make the browser check the data before sending. This is client-side validation. It improves the experience but a user (or a script) can bypass it, so the server must validate again (week 3).

:valid / :invalid in CSS. A field with required and no text is invalid, so a rule like input:valid { border: 2px solid red; } does not colour an empty required field, and does colour a correctly filled one. Past papers have asked this.

Watch out - real exam trap
  • No name means the value is never sent.
  • Radio buttons are grouped by the same name; different names make independent groups.
  • A form with method="get" puts values in the URL; the default method is GET.
  • Client-side validation can be bypassed, so it never replaces server-side checks.

Idea 4: Adding CSS: inline, internal, external

A CSS rule has a selector and declarations:

p {
  color: darkblue;
  font-size: 18px;
}

Three ways to attach CSS:

<!-- 1. Inline: on one element -->
<p style="color: red;">Red text</p>

<!-- 2. Internal: a style tag in head -->
<style>
  p { color: blue; }
</style>

<!-- 3. External: a separate file, linked in head (best for real projects) -->
<link rel="stylesheet" href="style.css">

External CSS is shared by many pages and is cached by the browser. In Flask the file lives in the static folder and is linked with url_for('static', filename='style.css') (week 3).

The cascade: who wins?

When several rules target one element, the browser decides in this order:

  1. !important beats everything else (use rarely).
  2. Higher specificity wins.
  3. If specificity ties, the rule that comes later wins.
  4. Some properties (colour, font) are inherited from the parent when no rule applies.

Specificity score, compare the columns from left to right:

Selector kindWeightExample
Inline style1000style="..."
id100#main
class, attribute, pseudo-class10.note, [type="text"], :hover
type (tag), pseudo-element1p, ::before
Solved example: 1. Which colour?

Question. What colour is the text?

<style>
  p            { color: blue; }
  .note        { color: green; }
  #first       { color: red; }
  p.note       { color: orange; }
</style>
<p id="first" class="note">Hello</p>
<p class="note">World</p>

Solution. First paragraph: scores are 1, 10, 100, 11. The id rule is highest: red. Second paragraph has no id: p.note (11) beats .note (10) and p (1): orange. If we added style="color: black" to the first paragraph, it would become black (inline = 1000), unless a rule used !important.

Idea 5: Selectors, all kinds

h1 { }                    /* type: every h1 */
.note { }                 /* class: class="note" */
#main { }                 /* id: id="main" (unique) */
* { }                     /* universal: every element */
h1, h2 { }                /* group: either */

div p { }                 /* descendant: any p anywhere inside a div */
div > p { }               /* child: p directly inside a div */
h1 + p { }                /* adjacent sibling: the p right after an h1 */
h1 ~ p { }                /* general sibling: all later p siblings of an h1 */

a:hover { }               /* pseudo-class: mouse is over */
li:nth-child(2) { }       /* li that is the 2nd child of its parent */
li:nth-child(odd) { }     /* 1st, 3rd, 5th ... (even: 2nd, 4th ...) */
li:first-child { }
input:focus { }
input:valid { }

p::before { content: "Note: "; }   /* pseudo-element: injected text before */
p::first-line { }

input[type="text"] { }    /* attribute equals */
[class~="out"] { }        /* attribute contains the WORD "out" in a space-separated list */
a[href^="https"] { }      /* attribute starts with */
a[href$=".pdf"] { }       /* attribute ends with */
a[href*="example"] { }    /* attribute contains the text anywhere */
  • One colon : is a pseudo-class (a state), two colons :: is a pseudo-element (a part).
  • div p goes at any depth; div > p only one level down.
  • [class~=out] matches an element whose class list contains the word out. [id~=out] does the same for id, so it matches id="out".
Solved example: 2. Read the selector

Question. Which items turn red?

<style>
  ul > li:nth-child(even) { color: red; }
  li ~ li:last-child      { font-weight: bold; }
</style>
<ul>
  <li>A</li><li>B</li><li>C</li><li>D</li><li>E</li>
</ul>

Solution. nth-child(even) picks the 2nd and 4th: B and D are red. The second rule picks the last li that has an li sibling before it: E is bold. A, B, C and D are not bold.

Solved example: 3. Attribute selectors in a past-paper style

Question. With these two rules, what border does each paragraph get?

<style>
  [id~=out]    { border: 10px solid red; }
  [class~=out] { border: 5px solid yellow; }
</style>
<p id="out">One</p>
<p class="out">Two</p>
<p class="outer">Three</p>

Solution. One has the id, so it gets the red 10px border. Two has the class word out: yellow 5px border. Three has class outer, a different word, so it gets no border. The paragraph with the class does not get the id rule, and the headings get nothing.

Your turn: 2. Specificity race

div p {color: red}, .box p {color: blue}, p {color: green}. HTML: <div class="box"><p>Hi</p></div>. What colour?

Need a hint?

Count: div p = 1 + 1, .box p = 10 + 1, p = 1.

Show the full solution

Scores 2, 11 and 1. .box p wins: blue.

Idea 6: Box model, units and colours

Every element is a box made of four layers, from the inside out: content, padding (inside space), border, margin (outside space).

.card {
  width: 200px;
  padding: 20px;
  border: 5px solid black;
  margin: 10px;
}

With the default box-sizing: content-box, width is the content width:

  • Visible box width = 200 + 20 + 20 (padding) + 5 + 5 (border) = 250px.
  • Space taken in the row = 250 + 10 + 10 (margin) = 270px.

With box-sizing: border-box the 200px already includes padding and border: visible width 200px; content shrinks to 150px. Bootstrap sets border-box everywhere.

Shorthand: margin: 10px 20px; means top/bottom 10, left/right 20. Four values go clockwise: top, right, bottom, left.

UnitMeaning
pxA fixed pixel
%Percent of the parent
emTimes the current element's font size
remTimes the root (html) font size, usually 16px
vw, vh1 percent of the window width / height

Colours: names (red), hex (#ff0000, #f00), rgb(255, 0, 0), rgba(255, 0, 0, 0.5) (the last number is opacity) and hsl(0, 100%, 50%).

Display and position

  • display: block | inline | inline-block | none | flex. none removes the element entirely. (visibility: hidden hides it but keeps the space.)
  • position: static (default, normal flow), relative (shift from its normal place), absolute (placed against the nearest positioned ancestor), fixed (stays on the screen when scrolling), sticky (sticks after scrolling to a point). Offsets use top, left, right, bottom.

Flexbox basics

<style>
  .row { display: flex; justify-content: space-between; align-items: center; gap: 10px; }
  .row div { flex: 1; }
</style>
<div class="row">
  <div>One</div><div>Two</div><div>Three</div>
</div>

Setting display: flex on the parent makes the children flex items laid out in a row.

Property (on the parent)Effect
flex-direction (row or column)Main axis direction (row is the default)
justify-contentSpacing along the main axis: flex-start, center, space-between, space-around
align-itemsAlignment along the cross axis: stretch, center, flex-start
flex-wrap: wrapAllow items to go to the next line
gapSpace between items

On a child, flex: 1 makes children share the free space equally. Above, three equal columns.

Your turn: 3. Box size

div {width: 300px; padding: 10px; border: 2px solid; margin: 15px; box-sizing: border-box;}. What is the visible width, and what space does it take in a row?

Need a hint?

With border-box the width already includes padding and border.

Show the full solution

Visible width: 300px. Space in a row: 300 + 15 + 15 = 330px. (With content-box it would be 324px visible.)

Idea 7: Bootstrap

Bootstrap gives ready classes. No install is needed: link it from a CDN in the head (and, only if you use components such as dropdowns or modals, add the script before the closing body).

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Bootstrap demo</title>
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
  <div class="container">
    <h1 class="text-center mt-4">Courses</h1>
    <div class="row">
      <div class="col-12 col-md-6">
        <div class="alert alert-info">Left half on medium screens and up</div>
      </div>
      <div class="col-12 col-md-6">
        <button class="btn btn-primary">Enrol</button>
      </div>
    </div>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
  • Containers. container is centred with a maximum width; container-fluid spans the whole width.
  • Grid. A row holds 12 columns per line. col-md-6 means "take 6 of 12 columns (half) from the medium breakpoint upward; below that stack full width". Breakpoints: sm 576px, md 768px, lg 992px, xl 1200px. col-4 col-4 col-4 makes three equal columns.
  • Utilities. Small single-purpose classes: spacing m-3, mt-2, px-4, p-0 (scale 0 to 5, where 3 is 1rem), text text-center, fw-bold, colour text-danger, bg-light, display d-flex, d-none, justify-content-between, border, rounded.
  • Components. btn btn-primary, card, navbar, table table-striped, form-control, alert alert-success, list-group.
Watch out - real exam trap
  • Missing the viewport meta tag makes the responsive grid behave badly on phones.
  • Columns in a row should add up to 12; extras wrap to the next line.
  • col-md-6 does nothing below 768px: items stack. Large-to-small is mobile first.
  • Forgetting the CDN link means the classes do nothing and the page looks plain.
In your project

Use one static/style.css for your own styles and Bootstrap from a CDN for layout. In the viva be ready to show one container/row/col layout, explain col-md-6, and change a button colour or a column width live. Use a semantic structure (nav, main, footer) and alt text on images.

Exam radar

Exam radar

The graded questions that touch this week's keywords are about 215 of 692 in Quiz 1, 128 of 624 in Quiz 2 and 252 of 1600 in the End Term (a loose keyword match, since forms and templates are counted too). The questions that really test HTML and CSS are fewer and are very predictable:

  • Selectors and specificity: predict which paragraph gets which border or colour (attribute selectors such as [class~=out], :nth-child, descendant versus child).
  • Which tag? ul versus ol for a recipe; the right way to link a script (script with src) or a stylesheet.
  • Forms and validation: what required and :valid do; whether a form has client-side validation, server-side validation or both; the name attribute.
  • Statements: "HTML defines content, CSS defines styling" (true); "JavaScript is always the core part of the frontend" (false).
  • Small JavaScript: an onclick button or JSON.parse on a string and showing properties through innerHTML. Know only the basics: getElementById, innerHTML, alert.
  • Box model and Bootstrap grid questions appear less often but are easy marks.
Watch out - real exam trap
  • The class word match [class~=out] is not the same as [class*=out] (outer matches *= but not ~=).
  • More specific beats later: an id rule above beats a class rule below.
  • div > p is direct children only.
  • visibility: hidden keeps the space; display: none does not.
  • ol is numbered and ordered, ul has bullets.

Quick quiz

Quick quiz

A recipe page needs ingredients (order does not matter) and cooking steps (order matters). Which tags?

  • ol for ingredients, ul for steps
  • ol for both
  • ul for both
  • ul for ingredients, ol for steps
An unordered list for items with no order, an ordered list when the sequence matters.

A page has p {color: blue} in a style tag, .note {color: green}, and <p class="note" style="color: black">. The text colour is...

  • blue
  • green
  • black
  • red
Inline style has the highest specificity (1000) so it beats a class rule (10) and a type rule (1).

Which selector picks only li elements that are direct children of a ul?

  • ul li
  • ul > li
  • ul ~ li
  • ul + li
The > child combinator means direct child; a space means any depth.

Select all TRUE statements. (select all that apply)

  • HTML describes content and structure; CSS describes styling.
  • An input without a name is not submitted with its form.
  • JavaScript is always required for every web page.
  • :hover is a pseudo-element.
:hover has one colon so it is a pseudo-class; JavaScript is optional extra behaviour.

width: 200px; padding: 20px; border: 5px solid; margin: 10px; with content-box. What is the visible width of the box?

  • 200px
  • 220px
  • 250px
  • 270px
200 + (20 x 2) + (5 x 2) = 250px; 270px would include the 10px margins.

In Bootstrap, <div class="col-md-6"> means...

  • half the width at all screen sizes
  • half the row from the md breakpoint upward, full width below
  • 6 pixels wide
  • hide on medium screens
Six of twelve columns from 768px up; narrower screens stack the columns.

Viva: say it out loud

Viva: say it out loud
What is the difference between HTML, CSS and JavaScript?

HTML gives the structure and content, CSS gives the look and layout, JavaScript adds behaviour such as reacting to clicks. I keep them in separate files where I can.

How does the browser decide which CSS rule wins?

It checks for !important, then compares specificity (inline, then id, then class, then tag), and if the score ties the later rule wins. Some properties are also inherited from the parent.

What is the box model?

Every element is a box: content, then padding, then border, then margin. The visible width adds content, padding and border. border-box makes the width include padding and border.

Why do you use semantic tags and alt text?

Semantic tags such as nav and main tell browsers, search engines and screen readers what each part is. The alt text describes an image for people who cannot see it and shows when the image fails.

Explain client-side and server-side validation in your form.

The browser checks required, type="email" and similar attributes before submit, which is quick but can be bypassed. My Flask route validates again, because only the server can be trusted.

How did you do your layout?

I used Bootstrap from a CDN: a container, row, and col-md-* columns for the grid, plus utility classes for spacing. For small custom pieces I used flexbox with justify-content and align-items.

Where do your CSS files live in your Flask project?

In the static folder, linked in the template with url_for('static', filename='style.css').

Recap

Remember this
  • HTML skeleton: doctype, html, head (title, meta, links), body. Serve with python -m http.server.
  • Block elements start a new line; inline elements sit in a line. Use semantic tags.
  • Forms send name=value pairs; name matters, id does not. HTML5 validation is client-side only.
  • CSS comes inline, internal or external; the winner is decided by !important, specificity (id 100, class 10, tag 1, inline 1000), then order.
  • Selectors: type, class, id, descendant, >, +, ~, :hover, :nth-child, ::before, [attr] forms.
  • Box width = content + padding + border (+ margin for space). Flexbox: display: flex on the parent.
  • Bootstrap: CDN link, container, row, 12-column col-md-*, utility classes, components.
Code and facts to keep
  • Skeleton: <!DOCTYPE html><html><head><title></title></head><body></body></html>
  • Links: <link rel="stylesheet" href="s.css">, <script src="a.js"></script>, <a href="">, <img src="" alt="">
  • Specificity: inline 1000, #id 100, .class [attr] :pseudo-class 10, tag ::pseudo-element 1
  • Visible width (content-box) = width + 2 padding + 2 border; space = + 2 margin
  • Flex: display: flex; justify-content: ...; align-items: ...; gap: ...
  • Bootstrap 5 CSS: https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css
  • Breakpoints: sm 576, md 768, lg 992, xl 1200; grid = 12 columns
Connected weeks (learn them together)

Practise with real exam questions

These come straight from past papers (with the real figures and the official answer key). Open 60 real questions on this week   All Quiz 1 papers