We are still cooking the magic in the way!
Introduction to CSS3 & How Stylesheets Work
What is CSS?
CSS stands for Cascading Style Sheets. It is the language that controls the visual presentation of web pages -- everything from colors and fonts to layout, spacing, animations, and responsive behavior. While HTML provides the structure and content of a web page, CSS is responsible for making that content look good. Without CSS, every website would look like a plain text document with default browser styling -- black text on a white background with Times New Roman font.
The word Cascading is key to understanding CSS. It refers to the way styles flow down through a hierarchy of rules. When multiple CSS rules apply to the same element, the browser follows a specific set of rules to determine which style wins. This cascading behavior gives CSS its power and flexibility, but it can also be a source of confusion for beginners. We will explore the cascade in detail in a later lesson.
CSS is not a programming language -- it does not have variables in the traditional sense (though CSS custom properties exist), it does not have loops, and it does not perform calculations (though calc() exists for simple math). CSS is a declarative stylesheet language. You declare how elements should look, and the browser figures out how to render them.
Why Does CSS Exist?
In the early days of the web (early 1990s), there was no CSS. All visual styling was done directly inside HTML using attributes and tags. Want red text? You would write <font color="red">. Want centered text? You would use <center>. Want a background color on a table cell? You would add bgcolor="yellow" to the <td> tag.
This approach had massive problems:
- Code duplication -- If you wanted all headings to be blue, you had to add
color="blue"to every single heading tag on every single page. - Maintenance nightmare -- Changing the site's color scheme meant editing hundreds or thousands of HTML files.
- Bloated HTML -- Mixing presentation with structure made HTML files large and hard to read.
- No consistency -- It was easy to accidentally have slightly different styling on different pages.
- Accessibility problems -- Screen readers and assistive technologies had difficulty parsing content that was cluttered with presentation markup.
CSS was created to solve all of these problems by introducing the concept of separation of concerns -- keeping structure (HTML) separate from presentation (CSS). This principle remains one of the most important foundations of modern web development.
The History of CSS: From CSS1 to CSS3
Understanding the history of CSS helps you appreciate why certain features exist and why CSS works the way it does today.
CSS1 (1996)
The first version of CSS was published as a W3C Recommendation in December 1996. It was created by Hakon Wium Lie and Bert Bos. CSS1 introduced basic styling capabilities:
- Font properties (family, size, weight, style)
- Text properties (color, alignment, decoration, spacing)
- Box model basics (margins, padding, borders)
- Background colors and images
- Basic selectors (element, class, ID)
Browser support was inconsistent and buggy. Internet Explorer 3 was the first browser to implement (partial) CSS support, followed by Netscape Navigator 4. The inconsistencies between browsers during this era are legendary -- what looked perfect in one browser could be completely broken in another.
CSS2 and CSS2.1 (1998-2011)
CSS2 was published in 1998 and added significant new features:
- Positioning (
position: absolute,relative,fixed) - Z-index for layering elements
- Media types (screen, print, etc.)
- New selectors (child selector, adjacent sibling, attribute selectors)
- Generated content with
::beforeand::after - Table layout properties
CSS2.1 was a revised version that removed poorly supported features and clarified the specification. It became a W3C Recommendation in 2011 after years of refinement. CSS2.1 represented the stable baseline that all major browsers agreed upon.
CSS3 (2011-Present)
CSS3 introduced a revolutionary change in how CSS is developed. Instead of one massive specification, CSS3 was split into individual modules, each focusing on a specific area. This modular approach means different features can progress at different speeds. Some modules are already stable standards, while others are still in draft status.
Key modules and features introduced by CSS3 include:
- Selectors Level 3 --
:nth-child(),:not(), attribute substring selectors - Backgrounds and Borders --
border-radius,box-shadow, multiple backgrounds,background-size - Color Module --
rgba(),hsla(),opacity - Transitions -- Smooth animation between states
- Animations -- Keyframe-based animations
- Transforms --
rotate(),scale(),translate(), 3D transforms - Flexbox -- Powerful one-dimensional layout system
- Grid Layout -- Two-dimensional layout system
- Media Queries -- Responsive design breakpoints
- Web Fonts --
@font-facefor custom typography - Custom Properties -- CSS variables with
--variable-name - Filters --
blur(),grayscale(),drop-shadow()
How CSS Works with HTML: Separation of Concerns
The principle of separation of concerns is fundamental to modern web development. It states that each technology should handle one responsibility:
- HTML -- Structure and content (what things are)
- CSS -- Presentation and layout (how things look)
- JavaScript -- Behavior and interactivity (how things act)
When you keep these concerns separate, you gain several advantages:
- Reusability -- One CSS file can style thousands of HTML pages. Change the CSS once, and every page updates.
- Maintainability -- Designers can modify styles without touching HTML. Developers can change HTML without breaking styles.
- Performance -- CSS files are cached by the browser. After the first page load, the stylesheet does not need to be downloaded again.
- Accessibility -- Clean HTML with external CSS is easier for screen readers and assistive technologies to interpret.
- Team collaboration -- Different team members can work on HTML and CSS simultaneously without conflicts.
Example: Bad Practice -- Styling in HTML (Old Way)
<h1><font color="blue" size="7" face="Arial">My Website</font></h1>
<p><font color="#333333" size="3" face="Georgia">
Welcome to my website. This text is styled inline.
</font></p>
<table bgcolor="yellow" border="1" cellpadding="10">
<tr>
<td><font color="red">Cell 1</font></td>
<td><font color="green">Cell 2</font></td>
</tr>
</table>
Example: Good Practice -- Separation of Concerns (Modern Way)
<!-- HTML file (structure only) -->
<h1>My Website</h1>
<p>Welcome to my website. This text is styled with CSS.</p>
<table class="data-table">
<tr>
<td class="highlight">Cell 1</td>
<td class="success">Cell 2</td>
</tr>
</table>
<!-- CSS file (presentation only) -->
<style>
h1 {
color: blue;
font-size: 2.5em;
font-family: Arial, sans-serif;
}
p {
color: #333333;
font-size: 1em;
font-family: Georgia, serif;
}
.data-table {
background-color: yellow;
border: 1px solid #000;
border-collapse: collapse;
}
.data-table td {
padding: 10px;
}
.highlight { color: red; }
.success { color: green; }
</style>
highlight and success instead of directly specifying colors in the HTML. This makes the code more readable and easier to maintain. If you later decide that "success" should be blue instead of green, you change it in one place in the CSS file.How the Browser Parses CSS: The CSSOM
When a browser loads a web page, it does not simply read the HTML and CSS files and magically display a page. There is a complex process happening behind the scenes. Understanding this process helps you write more efficient CSS and debug rendering issues.
Step 1: Building the DOM
First, the browser parses the HTML and builds the DOM (Document Object Model). The DOM is a tree-like representation of the HTML document. Each HTML element becomes a node in the tree, with parent-child relationships matching the nesting of HTML tags.
Example: HTML to DOM Tree
<!-- This HTML: -->
<html>
<head>
<title>My Page</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<h1>Hello World</h1>
<p>A paragraph with <strong>bold text</strong>.</p>
</body>
</html>
<!-- Becomes this DOM tree: -->
Document
└── html
├── head
│ ├── title
│ │ └── "My Page"
│ └── link
└── body
├── h1
│ └── "Hello World"
└── p
├── "A paragraph with "
├── strong
│ └── "bold text"
└── "."
Step 2: Building the CSSOM
Simultaneously (or shortly after), the browser parses all CSS and builds the CSSOM (CSS Object Model). The CSSOM is similar to the DOM but for styles. It represents all the CSS rules in a tree structure that mirrors the document structure. Each node in the CSSOM contains the computed styles for the corresponding DOM element.
The browser reads CSS from multiple sources and combines them:
- User agent stylesheet -- The browser's default styles (e.g., headings are bold, links are blue and underlined).
- User stylesheet -- Custom styles set by the user in browser preferences (rare today).
- Author stylesheet -- Your CSS files, inline styles, and
<style>tags.
Example: CSS Rules Being Parsed
/* The browser reads these rules: */
body {
font-family: Arial, sans-serif;
font-size: 16px;
color: #333;
}
h1 {
font-size: 2em;
color: navy;
margin-bottom: 20px;
}
p {
line-height: 1.6;
margin-bottom: 15px;
}
/* And builds a CSSOM tree:
body
font-family: Arial, sans-serif
font-size: 16px
color: #333
├── h1
│ font-size: 2em (computed: 32px)
│ color: navy
│ margin-bottom: 20px
│ (inherits font-family from body)
└── p
line-height: 1.6
margin-bottom: 15px
(inherits font-family, font-size, color from body)
*/
Step 3: The Render Tree
The browser then combines the DOM and CSSOM to create the Render Tree. The render tree contains only the elements that will actually be displayed on screen. Elements with display: none are excluded from the render tree entirely (but elements with visibility: hidden remain in the render tree -- they just take up space without being visible).
Step 4: Layout (Reflow)
The browser calculates the exact position and size of each element in the render tree. This process is called layout (or reflow). The browser must figure out how much space each element takes, where it goes relative to other elements, and how it fits within the viewport.
Step 5: Paint
Finally, the browser paints each element pixel by pixel onto the screen. This includes filling in colors, rendering text, drawing borders, applying shadows, and compositing layers. This is the paint (or raster) step.
Step 6: Compositing
For elements that exist on separate layers (due to transforms, opacity, or z-index), the browser composites them together in the correct order. This is the compositing step.
color only triggers a repaint, which is relatively cheap. But changing width or height triggers a full layout recalculation (reflow), which is much more expensive. This is why animations that use transform and opacity are smoother than animations that change width, height, or margin.The Complete Rendering Pipeline
Here is the complete rendering pipeline in order:
- Parse HTML -- Build the DOM tree
- Parse CSS -- Build the CSSOM tree
- Combine -- Merge DOM + CSSOM into the Render Tree
- Layout -- Calculate geometry (position, size) of each element
- Paint -- Fill in pixels (colors, text, images, borders)
- Composite -- Layer together separate compositing layers
If anything changes after the initial render -- for example, a CSS class is added via JavaScript, or the user resizes the window -- the browser may need to repeat some or all of these steps. This is why efficient CSS matters for performance.
Example: Rendering Pipeline Visualization
HTML Document CSS Stylesheet
│ │
▼ ▼
DOM Tree CSSOM Tree
│ │
└───────┬───────────────┘
▼
Render Tree
│
▼
Layout
(calculate positions)
│
▼
Paint
(fill in pixels)
│
▼
Composite
(merge layers)
│
▼
Pixels on Screen
CSS is Render-Blocking
An important concept to understand is that CSS is render-blocking. This means the browser will not render any content to the screen until it has finished downloading and parsing all CSS files. The reason is simple -- the browser needs to know the styles before it can lay out and paint elements. If it rendered content before CSS was loaded, you would see a flash of unstyled content (FOUC) followed by a jarring re-render when styles are applied.
This has practical implications:
- Keep your CSS files as small as possible for faster initial rendering.
- Place
<link>tags for CSS in the<head>of your document so the browser discovers them early. - Consider using critical CSS (inlining essential styles) for above-the-fold content.
- Avoid unnecessary
@importstatements in CSS, as they create additional round trips to the server.
Developer Tools for CSS Inspection
Every modern browser comes with powerful developer tools that let you inspect, modify, and debug CSS in real time. Learning to use these tools is just as important as learning CSS itself.
Opening Developer Tools
- Chrome / Edge -- Press
F12orCtrl+Shift+I(Windows/Linux) orCmd+Option+I(Mac) - Firefox -- Press
F12orCtrl+Shift+I(Windows/Linux) orCmd+Option+I(Mac) - Safari -- Press
Cmd+Option+I(you must first enable the Develop menu in Preferences > Advanced)
Key Panels for CSS Work
- Elements / Inspector panel -- Shows the DOM tree. Click any element to see its applied CSS styles in the Styles sub-panel.
- Styles sub-panel -- Displays all CSS rules that apply to the selected element, in order of specificity. You can edit styles live.
- Computed tab -- Shows the final computed values after the cascade is resolved. This is what the browser actually uses.
- Box Model visualization -- Shows the element's content, padding, border, and margin as a visual diagram.
- Layout tab -- Helps visualize Grid and Flexbox layouts with overlay guides.
Example: Using the Inspect Element Feature
1. Right-click on any element on a web page
2. Select "Inspect" or "Inspect Element"
3. The developer tools will open with that element highlighted
4. In the Styles panel on the right, you will see:
- All CSS rules applied to that element
- Which file each rule comes from
- Which rules are overridden (shown with strikethrough)
- The ability to toggle properties on/off with checkboxes
- The ability to edit values by clicking on them
5. Try changing a color value:
- Click on the color value next to "color:"
- Type a new color name like "red"
- Watch the page update instantly
6. Try adding a new property:
- Click in an empty area within a rule
- Type a new property like "border: 2px solid red"
- Press Enter to apply
Useful Dev Tools Features for CSS
- Force element state -- You can force an element into
:hover,:active,:focus, or:visitedstate to inspect styles that only appear during interaction. - Color picker -- Click any color swatch in the Styles panel to open a visual color picker.
- Toggle CSS properties -- Uncheck the checkbox next to any property to disable it temporarily and see its effect.
- Filter styles -- Use the filter box in the Styles panel to search for specific properties.
- Device toolbar -- Toggle the responsive design mode to see how your CSS looks on different screen sizes.
Exercise 1: Explore Browser Default Styles
Create a simple HTML file with a heading, a paragraph, a link, an unordered list, and a blockquote. Do not add any CSS at all. Open the file in your browser and use developer tools to inspect each element. In the Styles panel, you will see the browser's user agent stylesheet rules. Take note of:
- What default font size does the browser assign to
<h1>? - What default margins does
<p>have? - What color and text-decoration does
<a>have? - What list-style-type does
<ul>use? - Does
<blockquote>have any default margin or padding?
Understanding these defaults will help you write better CSS, because your styles build on top of (or override) these browser defaults.
Exercise 2: Modify a Live Website with Developer Tools
Go to any website you visit regularly (a news site, social media, or any web app). Open the developer tools and try the following:
- Change the background color of the page body to a dark color and the text color to white (dark mode experiment).
- Find the main heading of the page and increase its font size to 48px.
- Find a navigation menu and change its background color.
- Find an image and add a CSS
filter: grayscale(100%)to make it black and white. - Find a button and add
border-radius: 50pxto make it pill-shaped.
Take a screenshot of your modified page. This exercise helps you build confidence with developer tools and demonstrates the power of CSS to completely transform a page's appearance.
Exercise 3: Trace the Rendering Pipeline
Create the following HTML file and open it in your browser:
<!DOCTYPE html>
<html>
<head>
<style>
body { font-family: sans-serif; background: #f0f0f0; }
.box { width: 200px; padding: 20px; margin: 20px auto;
background: white; border: 2px solid #333; }
.box h2 { color: darkblue; }
.hidden { display: none; }
.invisible { visibility: hidden; }
</style>
</head>
<body>
<div class="box"><h2>Visible Box</h2><p>This is visible.</p></div>
<div class="box hidden"><h2>Hidden Box</h2><p>display: none</p></div>
<div class="box invisible"><h2>Invisible Box</h2><p>visibility: hidden</p></div>
</body>
</html>
Use developer tools to inspect all three boxes. Notice that the .hidden box does not take up any space on the page (it is removed from the render tree), while the .invisible box still takes up space even though you cannot see it. Sketch out what the DOM tree, CSSOM, and render tree look like for this document.