Skip to content

Style a page with CSS

You will connect an external CSS file to your profile page, apply reusable visual styles, and use browser DevTools to identify which declarations control the visible result.

HTML describes the content and structure of a page. CSS controls how that structure looks. Keeping the two languages in separate files makes each file easier to read, reuse, and change.

What you will practice

  • Connect an external stylesheet to an HTML document with a link element.
  • Identify the selector, declaration block, property, and value in a CSS rule.
  • Use element and class selectors for different styling purposes, and recognize an ID selector.
  • Explain a small example of inheritance and a small example of the cascade.
  • Use browser DevTools to inspect, disable, and temporarily edit a declaration.
  • New: External stylesheets, CSS rules, comments, element selectors, class selectors, ID selectors, inheritance, the cascade, and CSS inspection in browser DevTools.
  • Reused: The html-profile project, semantic HTML, attributes, file paths, saving files, reloading the browser, and testing navigation links.

Starting point

Before you start

  • The completed html-profile folder from the HTML profile-page assignment.
  • A saved index.html file that opens in the browser and contains the required profile content.
  • VS Code and a current version of Edge, Chrome, or Firefox.
Current state
html-profile contains index.html. The page uses the browser's default colors, typeface, and borders because it does not load a stylesheet yet.
First action
Open the html-profile folder in VS Code and create styles.css beside index.html.
First checkpoint
VS Code shows index.html and styles.css in the same folder.
Help trigger
Use the recovery note or ask for help if styles.css is not in the same folder as index.html, a saved CSS change does not appear after reloading, or DevTools does not show a rule from styles.css.

You have completed the lesson when:

  • html-profile contains index.html and styles.css;
  • index.html loads styles.css with a link element in head;
  • the page uses CSS for its typeface, line height, text color, background color, heading colors, link color, and at least one border;
  • every project article uses the same class, and one class selector styles all project entries;
  • the supplied text and background color pairs remain together, and links keep their visible underline;
  • all profile content and navigation links still work; and
  • you can use DevTools to find, disable, and temporarily change one declaration from styles.css.

An external stylesheet is a CSS file that an HTML document loads. Keep styles.css beside index.html:

html-profile folder
html-profile/
├── index.html
└── styles.css

Open index.html. Inside head, add this link element after the viewport meta element:

html-profile/index.html — inside head
<link rel="stylesheet" href="styles.css">

The attributes have separate jobs:

  • rel="stylesheet" states the relationship between the HTML document and the linked file;
  • href="styles.css" gives the stylesheet path; and
  • the relative path starts in the folder that contains index.html, so it points to the file beside it.

The link element belongs in head because it describes a resource used by the document. It is a void element, so it does not have a closing tag.

Add this first rule to styles.css:

html-profile/styles.css
body {
background-color: #f4f7fb;
}

Save both files and reload index.html in the browser. The page background changes from the browser’s default white to a light blue-gray.

The complete code from body through } is a CSS rule:

Part Code Purpose
Selector body Selects the HTML element that the rule will style
Declaration block { ... } Contains the declarations for the selected element
Property background-color Names the visual feature to change
Value #f4f7fb Supplies the new setting for the property
Declaration background-color: #f4f7fb; Combines one property and one value

A colon separates the property from its value. A semicolon ends the declaration. The braces contain all declarations that belong to the rule.

  1. Confirm that index.html and styles.css appear at the same level in the VS Code Explorer.
  2. Save both files and reload the browser.
  3. Confirm that the page background has changed.
  4. Change #f4f7fb temporarily to #ffffff, save, and reload. The background becomes white.
  5. Restore #f4f7fb, save, and reload.
  • If the background does not change, compare the file name in href with the actual file name character by character.
  • If styles.css appears inside another folder, move it beside index.html or update the path to match its location.
  • If the browser shows old styling, save both files and reload the same index.html file.
  • If the complete page disappears, confirm that the link element is inside head and not replacing the body element.

Checkpoint: The browser loads the external stylesheet

What now works
Reloading index.html shows the light blue-gray background from the body rule in styles.css.
Files changed
html-profile/index.html, html-profile/styles.css
What remains
Add page-wide text styles, heading and link styles, and one reusable class for project entries.
Next action
Open styles.css and expand the existing body rule with the declarations in the next section.
If it does not work
Confirm that the two files are in the same folder and that head contains link rel="stylesheet" with href="styles.css".

Replace the current body rule with this version:

html-profile/styles.css — page defaults
/* Page defaults */
body {
color: #1f2937;
background-color: #f4f7fb;
font-family: Arial, sans-serif;
line-height: 1.6;
}

Each declaration controls one feature:

  • color sets the foreground color used for text;
  • background-color sets the color behind the content;
  • font-family asks for Arial and uses the browser’s generic sans-serif typeface if Arial is unavailable; and
  • line-height sets the height of each line to 1.6 times the current font size.

The first line is a CSS comment. The browser ignores text between /* and */. Use comments to explain the purpose of a group when that explanation helps someone navigate the file.

Add these rules after the body rule:

html-profile/styles.css — headings, links, and footer
/* Headings and links */
h1 {
color: #16324f;
}
h2 {
color: #1f4e79;
}
a {
color: #005ea8;
}
footer {
color: #44546a;
border-top: 2px solid #9aa9b8;
}

These are element selectors. Each selector uses an HTML element name and applies to every matching element. The h2 rule, for example, gives every second-level heading the same color.

The border-top declaration combines three settings in one value: a 2px width, a solid line style, and the color #9aa9b8.

The supplied colors form readable dark-text and light-background pairs. Keep each foreground color on the supplied light backgrounds during the required path. The link also keeps the browser’s default underline, so color is not the only feature that identifies it as a link.

Some CSS properties pass from a parent element to its nested elements. This behavior is called inheritance.

The visible page content is nested inside body. Most text therefore inherits the font-family, line-height, and color values from the body rule. You do not need to repeat those declarations for every paragraph and list item.

Not every property inherits. The body background and the footer border stay on those selected elements. The heading and link rules also supply their own color values, so those elements do not use the inherited body text color.

  1. Save styles.css and reload the browser.
  2. Confirm that the page uses a sans-serif typeface and that the text lines have more vertical space.
  3. Confirm that the h1, every h2, and every link use their supplied colors.
  4. Confirm that the footer has a horizontal border above it.
  5. Select each navigation link and confirm that it still reaches the matching profile section.
  • If one declaration has no effect, confirm that its property and value are separated by : and that the declaration ends with ;.
  • If all declarations after one line fail, inspect the preceding braces and confirm that every rule has one opening { and one closing }.
  • If the link color does not change, confirm that the selector is the element name a, not the text from a specific link.
  • If a navigation link no longer works, inspect index.html. CSS does not need a change to the link’s href or its target id.

An element selector is suitable when every element of one type needs the same style. A class selector is suitable when selected elements share a styling purpose.

Open index.html. Add class="project-entry" to the opening tag of each project article. Keep each article’s content unchanged:

html-profile/index.html — project article opening tags
<article class="project-entry">
<!-- Keep the existing project heading and paragraph here. -->
</article>
<article class="project-entry">
<!-- Keep the existing project heading and paragraph here. -->
</article>

The comments mark the location of your existing content. Do not replace that content with the comments.

Add this rule at the end of styles.css:

html-profile/styles.css — reusable project style
/* Reusable project style */
.project-entry {
background-color: #ffffff;
border-bottom: 2px solid #9aa9b8;
}

The period in .project-entry means “select every element whose class attribute contains project-entry.” The HTML attribute does not include the period.

Both project articles now receive the same background and bottom border from one rule. If you add another project later, the new article receives the same style when you give it the same class.

The profile page already uses IDs as targets for its fragment navigation. For example, the navigation link href="#projects" targets the Projects section. This simplified example shows the relevant relationship; keep the existing project articles in your page.

html-profile/index.html — simplified fragment target
<section id="projects">
<h2>Projects</h2>
</section>

CSS can select the same element with an ID selector:

ID selector example — not required
#projects {
background-color: #eef4ff;
}

The #projects selector matches the element whose id value is projects. The # belongs in the CSS selector, not in the HTML id value.

An ID must be unique within an HTML document, so an ID selector is suitable only for that unique element. A class can be added to several elements, so class selectors are usually more useful for reusable styles. You do not need to add the #projects rule to complete this lesson.

  1. Save index.html and styles.css, then reload the browser.
  2. Confirm that each project entry has a white background and a bottom border.
  3. In the source, confirm that each project remains an article.
  4. Remove project-entry from one article temporarily, save, and reload. Only that article loses the class style.
  5. Restore the class, save, and reload. Both project entries match again.
  • If neither project changes, confirm that the CSS selector starts with a period and that the HTML class value does not.
  • If only one project changes, compare the two opening article tags and confirm that both contain class="project-entry".
  • If the project content disappears, restore the original headings and paragraphs between each opening and closing article tag.

Checkpoint: The page has reusable CSS styles

What now works
The page uses shared text and color defaults, element selectors style headings and links, and one class selector styles every project entry.
Files changed
html-profile/index.html, html-profile/styles.css
What remains
Inspect the applied rules in DevTools and connect the visible result to the cascade.
Next action
Reload the page, right-click the main heading, and select Inspect.
If it does not work
Confirm that the stylesheet link works first, then check one selector and its matching HTML element at a time.

CSS Diner is an external practice game. It shows an HTML structure and asks you to type a selector that matches the requested items. It does not edit your html-profile files and does not replace the checks in this lesson.

Base-material target: Complete levels 1–3. These levels practice element, ID, and class selectors, which this lesson introduces directly.

Hover an item before you type to inspect its HTML. Start with the smallest selector that could match the target. If a selector does not work, use the game’s help panel, then compare the selector with the displayed HTML. You do not need to memorize every selector form before you continue.

Stop after level 3. The reusable CSS lesson returns to CSS Diner after the course introduces selector lists, the universal selector, and selector relationships.

Browser DevTools lets you inspect the page that the browser created. DevTools names and positions differ between browsers, but Edge, Chrome, and Firefox all provide an element inspector and a styles or rules panel.

  1. Reload the profile page so it shows the saved source.
  2. Right-click the main heading and select Inspect.
  3. In the Elements or Inspector panel, confirm that the selected element is h1.
  4. In the Styles or Rules panel, find the h1 rule from styles.css.
  5. Clear the checkbox beside color: #16324f, or disable that declaration with the control supplied by your browser.
  6. Confirm that the heading returns to another color because the declaration no longer applies.
  7. Enable the declaration again.
  8. Select the color value and enter another valid CSS color temporarily.
  9. Reload the page. The temporary DevTools edit disappears, and the saved value from styles.css applies again.

DevTools changes the browser’s current rendered page. It does not save changes to styles.css. Use DevTools to test an idea, then edit the source file when you want to keep the result.

Next, inspect one project article. Confirm that the Styles or Rules panel shows .project-entry. Disable and enable its border-bottom declaration and observe the border.

  • If DevTools selects a nested heading or paragraph instead of the article, move upward in the element tree until the selected opening tag is article class="project-entry".
  • If no rule from styles.css appears, return to the first checkpoint and verify the stylesheet path.
  • If a temporary edit remains after reload, confirm that you did not also copy the edit into styles.css.
  • If your browser uses different panel names, ask for the element-inspection and CSS-rules panels. The required actions are select an element, find a declaration, disable it, and edit its value.

Checkpoint: DevTools connects the source to the visible page

What now works
You can select an element, find a matching rule from styles.css, disable one declaration, and test a temporary value.
Files changed
html-profile/index.html, html-profile/styles.css
What remains
Review how inheritance and the cascade produce the final values, then complete the self-check.
Next action
Compare the two h2 rules in the cascade example without adding them to styles.css.
If it does not work
Select one visible element first, then find only the rule whose selector matches that element.

Several CSS rules can affect the same element. The cascade is the process the browser uses to choose the declaration that supplies the final value.

The cascade considers factors that include importance, selector specificity, and source order. Specificity is a measure of how directly a selector targets an element. You will work with more selector combinations and specificity in a later lesson.

For now, compare two rules with the same selector:

Source-order example — do not add both rules
h2 {
color: #1f4e79;
}
h2 {
color: #7a284d;
}

Both selectors have the same specificity and set the same property. The later declaration wins, so the final h2 color is #7a284d.

This source-order rule does not mean that the last declaration always wins. Source order decides this example because the other cascade factors are equal.

Inheritance and the cascade solve related but different problems:

  • Inheritance can pass a value from a parent element to nested elements.
  • The cascade chooses between declarations that could supply a value to the same element.

DevTools makes both mechanisms visible. The Styles or Rules panel can show matching declarations, crossed-out declarations that lost in the cascade, and values inherited from parent elements.

Self-check

Complete these checks against the required result.

  1. Confirm that html-profile contains index.html and styles.css at the same folder level.
  2. Point to the link element in head and explain what its rel and href attributes do.
  3. Point to one CSS rule and identify its selector, declaration block, property, and value.
  4. Confirm that the page uses the supplied background, text, heading, and link colors and that links remain underlined.
  5. Confirm that each project article contains class="project-entry" and receives the same class style.
  6. Explain how .project-entry and #projects match different HTML attributes and which selector can match several elements.
  7. Explain one inherited value from body and one property that stays on its selected element.
  8. Explain why the later h2 color wins in the equal-specificity source-order example.
  9. Use DevTools to disable and restore one saved declaration without changing the source file.
  10. Select all profile navigation links and confirm that their destinations still work.
  11. View the page in a narrow browser window and at 200% zoom. Confirm that the text remains readable and no content is clipped by the new styles.

The browser first reads index.html and builds a document structure from its elements. The link element tells the browser to load styles.css. The browser parses the CSS rules, matches selectors with elements, resolves inherited and competing values, and renders the result.

The HTML remains the source of the content and meaning. The CSS becomes a separate set of presentation rules. A broken CSS rule can change or remove a style, but it does not change an article into another HTML element or repair an incorrect link target.

After the required self-check passes, record the working state in the existing html-profile repository:

Commit and push the CSS foundation
git status
git diff
git add index.html styles.css
git diff --staged
git commit -m "Add profile CSS foundation"
git push

Reload the private GitHub repository and confirm that the commit contains the stylesheet connection and the first reusable styles.

The required lesson is complete when the profile page loads styles.css, the saved rules produce the required visual changes, both project entries share one class style, and you can inspect a declaration in DevTools.

Continue to Control size and spacing with the box model to control content width, space around elements, and space between content and borders.

If you stop here, leave yourself this resume note: The stylesheet is connected and the first visual styles work. Next, open the box-model lesson and inspect the space around one project entry.