DataLens

CSS basics: selectors and the box model

Write CSS rules with type, class, id, descendant and grouped selectors, and control every element's size and spacing with the box model, including padding, border, margin and box-sizing.

Level: Intermediate · 7 min read

Practise this module

The questions for this lesson run in your browser and check your answer straight away.

The idea

HTML says what things are; CSS (Cascading Style Sheets) says how they look. A stylesheet is a list of rules, and each rule says "for these elements, set these properties":

selector {
  property: value;
  another-property: value;
}

Two concepts carry almost everything else in CSS: selectors (which elements a rule applies to) and the box model (how every element's size and spacing is calculated).

Adding CSS to a page

CSS usually lives in a separate file linked from the <head> (<link rel="stylesheet" href="styles.css">). For small examples, a <style> element works the same way:

<style>
  h1 { color: #7a4b2a; }
  p { line-height: 1.6; }
</style>

<h1>Toko Kita</h1>
<p>Freshly roasted Indonesian coffee, delivered to your door.</p>

In the exercises, the style.css tab plays the role of the stylesheet file.

Selectors

The selector is how a rule says which elements it applies to. Sometimes you want every paragraph, sometimes only the price on a product card, sometimes only links while the mouse is over them. Here are the selectors you'll use day to day, each with a comment saying what it picks:

<style>
  p { color: #333; }                         /* type: every <p> */
  .price { font-weight: bold; }              /* class: every element with class="price" */
  #featured { background: #fff4e5; }        /* id: the one element with id="featured" */
  .card h3 { margin: 0; }                    /* descendant: <h3> anywhere inside .card */
  .card > p { color: #666; }                 /* child: <p> directly inside .card */
  h1, h2, h3 { font-family: Georgia, serif; } /* group: same rule for several selectors */
  a:hover { text-decoration: none; }         /* pseudo-class: a state */
</style>

<article class="card" id="featured">
  <h3>Arabica Gayo</h3>
  <p>Fruity and smooth.</p>
  <p class="price">Rp 95.000</p>
</article>

In practice, classes do most of the work: they're reusable, they describe a role (.card, .price, .button) and they're easy to override. Ids are unique per page and very "strong" in the cascade (module 7), so keep them for links and JavaScript, not styling.

The box model

Every element is a rectangular box made of four layers, from the inside out:

┌──────────────── margin (space outside, transparent) ────────────────┐
│  ┌───────────── border ───────────────────────────────────────────┐  │
│  │  ┌────────── padding (space inside, has the background) ────┐  │  │
│  │  │                                                          │  │  │
│  │  │                   content (width × height)               │  │  │
│  │  │                                                          │  │  │
│  │  └──────────────────────────────────────────────────────────┘  │  │
│  └────────────────────────────────────────────────────────────────┘  │
└──────────────────────────────────────────────────────────────────────┘
<style>
  .box {
    width: 200px;
    padding: 20px;
    border: 5px solid #7a4b2a;
    margin: 30px;
    background: #fff4e5;
  }
</style>

<div class="box">A box</div>

How wide is that box on screen? By default, width sets only the content, and padding and border are added on top: 200 + 20 + 20 + 5 + 5 = 250 px. Plus 30 px of margin on each side that pushes neighbours away.

box-sizing: border-box

Adding padding and making the box grow is rarely what you want. With box-sizing: border-box, width includes padding and border:

<style>
  *, *::before, *::after { box-sizing: border-box; }
  .box { width: 200px; padding: 20px; border: 5px solid #7a4b2a; background: #fff4e5; }
</style>

<div class="box">Exactly 200px wide, padding and border included</div>

Almost every modern stylesheet starts with that first line. Then width: 200px means 200 px on screen, and adding padding never breaks a layout.

Shorthands

Setting padding-top, padding-right, padding-bottom and padding-left one by one gets tedious. Most box properties have a shorthand that sets several sides in one line. The order to remember is clockwise from the top:

padding: 10px;               /* all four sides */
padding: 10px 20px;          /* top & bottom 10, left & right 20 */
padding: 10px 20px 30px 40px; /* top, right, bottom, left (clockwise) */
margin: 0 auto;              /* centre a block that has a width */
border: 1px solid #ddd;      /* width, style, colour */

Two things that surprise everyone once:

Key idea

A CSS rule is selector + declarations. Style mostly with classes. Every element is content + padding + border + margin; set box-sizing: border-box everywhere so width means the visible width.

Why this matters for clean code

Class-based selectors that describe roles (.card, .price) make CSS reusable and predictable, and a global border-box removes a whole category of layout arithmetic bugs. Clean CSS starts with the same habit as clean Python: name things by what they are, not by how they look (.price, not .bold-red-text).

Recap

Practise this module

The questions for this lesson run in your browser and check your answer straight away.

Next: Colors, fonts, and units →