Inline CSS: when a style attribute is right

Inline CSS is a rule written directly on an element in its style attribute. It wins over every stylesheet rule, cannot be reused, and is exactly right in two situations: a value computed per element, and an email. Everywhere else, a style block in the page does the same job better.

Inline CSS is a rule placed on the element itself, in a style attribute, rather than in a stylesheet: <p style="color:#b91c1c">.

The markup. The highlighted line is the part this term is about.
The markup. The highlighted line is the part this term is about.

It has the highest specificity of any ordinary rule, so it wins whatever the stylesheet says, and it cannot be shared between elements. Those two facts decide where it belongs.

This guide covers the two cases where inline is correct, why it is wrong the rest of the time, specificity concretely, and how inline, internal and external styles relate for a page that will be sent as one file.

Three places CSS can live:

<!-- inline: one element -->
<p style="color:#52525b;font-size:14px">…</p>

<!-- a style tag: this document -->
<style> p { color:#52525b; font-size:14px } </style>

<!-- an external file: many documents -->
<link rel="stylesheet" href="styles.css">

Inline wins any conflict between them, because the browser treats it as the most specific possible rule.

The two cases where inline CSS is correct

1. A value computed at runtime

Inline CSS lives on the element and beats the other two. A style block in the page is reusable and travels with the file. An external file is reusable across pages and is the one that goes missing when a single page is sent.
Inline CSS lives on the element and beats the other two. A style block in the page is reusable and travels with the file. An external file is reusable across pages and is the one that goes missing when a single page is sent.
<span class="track"><i class="fill" style="width:78%"></i></span>

The 78% comes from data. It cannot live in a stylesheet, because a stylesheet cannot know it. Everything else about the bar — colour, height, radius, transition — belongs in a class:

.fill { display: block; height: 100%; background: var(--accent); border-radius: 6px; }

That split is the right pattern for every chart: the number inline, the appearance in a class.

2. Email

Email clients strip <style> blocks unpredictably and support a small, inconsistent subset of CSS. Inline styles on every element is the only approach that survives, which is why marketing email still looks like 2004 markup. See sending HTML by email for why sending a page as a link avoids the whole area.

Why it is wrong the rest of the time

It repeats. The same declaration on forty rows is forty copies. One class is one copy — this is the main reason generated pages hit length limits.

It cannot hold conditions. No media queries, no :hover, no :focus, no prefers-color-scheme. Anything responsive or interactive is unreachable inline.

<!-- impossible inline -->
<div style="@media (max-width: 600px) { ... }">

It is hard to override. Overriding an inline style from a stylesheet requires !important, which then has to be overridden by another !important. Two steps from there the cascade is unreadable.

It cannot be cached separately. A stylesheet is downloaded once and reused across pages. Inline styles come with every copy of every document.

A page split across files ✗ Works only inside its own folder ✗ Styling vanishes when sent alone ✗ Images turn into empty boxes ✗ Breaks the moment a file is renamed One self-contained file ✓ Renders anywhere it lands ✓ Styling travels with it ✓ Images are carried inside ✓ Nothing to keep together
A page whose rules are inside it renders the same everywhere. A page whose rules are in another file renders only next to that file.

Specificity, concretely

Source Wins against
!important in a stylesheet Everything except another !important inline
style="…" Every normal selector
#id Classes and elements
.class Elements
p Nothing

Debugging note: if a rule refuses to apply and the inspector shows it struck through, look for a style attribute on the element. That is the cause more often than a specificity miscalculation.

For a single self-contained file

A page that must travel alone should use a <style> block in the head, not inline styles everywhere. You get both properties at once: everything inside one file, and rules that can be reused and can hold media queries.

<head>
  <style>
    * { box-sizing: border-box; }
    body { font-family: -apple-system, "Segoe UI", sans-serif; margin: 0; }
    .card { border: 1px solid #e7e7ea; border-radius: 12px; padding: 15px; }
    @media (max-width: 700px) { .cards { grid-template-columns: 1fr; } }
  </style>
</head>

That is the arrangement to ask for in any prompt — see self-contained HTML.

Decision table

Situation Inline <style> block External file
A width computed from data Yes
An email body Yes
One page sent as a file Yes
A page to be embedded or previewed Yes
A page generated by an assistant Yes
A site with several pages Yes
A hover or focus state Yes Yes
A media query Yes Yes
Dark mode Yes Yes

The bottom three rows are impossible inline, which is the hard limit rather than a preference.

The specificity consequence

An inline style beats every selector in a stylesheet, so overriding one needs !important — and then overriding that needs another !important. Two steps in, nobody can predict which rule wins.

Practical debugging note: when a rule refuses to apply and the inspector shows it struck through, look for a style attribute on the element before recalculating specificity. That is the cause more often than a selector mistake.

For a single-file page, a <style> block in the head gives you everything inline gives you — nothing to fetch, self-contained — while keeping media queries and states available. There is no case where scattering inline styles through a document is better than that, except email.

How inline styles interact with everything else

An inline rule beats any selector in a stylesheet, however specific, unless the stylesheet rule carries !important.

That is why a generated page full of inline styles is so hard to restyle: a new stylesheet does nothing until every attribute is removed or overridden one by one.

It is also why a bar chart's widths belong inline, they are per-element values that no stylesheet should override, and why a colour scheme does not, because it should be changeable in one place.

The email exception, in detail

Mail clients render a small subset of CSS and many of them strip <style> blocks from the head, so a marketing email is built with every rule inlined on the element it applies to.

That is a constraint of the medium, not a style choice, and tools exist to inline a stylesheet automatically before sending.

For a page that is read in a browser, the same technique is pure cost. Email versus link covers what survives an inbox.

Choosing where a rule lives: 4 steps

  1. Use inline for values computed per element. A bar's width, a colour driven by data. The value belongs to that element and no other.
  2. Use inline for email. Mail clients strip style blocks in many cases; inline is what survives the paste.
  3. Use a <style> block for everything else on a page you will send. Reusable, readable, and it travels with the file, which is what a self-contained page needs.
  4. Use an external file only for a site of many pages. Never for a single page that will be sent on its own, because the file does not come along.

Questions people ask

What is inline CSS?

A style attribute on a single element. It applies only to that element and overrides rules from any stylesheet.

When should I use it?

For a value computed at runtime, such as a bar width from a number, and for email, where stylesheets are unreliable.

Why is it discouraged otherwise?

It cannot be reused, cannot carry media queries or hover states, is hard to override, and repeats the same declarations dozens of times.

Does it hurt performance?

Indirectly. The same declarations repeated through the markup make the document larger, and it cannot be cached separately the way a stylesheet can.

Keep reading