CSS Fundamentals
Selectors, properties, and the cascade
What is CSS?
CSS (Cascading Style Sheets) is the language that brings visual life to your HTML. While HTML provides the structure and content of a web page, CSS controls every aspect of how that content looks—from colors and fonts to layouts and animations. Think of HTML as the skeleton and CSS as the skin, clothes, and makeup.
CSS works by targeting HTML elements and applying style rules to them. You can change colors, adjust spacing, create layouts, add animations, and make your site responsive to different screen sizes—all with CSS.
Adding CSS to HTML
There are three ways to add CSS to your HTML, each with its own use case:
✓ 1. External Stylesheet (Recommended)
Keep CSS in separate files for maintainability and reusability.
<!-- In your HTML head -->
<link rel="stylesheet" href="styles.css" />
2. Internal Styles (Use Sparingly)
Useful for page-specific styles or small projects.
<style>
p { color: blue; }
</style>
❌ 3. Inline Styles (Avoid)
Hard to maintain, not reusable, highest specificity.
<p style="color: blue;">Text</p>
CSS Selectors
Selectors are patterns that tell CSS which HTML elements to style. Understanding selectors is fundamental to writing efficient CSS.
Basic Selectors
/* Element selector - targets all elements of a type */
p {
color: blue;
}
/* Class selector - reusable, can apply to any element */
.highlight {
background: yellow;
}
/* ID selector - unique, should only appear once per page */
#header {
height: 60px;
}
/* Universal selector - targets everything */
* {
margin: 0;
padding: 0;
}
Combinators
/* Descendant selector - any level of nesting */
article p {
font-size: 16px;
}
/* Child selector - direct children only */
ul > li {
list-style: disc;
}
/* Adjacent sibling - immediately following */
h2 + p {
margin-top: 0;
}
/* General sibling - all following siblings */
h2 ~ p {
color: gray;
}
Attribute Selectors
/* Has attribute */
input[type] { }
/* Exact match */
input[type="email"] {
border: 1px solid blue;
}
/* Contains word */
a[title~="important"] { }
/* Starts with */
a[href^="https"] { }
/* Ends with */
a[href$=".pdf"] { }
/* Contains substring */
a[href*="example"] { }
Pseudo-classes
/* User interaction */
a:hover { color: red; }
input:focus { outline: 2px solid blue; }
button:active { transform: scale(0.95); }
/* Structural */
li:first-child { font-weight: bold; }
li:last-child { border-bottom: none; }
li:nth-child(odd) { background: #f5f5f5; }
li:nth-child(3n) { /* every 3rd */ }
/* State */
input:disabled { opacity: 0.5; }
input:checked { }
input:valid { border-color: green; }
input:invalid { border-color: red; }
Pseudo-elements
/* Style parts of elements */
p::first-line {
font-weight: bold;
}
p::first-letter {
font-size: 2em;
float: left;
}
/* Add content before/after */
p::before {
content: "→ ";
color: blue;
}
p::after {
content: " ←";
}
The Cascade & Specificity
When multiple CSS rules target the same element, CSS uses a specificity system to determine which rule wins. Understanding this is crucial for debugging and writing maintainable CSS.
Specificity Hierarchy (lowest to highest)
- Element selectors:
p, div, h1→ Specificity: (0,0,1) - Class selectors:
.class, [attr], :hover→ Specificity: (0,1,0) - ID selectors:
#id→ Specificity: (1,0,0) - Inline styles:
style="..."→ Specificity: (1,0,0,0) - !important: Overrides everything (avoid unless absolutely necessary)
Calculating Specificity
/* Specificity examples */
p { color: blue; } /* (0,0,1) */
.text { color: green; } /* (0,1,0) - WINS over p */
#main { color: red; } /* (1,0,0) - WINS over .text */
p.text { color: purple; } /* (0,1,1) - WINS over .text */
div p.text { color: orange; } /* (0,1,2) - WINS over p.text */
#main .text { color: pink; } /* (1,1,0) - WINS over all above */
/* !important overrides specificity (use sparingly!) */
p { color: black !important; } /* WINS over everything */
⚠️ When Rules Have Equal Specificity
The last rule in your CSS file wins (the "cascade" in Cascading Style Sheets).
Common CSS Properties
Colors
/* Multiple color formats */
color: #333; /* Hex */
color: #333333ff; /* Hex with alpha */
color: rgb(51, 51, 51); /* RGB */
color: rgba(51, 51, 51, 0.5); /* RGB with alpha */
color: hsl(0, 0%, 20%); /* HSL (Hue, Saturation, Lightness) */
color: hsla(0, 0%, 20%, 0.5); /* HSL with alpha */
background-color: #f5f5f5;
background: linear-gradient(to right, #3b82f6, #8b5cf6);
Typography
font-family: 'Inter', system-ui, sans-serif;
font-size: 16px; /* Fixed */
font-size: 1rem; /* Relative to root */
font-size: 1.2em; /* Relative to parent */
font-weight: 400; /* 100-900 */
font-weight: bold; /* Same as 700 */
line-height: 1.5; /* Unitless (recommended) */
line-height: 24px;
text-align: center; /* left, right, center, justify */
text-decoration: underline;
text-transform: uppercase; /* lowercase, capitalize */
letter-spacing: 0.05em;
word-spacing: 0.2em;
Spacing
/* Margin (outside spacing) */
margin: 20px; /* All sides */
margin: 10px 20px; /* Vertical | Horizontal */
margin: 10px 20px 30px; /* Top | H | Bottom */
margin: 10px 20px 30px 40px; /* Top Right Bottom Left */
/* Padding (inside spacing) */
padding: 20px; /* Same shorthands */
/* Individual sides */
margin-top: 10px;
padding-bottom: 15px;
Borders
border: 1px solid #ccc; /* width style color */
border-width: 2px;
border-style: solid; /* solid, dashed, dotted, none */
border-color: #333;
border-radius: 8px; /* Rounded corners */
border-radius: 50%; /* Circle */
border-radius: 10px 20px; /* Top-left/bottom-right | others */
/* Individual sides */
border-top: 1px solid #ccc;
border-right: none;
Sizing
width: 100%;
width: 300px;
max-width: 600px; /* Won't exceed this */
min-width: 320px; /* Won't go below this */
height: auto; /* Automatic based on content */
height: 100vh; /* Viewport height */
/* Box sizing affects how width/height work */
box-sizing: border-box; /* Include padding and border in width */
box-sizing: content-box; /* Default: width is content only */
Inheritance
Some CSS properties automatically pass down from parent to child elements. Understanding inheritance helps you write less code and avoid repetition.
Properties That Inherit:
- • Typography:
font-family,font-size,font-weight,line-height,color - • Text properties:
text-align,text-transform,letter-spacing - • Lists:
list-style
Properties That DON'T Inherit:
- • Layout:
margin,padding,width,height - • Borders:
border - • Background:
background - • Position:
position,top,left
/* Inheritance example */
body {
font-family: Arial, sans-serif;
color: #333;
/* All children inherit these automatically */
}
/* Control inheritance explicitly */
.child {
color: inherit; /* Force inheritance */
margin: initial; /* Browser default */
padding: unset; /* Inherit if inheritable, else initial */
}
Visual Example: Selector Specificity
See how different selectors compete for styling the same element:
This text is styled with element selector (specificity: 0,0,1)
This text has a class, so it wins (specificity: 0,1,0)
This text has an ID, highest specificity (specificity: 1,0,0)
CSS Applied:
p { color: blue; } /* All paragraphs */
.highlight { color: green; } /* Class wins over element */
#special { color: red; } /* ID wins over class */
✓ Best Practices
- • Use classes for styling – IDs are for JavaScript and anchors
- • Keep specificity low – Easier to maintain and override
- • Avoid !important – Only use for utility classes
- • Use external stylesheets – Separation of concerns, better caching
- • Organize CSS logically – Variables → Reset → Layout → Components
- • Use meaningful class names – Describe purpose, not appearance
- • Comment complex code – Help future you and other developers