Introduction to CSS
What is CSS?
CSS (Cascading Style Sheets) is the language that controls how HTML looks. Without CSS, every webpage would look like a plain text document from 1993. CSS controls colours, fonts, spacing, layout, animations — everything visual about a webpage.
CSS works by selecting HTML elements and then applying declarations (property-value pairs) to them. The word "Cascading" refers to how conflicting styles are resolved — more on that in the specificity section.
3 Ways to Add CSS
There are three places you can write CSS. Always prefer external stylesheets for real projects — they keep your HTML clean and let you reuse styles across multiple pages.
<!-- ❌ Method 1: Inline CSS (avoid — hardest to maintain) --> <h1 style="color: blue; font-size: 2rem;">Inline</h1> <!-- ⚠️ Method 2: Internal (style tag in head — single page only) --> <head> <style> h1 { color: blue; } p { font-size: 1.1rem; } </style> </head> <!-- ✅ Method 3: External stylesheet (best — use always) --> <head> <link rel="stylesheet" href="style.css"> </head> /* style.css */ h1 { color: blue; font-size: 2rem; } p { font-size: 1.1rem; line-height: 1.6; }
CSS Selectors
Selectors are patterns that match HTML elements. The more specific your selector, the more targeted its styles. Here are all the essential selector types:
/* === BASIC SELECTORS === */ /* Type selector — all <p> elements */ p { color: #333; } /* Class selector — elements with class="btn" */ .btn { background: blue; color: white; } /* ID selector — element with id="hero" (unique per page) */ #hero { font-size: 3rem; } /* Universal selector — every element */ * { box-sizing: border-box; } /* Attribute selector */ input[type="email"] { border-color: blue; } a[target="_blank"] { color: orange; } /* === COMBINATORS === */ /* Descendant: all <p> inside <article> */ article p { font-size: 1.05rem; } /* Child (direct only): <li> that are direct children of <ul> */ ul > li { list-style: none; } /* Adjacent sibling: <p> immediately after <h2> */ h2 + p { font-size: 1.2rem; font-weight: 600; } /* General sibling: all <p> after any <h2> */ h2 ~ p { color: gray; } /* === PSEUDO-CLASSES === */ /* User interaction states */ a:hover { color: orange; text-decoration: underline; } a:visited { color: purple; } button:focus { outline: 2px solid blue; } input:focus { border-color: blue; } /* Structural */ li:first-child { font-weight: bold; } li:last-child { border-bottom: none; } li:nth-child(2n) { background: #f5f5f5; } /* even rows */ li:nth-child(odd){ background: white; } /* Form state */ input:required { border-left: 3px solid red; } input:valid { border-color: green; } input:disabled { opacity: 0.5; } /* === PSEUDO-ELEMENTS === */ /* ::before and ::after add content via CSS */ .btn::before { content: "→ "; /* content property REQUIRED */ } p::first-line { font-weight: bold; } p::first-letter{ font-size: 2em; float: left; } ::selection { background: blue; color: white; } /* === GROUPING === */ /* Apply same styles to multiple selectors */ h1, h2, h3, h4 { font-family: 'Syne', sans-serif; font-weight: 800; }
The Cascade & Specificity
When two CSS rules target the same element and set the same property, the browser must decide which one wins. This is determined by specificity — a score calculated from the selector type. Higher specificity wins. If specificity is equal, the last rule in the file wins.
/* Which color wins for <p id="intro" class="lead">? */ p { color: black; } /* specificity: 0,0,0,1 = 1 */ .lead { color: blue; } /* specificity: 0,0,1,0 = 10 */ #intro { color: green; } /* specificity: 0,1,0,0 = 100 ← WINS */ /* Compound selectors: scores add up */ article .lead { color: purple; } /* 0,0,1,1 = 11 */ .card .lead { color: red; } /* 0,0,2,0 = 20 ← higher than article .lead */ /* !important overrides everything (avoid — breaks cascade) */ p { color: orange !important; } /* wins over everything above */ /* Inheritance — some properties pass to children */ body { font-family: 'DM Sans', sans-serif; /* inherits to ALL descendants */ color: #333; /* inherits to all text */ background: white; /* does NOT inherit */ } /* border, margin, padding, width — do NOT inherit */ /* color, font-*, line-height, list-style — DO inherit */
!important in real projects!important overrides ALL specificity — even inline styles. It looks like a quick fix but creates an arms race where everything needs !important to override anything else. Fix the underlying specificity issue instead. The only legitimate uses are in utility classes or third-party overrides where you genuinely have no other option.Essential CSS Properties
Before the box model and layout, here are the most fundamental visual properties — colours, typography, and backgrounds:
/* === COLOUR === */ p { color: #333333; /* hex */ color: rgb(51, 51, 51); /* rgb */ color: rgba(0, 0, 0, 0.8); /* rgba with opacity */ color: hsl(0, 0%, 20%); /* hue, saturation, lightness */ color: oklch(40% .02 240); /* modern CSS oklch */ } /* === TYPOGRAPHY === */ body { font-family: 'DM Sans', Arial, sans-serif; /* stack with fallbacks */ font-size: 16px; /* base size — use rem for everything else */ font-weight: 400; /* 100–900, or bold/normal */ font-style: normal; /* or italic */ line-height: 1.6; /* unitless recommended: 1.4–1.8 */ letter-spacing: 0.02em; /* em relative to font size */ text-align: left; /* center, right, justify */ text-transform: none; /* uppercase, lowercase, capitalize */ text-decoration: none; /* underline, line-through */ } /* === SIZING UNITS === */ h1 { font-size: 2rem; } /* rem = relative to root (html) font-size */ .lead { font-size: 1.2em; } /* em = relative to parent font-size */ .hero { width: 100%; } /* % = relative to parent width */ .full { height: 100vh; } /* vh = viewport height, vw = viewport width */ /* === BACKGROUND === */ .hero { background-color: #05091a; background-image: url('hero.jpg'); background-size: cover; /* cover | contain | auto */ background-position: center; background-repeat: no-repeat; /* shorthand: */ background: url('hero.jpg') center/cover no-repeat #05091a; } /* Gradient backgrounds */ .gradient-box { background: linear-gradient(135deg, #f97316, #fbbf24); background: radial-gradient(circle, #4f9eff, #05091a); }
rem for font sizes, not pxpx is absolute — if a user sets their browser default font to 20px (for accessibility), px ignores it. rem is relative to the browser's root font size (typically 16px) — so 1rem = 16px, 1.5rem = 24px. This respects user preferences and improves accessibility..card h2?em and rem?h2 + p target?style.css and link it to your portfolio.html from Phase 1. Style it with:1.
* selector: box-sizing: border-box; margin: 0; padding: 02.
body: a dark background (#05091a), light text colour, font-family: sans-serif, line-height: 1.63.
header: a different background, padding, and a bottom border4.
nav a: remove underline, add colour, hover state changes colour5.
h1, h2, h3: grouped selector, set font-weight and colour6.
section: padding, max-width, margin auto to centre7.
ul li: remove default list-style, add custom bullet with li::before8.
footer: centred text, smaller font, top border
💡 Show hints
- Custom bullet:
li::before { content: "→ "; color: orange; } - Centre sections:
section { max-width: 800px; margin: 0 auto; padding: 2rem; } - Remove underlines:
a { text-decoration: none; } - Hover:
nav a:hover { color: orange; }
/* === RESET === */ * { box-sizing: border-box; margin: 0; padding: 0; } /* === BASE === */ body { background-color: #05091a; color: #eef3ff; font-family: 'DM Sans', sans-serif; font-size: 16px; line-height: 1.7; } /* === TYPOGRAPHY === */ h1, h2, h3 { font-weight: 800; color: #ffffff; line-height: 1.2; } h1 { font-size: 2.5rem; margin-bottom: 0.5rem; } h2 { font-size: 1.8rem; margin-bottom: 1rem; color: #4f9eff; } /* === HEADER === */ header { background-color: #0a1230; padding: 1.5rem 2rem; border-bottom: 1px solid rgba(255,255,255,.1); position: sticky; top: 0; } /* === NAVIGATION === */ nav a { text-decoration: none; color: #8ca8d8; margin-right: 1.5rem; font-weight: 600; transition: color 0.2s; } nav a:hover { color: #f97316; } /* === SECTIONS === */ section { max-width: 800px; margin: 0 auto; padding: 3rem 2rem; border-bottom: 1px solid rgba(255,255,255,.06); } /* === LISTS — custom bullets === */ ul { list-style: none; } ul li { padding: 0.4rem 0; color: #8ca8d8; } ul li::before { content: "→ "; color: #f97316; font-weight: bold; } /* === LINKS === */ a { color: #4f9eff; text-decoration: none; } a:hover { color: #f97316; text-decoration: underline; } /* === FOOTER === */ footer { text-align: center; padding: 2rem; border-top: 1px solid rgba(255,255,255,.08); color: #4a68a0; font-size: 0.85rem; }