FirstHack Learn
Log in Sign up free
Lessons in this course 0/6 All courses Web Development Basics

CSE

Progress0 / 6 lessons
  1. 1. How a web page reaches your screen
  2. 2. HTML structure and semantic tags
  3. 3. CSS: the box model, flexbox, and why layouts break
  4. 4. JavaScript: variables, functions and the DOM
  5. 5. Events and forms
  6. 6. fetch and working with JSON from an API

Courses › Web Development Basics

CSS: the box model, flexbox, and why layouts break

Every element is a box. Once you see the boxes, layout stops being guesswork.

12 min read · Lesson 3 of 6 · Free

One rule, three parts

A CSS rule has a selector, a property and a value.

Code
p {
  color: #333;
  font-size: 16px;
}

Put your CSS in a file called style.css and link it from the head:

Code
<link rel="stylesheet" href="style.css">

Common selectors:

  • p - every paragraph
  • .card - every element with class="card"
  • #contact - the one element with id="contact"
  • nav a - every link inside a nav

Use classes for styling. Use ids for linking and for JavaScript. An id must appear only once per page.

Every element is a box

This is the idea that fixes most layout confusion. Each element is a rectangle with four layers, from inside out:

  1. content - the text or image
  2. padding - space inside the box, gets the background colour
  3. border - the line around it
  4. margin - space outside the box, always transparent

Now the trap. By default, width sets the width of the content only.

Code
.card {
  width: 300px;
  padding: 20px;
  border: 2px solid #ccc;
}

That card is not 300px wide on screen. It is 300 + 20 + 20 + 2 + 2 = 344px. Put four of them in a 1200px row and they overflow. This one rule has broken more student layouts than any other.

The fix is one line at the top of every stylesheet:

Code
* {
  box-sizing: border-box;
}

Now width: 300px means the whole box is 300px, and padding and border eat into it from inside. Almost every real project uses this.

Margin collapse

Two vertical margins that touch do not add up. They merge, and the larger one wins.

Code
h2 { margin-bottom: 30px; }
p  { margin-top: 20px; }

The gap is 30px, not 50px. This happens only to top and bottom margins, never left and right, and never inside a flex container.

Flexbox

Before flexbox, people centred things with floats and hacks. Now one line turns an element into a row manager.

Code
.row {
  display: flex;
  gap: 16px;
}

Every direct child becomes a flex item sitting in a row. The useful properties on the container:

Property Does
flex-direction row (default) or column
justify-content spacing along the main axis
align-items alignment across the other axis
gap space between items
flex-wrap wrap lets items drop to a new line

A complete, working card row:

Code
* { box-sizing: border-box; margin: 0; }

body {
  font-family: system-ui, Arial, sans-serif;
  padding: 24px;
  background: #f7f7f8;
}

.row {
  display: flex;
  gap: 16px;
  flex-wrap: wrap;
}

.card {
  flex: 1 1 260px;
  padding: 20px;
  border: 1px solid #ddd;
  border-radius: 8px;
  background: #fff;
}

.card h3 { margin-bottom: 8px; }

flex: 1 1 260px reads as: grow if there is space, shrink if there is not, and aim for 260px. Cards share the row and wrap to the next line on a phone. That is responsive design with one property.

To centre anything, both ways:

Code
.centre {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
}

100vh means the full height of the viewport.

⚠️

justify-content and align-items swap meaning when you set flex-direction: column. In a column, justify-content controls vertical position and align-items controls horizontal. Students set the wrong one and think flexbox is broken. It is not; the axis moved.

Why layouts break

Three causes cover most cases:

  1. Box sizing, as above.
  2. A rule you wrote is being overridden. Specificity: an id beats a class,

a class beats a tag name. Two rules of equal weight? The later one wins.

  1. You styled a parent when you meant the child, or the other way round.
💡

Stop guessing. Right click the broken element, choose Inspect, and look at the Styles panel. Overridden rules appear with a line through them, and the box model diagram at the bottom shows the real pixel numbers. This is faster than adding !important and hoping.

Next: JavaScript, and how to change this page while it is running.