🚀 New batches open: Advanced Excel • Power BI • SQL • AI for Analytics — Book a free demo

Day 7 — CSS - making it look like something

HTML says what things are. CSS says what they look like. Today the pages stop looking like 1994.

A rule

selector {
  property: value;
  property: value;
}

The selector picks the elements. Everything in the braces is applied to them. Every declaration ends in a semicolon.

Three ways to attach CSS, one of which you should use

<style>
  p { color: #1D3B73; }
</style>

<p>Styled by the style block above.</p>
<p style="color: #9B1C1C">Styled inline, overriding it.</p>
WayLooks likeVerdict
External file<link rel="stylesheet" href="style.css">Use this. One file styles the whole site, and the browser caches it.
Style block<style> in the headFine for one page or a demo. Used throughout this tutorial.
Inlinestyle="..." on the tagLast resort. Cannot be reused, hard to override, clutters the markup.

The selectors you will actually use

<style>
  h2            { color: #0A1A3D; }        /* every h2 */
  .lead         { font-size: 18px; }       /* class="lead" */
  #intro        { background: #F6F8FC; }   /* id="intro"  */
  .card p       { color: #4A5A78; }        /* p inside .card */
  a:hover       { color: #9B1C1C; }        /* while hovered */
</style>

<h2>Heading</h2>
<p id="intro" class="lead">Big, on a tinted background.</p>
<div class="card">
  <p>Grey, because it is inside .card</p>
</div>
<p><a href="https://example.com">Hover me</a></p>
SelectorPicks
pEvery p on the page
.cardAnything with class="card"
#introThe one element with id="intro"
.card pEvery p anywhere inside .card
.card > pOnly p that is a direct child of .card
h2, h3Both h2 and h3
a:hovera while the mouse is over it
li:first-childThe first li in its parent
Classes for styling, ids for linking A class can go on as many elements as you like. An id must be unique, so styling with it does not scale - the moment you need a second one you have to rewrite the rule. Style with classes. Keep ids for anchors, and for labels pointing at inputs.

Colour

<style>
  .a { color: crimson; }
  .b { color: #0A1A3D; }
  .c { color: rgb(240, 180, 41); }
  .d { background: rgba(10, 26, 61, 0.08); padding: 8px; }
</style>

<p class="a">A colour name</p>
<p class="b">A hex code</p>
<p class="c">An rgb triple</p>
<p class="d">rgba, with the a for transparency</p>

Hex is what you will see most: #RRGGBB, two hex digits each for red, green and blue. #000 is black, #fff white.

Contrast is not a matter of taste Light grey text on white is unreadable for a lot of people and fails the WCAG accessibility standard, which asks for a contrast ratio of at least 4.5 to 1 for body text. Search "contrast checker", paste your two colours in. If a client insists on #999 on white, show them the number.

Type

<style>
  body {
    font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
    font-size: 16px;
    line-height: 1.6;
    color: #333;
  }
  h1 {
    font-size: 32px;
    font-weight: 800;
    letter-spacing: -0.5px;
    margin-bottom: 6px;
  }
  .muted { color: #667; font-size: 14px; }
</style>

<h1>Advanced Excel</h1>
<p class="muted">Six weeks &middot; weekday and weekend batches</p>
<p>Formulas, pivot tables and dashboards, taught on real reports
   rather than toy data.</p>
Two settings that do most of the work line-height: 1.6 - the single biggest readability win there is. Default line spacing is too tight for body text.
font-family with a fallback list - the browser tries each in turn. Always end with sans-serif or serif so there is a guaranteed last resort.

The cascade

When two rules fight, the more specific one wins. If they are equally specific, the one written later wins.

<style>
  p          { color: green; }
  .note      { color: blue; }
  #special   { color: purple; }
  p          { color: red; }
</style>

<p>Red - two plain p rules, the later one wins.</p>
<p class="note">Blue - a class beats a plain element.</p>
<p class="note" id="special">Purple - an id beats a class.</p>

Roughly: inline style beats id, id beats class, class beats element. Reorder the rules in the box and watch what does and does not change.

!important is a trap color: red !important; overrides everything, and the only way to beat it later is another !important. Two months on you have a stylesheet nobody can change. If you need it, your selectors are usually the real problem.

Inheritance

Some properties pass down to children on their own. Colour, font and line-height do. Borders, padding and margins do not.

<style>
  .box {
    color: #1D3B73;
    font-family: Georgia, serif;
    border: 2px solid #1D3B73;
    padding: 12px;
  }
</style>

<div class="box">
  <p>This paragraph inherited the colour and the font,
     but it did not inherit the border or the padding.</p>
</div>

That is why setting font-family once on body is enough for the entire page.

Try these yourself

  1. Style a page so headings are navy, body text is dark grey and line-height is 1.6.
  2. Give one paragraph a class and colour only that one.
  3. Write a rule that only affects paragraphs inside a .card.
  4. Make two rules fight, then work out which wins before running it.
  5. Explain why you should style with classes rather than ids.