CSS How to Add CSS (Inline, Internal, External)

CSS (Cascading Style Sheets) is the language that controls how HTML elements look: colors, spacing, fonts, layout, and more. Before you can write a single rule, you need to know where that rule actually lives. There are three ways to attach CSS to an HTML document: inline, internal, and external. Each has a different scope, a different place in the cascade, and different practical trade-offs, so choosing the right one for the job is one of the first real skills in CSS.

Overview / How It Works

Inline CSS is written directly on an element using the style attribute, for example style="color: red;". It applies only to that single element instance and carries no selector at all — the “selector” is implicit, meaning this exact element. Inline styles are parsed as part of the HTML document itself; the browser reads them the moment it builds the DOM node for that element, and they never live in a separate stylesheet object.

Internal CSS, sometimes called embedded CSS, is written inside a <style> element, almost always placed in the <head> of the document. It behaves like a full stylesheet, with selectors, rules, and even media queries, but it only affects the single HTML file it is written in. The browser parses it in document order, building a CSSOM (CSS Object Model) fragment that applies to the whole page.

External CSS lives in a separate .css file and is linked into the HTML with a <link rel="stylesheet" href="..."> element, also normally placed in <head>. This is the most powerful method for real projects: one .css file can style an unlimited number of HTML pages, the browser can cache it across page loads so repeat visits are faster, and it keeps structure (HTML) cleanly separated from presentation (CSS).

Under the hood, the rendering engine builds the DOM from HTML and, independently, a CSSOM from every CSS source it encounters — inline declarations, <style> blocks, and linked files — then merges them by document order and resolves conflicts using specificity and the cascade. Inline styles are not “rules” the CSSOM resolves through selector specificity math at all; they are attached directly to the element and treated as having a specificity higher than any selector-based rule (short of !important), which is why they almost always win when there is a conflict.

Syntax

The three methods differ in where the CSS text lives and how it is introduced to the browser:

Method Where it lives General form
Inline A style attribute on one element <tag style="property: value; property: value;">
Internal A <style> element, usually in <head> <style> selector { property: value; } </style>
External A separate .css file, linked with <link> <link rel="stylesheet" href="styles.css">
  • property / value — the actual CSS declaration, identical in all three methods.
  • selector — required for internal and external CSS to target elements; not used for inline CSS because the element itself is the target.
  • rel=”stylesheet” — tells the browser to fetch and apply the linked file as CSS.
  • href — the path (relative or absolute) to the .css file.

Examples

Example 1: Inline CSS

Given the HTML <p style="color: navy; font-weight: bold; background-color: #f0f0f0; padding: 8px;">Hello</p>, the declarations inside the attribute are:

color: navy;
font-weight: bold;
background-color: #f0f0f0;
padding: 8px;

Result: The word “Hello” renders in bold, dark navy-blue text, sitting inside a light gray box with 8px of space between the text and the box edges on every side.

Inline CSS is convenient for a quick, one-off tweak, but it does not scale: there is no reuse across elements, no way to target pseudo-classes like :hover or use media queries, and overriding it later usually requires !important because of its very high specificity.

Example 2: Internal CSS

Placed inside <head><style>...</style></head>, applying to a page with an <h1> and a <p class="intro">:

body {
  font-family: Arial, sans-serif;
  margin: 0;
  background-color: #fafafa;
}

h1 {
  color: #222222;
  text-align: center;
}

.intro {
  font-size: 1.1rem;
  line-height: 1.6;
  color: #444444;
}

Result: The whole page gets a very light gray background and a sans-serif font. The <h1> heading appears centered in dark gray text, and any element with class intro gets slightly larger text with more generous line spacing in a medium gray.

Internal CSS is well suited to single-page demos, prototypes, or a page that genuinely needs styling no other page shares, since the rules are only ever read by the browser when it parses this exact HTML file.

Example 3: External CSS

Saved as styles.css and linked with <link rel="stylesheet" href="styles.css"> in <head>, applied to a <nav> containing links:

:root {
  --brand-color: #2b6cb0;
  --spacing: 1rem;
}

nav {
  display: flex;
  gap: var(--spacing);
  padding: var(--spacing);
  background-color: var(--brand-color);
}

nav a {
  color: white;
  text-decoration: none;
  font-weight: 600;
}

nav a:hover {
  text-decoration: underline;
}

Result: The navigation bar becomes a horizontal row (via flexbox) of evenly spaced links, with a solid medium-blue background and 1rem of padding around and between items. The links themselves are white, bold, and show no underline until the mouse hovers over one, at which point an underline appears.

External CSS is the only method that reuses the same rules across many HTML files, and browsers cache the downloaded file so subsequent page loads on the same site can skip re-downloading it. Custom properties like --brand-color defined at the top make it easy to keep values consistent site-wide.

How It Works Step by Step / Under the Hood

When a browser renders a page, it does the following, roughly in parallel:

  • Parses the HTML into a DOM (Document Object Model) tree.
  • Parses every CSS source it finds — external files referenced by <link>, <style> blocks, and inline style attributes — into a CSSOM (CSS Object Model).
  • Combines the DOM and CSSOM into a render tree, computing the final (“used”) value of every property on every element.
  • Runs layout (computing box sizes and positions) and then paint (drawing pixels).

When more than one rule targets the same element and property, the cascade decides the winner using, in order: origin and importance (author styles normally beat browser defaults; !important flips priority), specificity, and finally source order (later rules beat earlier ones when specificity ties). Specificity is calculated by counting selector parts: inline styles outrank everything (treat this as effectively the highest tier), an ID selector like #nav outranks a class or attribute selector like .nav, which in turn outranks a plain element selector like nav.

Concretely, suppose an external stylesheet contains h1 { color: blue; }, an internal <style> block placed later in the same <head> contains h1 { color: green; }, and the <h1> element itself has style="color: red;". All three selectors have identical specificity (a single element selector, or none at all for the inline case), so the browser first applies source order between the two stylesheet rules — the internal rule, appearing after the external <link> in the HTML, wins that comparison and the heading would be green if only those two existed. But the inline declaration is not compared by selector specificity at all; it is treated as more specific than any selector-based rule, so the final rendered color is red.

Common Mistakes

Mistake 1: Using // comments instead of /* */

CSS has no single-line comment syntax. Writing // inside a stylesheet, a habit carried over from JavaScript, produces invalid CSS that the parser cannot make sense of:

nav {
  // this is a nav bar
  display: flex;
}

This is wrong because // this is a nav bar is not a valid declaration (no property/value pair separated by a colon), so the parser fails on that line. The correct syntax uses /* ... */:

nav {
  /* this is a nav bar */
  display: flex;
}

Mistake 2: Forgetting to close a rule block

A missing closing brace on a <style> rule leaves the parser expecting more input and breaks every rule that follows it:

h1 {
  color: blue;
  font-size: 2rem;

This is wrong because the opening { for h1 is never matched with a closing }, so the parser treats everything after it, including any later rules, as still being inside this one unfinished block. The fix is simply to close the block:

h1 {
  color: blue;
  font-size: 2rem;
}

Best Practices

  • Prefer external CSS for anything beyond a single quick test or prototype; it is reusable across pages and cacheable by the browser.
  • Reserve inline styles for truly one-off cases or styles generated dynamically by JavaScript, since they are hardest to override and cannot use pseudo-classes or media queries.
  • Use internal CSS for single-file demos, code playgrounds, or a page that genuinely has no styling in common with the rest of the site.
  • Keep specificity low and predictable; fix an underlying selector instead of reaching for an inline style or !important just to “win” a cascade conflict.
  • Place <link> stylesheet references in <head> so styles are known before the page paints, avoiding a visible flash of unstyled content.
  • Use one external stylesheet, or a small organized set, per site rather than scattering rules across many separate <style> blocks.
  • Take advantage of CSS custom properties in an external sheet to keep values like colors and spacing consistent across every page that links to it.

Practice Exercises

1. Create an HTML page with a <style> block that gives every paragraph a light gray background and 12px of padding. Then add one paragraph with an inline style attribute that sets its background to yellow instead. Before running it, predict which background wins and why.

2. Move the internal <style> rules from exercise 1 into a separate file named page.css, and link it correctly from <head> using <link>. Confirm the page still looks identical.

3. Suppose an external stylesheet styles a heading with color: blue;, and an internal <style> block placed after that external <link> styles the same heading with color: green;, with no inline style involved. Write out both rules and predict, then verify in a browser, which color the heading actually shows.

Summary

  • CSS can be added to a page via inline styles, internal <style> blocks, or external linked .css files.
  • Inline CSS uses the style attribute on a single element and behaves as if it has the highest specificity of the three.
  • Internal CSS lives in a <style> element, usually in <head>, and affects only the one HTML document it is written in.
  • External CSS lives in a separate .css file linked with <link>, letting one file style many pages and benefit from browser caching.
  • When rules conflict, the browser resolves them through the cascade: origin and !important, then specificity, then source order.
  • For real projects, external CSS is the standard choice; inline and internal styles are best reserved for quick, one-off, or single-file needs.