CSS text color: what we’re really talking about

When people say “CSS text color”, they almost always mean the color property.

  • color sets the color of text (and it also affects currentColor, which we’ll use later).
  • background-color sets the background behind the text (different thing).
  • fill is for SVG shapes, not normal text (unless you’re using SVG text).

So if you want to change the color of words on the page, start with color. It’s the “I would like my letters to stop being boring” property.

The CSS text color property: color

The color property sets the foreground color of text. It applies to most text-containing elements: p, h2, span, links, buttons, and more.

.demo {
  color: #111;
}
.demo {
  color: crimson;
}
.demo {
  color: rebeccapurple;
}
.demo {
  color: rgb(0 120 255);
}
*,
::before,
::after {
  box-sizing: border-box;
}

.wrap {
  padding: 18px;
  font-family: ui-monospace, system-ui, sans-serif;
  background: #f6f6f6;
  border: 3px solid #111;
  border-radius: 14px;
  max-width: 720px;
}

.demo {
  font-size: 20px;
  line-height: 1.4;
}

.demo strong {
  font-weight: 800;
}

This text is using color. Switch snippets to change it.

CSS text color white and CSS text color red

Named colors are a quick way to get started. Two of the most common are white and red. The main gotcha: white text needs a darker background, or it’ll be invisible.

.card {
  background: #111;
  color: white;
}
.card {
  background: #fff;
  color: red;
}
.card {
  background: #111;
  color: #ff4d4d;
}
.card {
  background: #0b1020;
  color: #8be9fd;
}
*,
::before,
::after {
  box-sizing: border-box;
}

.card {
  padding: 18px;
  border: 3px solid #111;
  border-radius: 14px;
  font-family: system-ui, ui-monospace, sans-serif;
  max-width: 720px;
}

.card h3 {
  margin: 0 0 10px;
  font-size: 22px;
}

.card p {
  margin: 0;
  font-size: 16px;
  line-height: 1.4;
}

Readable text matters

White on dark works. Red on white works. White on white works… for ghosts.

Use named colors for quick demos, but most real projects use color codes so your brand colors don’t depend on what the browser thinks “red” should feel like today.

CSS text color code: hex, rgb, hsl (and friends)

Color “codes” are just different ways to describe a color. The three most common formats in CSS are:

  • Hex: #ff0000 or short #f00
  • RGB / RGBA: rgb(255 0 0) and rgb(255 0 0 / 0.6)
  • HSL / HSLA: hsl(0 100% 50%) and hsl(0 100% 50% / 0.6)

Hex is compact. RGB is great when you think in “red/green/blue”. HSL is nice when you want to tweak lightness/saturation without doing math gymnastics.

.sample.hex {
  color: #e11d48;
}
.sample.shorthex {
  color: #0af;
}
.sample.rgb {
  color: rgb(34 197 94);
}
.sample.rgba {
  color: rgb(59 130 246 / 0.55);
}
.sample.hsl {
  color: hsl(35 95% 50%);
}
*,
::before,
::after {
  box-sizing: border-box;
}

.panel {
  border: 3px solid #111;
  border-radius: 14px;
  padding: 18px;
  font-family: ui-monospace, system-ui, sans-serif;
  background: #f6f6f6;
  max-width: 760px;
}

.panel h3 {
  margin: 0 0 12px;
  font-size: 20px;
}

.row {
  display: grid;
  gap: 10px;
}

.sample {
  padding: 12px 14px;
  border-radius: 12px;
  background: #fff;
  border: 1px solid #ddd;
  font-size: 18px;
}

.muted {
  color: #111;
  font-size: 14px;
  margin: 10px 0 0;
}

Same idea, different syntax

Hex: #e11d48
Short hex: #0af
RGB: rgb(34 197 94)
RGB with alpha: rgb(59 130 246 / 0.55)
HSL: hsl(35 95% 50%)

Tip: modern CSS allows spaces in rgb/hsl and alpha with a slash.

A tiny cheat sheet for beginners

  • If you have a design file that gives you hex: use hex.
  • If you need transparency: use rgb(... / alpha) or hsl(... / alpha).
  • If you want to tweak “make it lighter/darker” often: try HSL.

Text color inheritance: why one rule changes a whole section

color is inherited. That means if you set color on a parent element, children usually take that color automatically.

This is super useful: set a base color once on a container, and only override where needed.

.section {
  color: #111;
}
.section {
  color: #0f172a;
}

.section .highlight {
color: #e11d48;
} 
.section {
  color: #111;
}

.section a {
  color: inherit;
}
.section {
  color: #111;
}

.section .muted {
  color: rgb(17 17 17 / 0.55);
}
*,
::before,
::after {
  box-sizing: border-box;
}

.section {
  border: 3px solid #111;
  border-radius: 14px;
  padding: 18px;
  background: #f6f6f6;
  font-family: system-ui, ui-monospace, sans-serif;
  max-width: 760px;
}

.section h3 {
  margin: 0 0 10px;
  font-size: 22px;
}

.section p {
  margin: 0 0 10px;
  line-height: 1.45;
}

.section a {
  text-decoration: underline;
  text-underline-offset: 3px;
}

.section code {
  font-family: ui-monospace, system-ui, sans-serif;
  background: #fff;
  border: 1px solid #ddd;
  padding: 0 6px;
  border-radius: 8px;
}

Inheritance in action

This paragraph inherits the section’s color. This part can override it.

Muted text can be done with alpha (still the same hue, just quieter).

A link: hover me

Pro tip: color: inherit; is handy for links inside colored components, where you want the link to match the surrounding text rather than default browser link blue.

Learn more about link styling in the CSS Link Interactive Tutorial.

CSS text color change: hover, focus, and class toggles

“Change text color” usually means one of these:

  • Change based on user interaction (hover/focus/active)
  • Change based on state (a class like .is-error, .is-success)
.linky {
  color: #0b5fff;
}

.linky:hover {
color: #e11d48;
} 

.button {
  color: white;
  background: #111;
}

.button:hover {
  color: #111;
  background: #fff;
}

.note {
  color: #111;
}

.note.is-success {
  color: #15803d;
}

.note.is-warning {
  color: #b45309;
}

.note.is-error {
  color: #b91c1c;
}

.input {
  color: #111;
}

.input:focus {
  color: #0b5fff;
}
*,
::before,
::after {
  box-sizing: border-box;
}

.grid {
  display: grid;
  gap: 14px;
  max-width: 760px;
  font-family: system-ui, ui-monospace, sans-serif;
}

.card {
  border: 3px solid #111;
  border-radius: 14px;
  padding: 16px;
  background: #f6f6f6;
}

.card h3 {
  margin: 0 0 10px;
  font-size: 18px;
}

.linky {
  text-decoration: underline;
  text-underline-offset: 3px;
}

.button {
  border: 2px solid #111;
  border-radius: 12px;
  padding: 10px 14px;
  cursor: pointer;
  font: inherit;
}

.note {
  font-weight: 700;
}

.input {
  width: 100%;
  border: 2px solid #111;
  border-radius: 12px;
  padding: 10px 12px;
  font: inherit;
  outline: none;
}

Hover a button

State classes

Success message

Warning message

Error message

Focus style

If you ever think “why doesn’t my hover color work?”, check whether you’re actually hovering the element you styled (and whether something else is sitting on top of it).

Learn more about :hover in the CSS :hover Pseudo-Class Interactive Tutorial.

Quick accessibility: contrast and link clarity

Readable color isn’t just aesthetic, it’s usability. Two beginner-friendly rules:

  • Contrast: light text needs dark background and vice versa. If it looks “faint”, it probably fails contrast.
  • Links: don’t rely on color alone to indicate links. Underlines are your friend.
.block {
  background: #111;
  color: rgb(255 255 255 / 0.75);
}
.block {
  background: #111;
  color: white;
}
.block {
  background: #fff;
  color: rgb(17 17 17 / 0.55);
}
.block {
  background: #fff;
  color: #111;
}
*,
::before,
::after {
  box-sizing: border-box;
}

.block {
  border: 3px solid #111;
  border-radius: 14px;
  padding: 18px;
  font-family: system-ui, ui-monospace, sans-serif;
  max-width: 760px;
}

.block h3 {
  margin: 0 0 10px;
  font-size: 20px;
}

.block p {
  margin: 0;
  line-height: 1.45;
}

Contrast check

Muted text is fine for secondary details, but don’t mute your main content into invisibility.

Muted text is great for timestamps, captions, hints, “last updated” labels. For body text, be careful with opacity.

CSS text color gradient: the “background-clip” trick

CSS can’t do color: linear-gradient(...). That value is invalid.

So how do people do “gradient text”? You put the gradient in the background, then clip it to the text.

  • Set background to a gradient
  • Use background-clip: text
  • Make the actual text color transparent with color: transparent

There’s also a WebKit-prefixed version for best compatibility: -webkit-background-clip: text.

.title {
  background: linear-gradient(90deg, #0b5fff, #e11d48);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.title {
  background: linear-gradient(90deg, #22c55e, #0b5fff, #eab308);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.title {
  background: radial-gradient(circle at 20% 30%, #e11d48, #0b5fff 55%, #111 95%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.title {
  background: linear-gradient(90deg, #0b5fff, #e11d48);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  filter: drop-shadow(0px 6px 18px rgb(0 0 0 / 0.25));
}
*,
::before,
::after {
  box-sizing: border-box;
}

.hero {
  border: 3px solid #111;
  border-radius: 14px;
  padding: 22px;
  background: #f6f6f6;
  font-family: system-ui, ui-monospace, sans-serif;
  max-width: 760px;
}

.title {
  font-size: 44px;
  line-height: 1.05;
  margin: 0 0 10px;
  font-weight: 900;
  letter-spacing: -0.02em;
  width: fit-content;
}

.sub {
  margin: 0;
  color: #111;
  line-height: 1.4;
}

Gradient Text

This is not color: linear-gradient(). It’s a clipped background.

CSS text color linear gradient: tips for better-looking gradient text

  • Use bigger font sizes and heavier weights. Tiny text + gradients can look noisy.
  • Try letter-spacing slightly negative for big headings (like we did).
  • Gradients look best on short text: titles, badges, labels.

Animated gradient text (because we can)

If you animate the background-position (and often make the background larger), you can create a smooth “moving gradient” effect.

.title {
  background: linear-gradient(90deg, #0b5fff, #e11d48, #22c55e, #0b5fff);
  background-size: 240% 100%;
  background-position: 0% 50%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  animation: slide 3s ease-in-out infinite alternate;
}

@keyframes slide {
to {
background-position: 100% 50%;
}
} 
*,
::before,
::after {
  box-sizing: border-box;
}

.wrap {
  border: 3px solid #111;
  border-radius: 14px;
  padding: 22px;
  background: #f6f6f6;
  font-family: system-ui, ui-monospace, sans-serif;
  max-width: 760px;
}

.title {
  font-size: 46px;
  line-height: 1.05;
  margin: 0;
  font-weight: 900;
  letter-spacing: -0.02em;
}

Moving Gradient

Extra power move: currentColor (borders and icons follow the text)

currentColor is a special keyword that resolves to the element’s computed color. That means you can set text color once and have borders, shadows, or icon fills match automatically.

.badge {
  color: #0b5fff;
  border-color: currentColor;
}
.badge {
  color: #e11d48;
  border-color: currentColor;
}
.badge {
  color: #15803d;
  border-color: currentColor;
}
.badge {
  color: #111;
  border-color: currentColor;
}
*,
::before,
::after {
  box-sizing: border-box;
}

.badge {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-family: system-ui, ui-monospace, sans-serif;
  font-weight: 800;
  padding: 12px 14px;
  border: 3px solid #111;
  border-radius: 999px;
  background: #f6f6f6;
}

.dot {
  width: 12px;
  height: 12px;
  border-radius: 999px;
  background: currentColor;
  display: inline-block;
}

.note {
  margin-top: 14px;
  font-family: system-ui, ui-monospace, sans-serif;
  color: #111;
}
Status Badge

The border and dot use currentColor, so they follow the text color automatically.

This is one of those “small CSS tricks” that makes components easier to theme.

CSS text color not working: a debugging checklist

If your color change isn’t showing up, it’s usually one of these:

  • Specificity: another selector is more specific and wins.
  • Order: the “winning” rule comes later in the CSS.
  • Inheritance confusion: you changed a child, but the text is actually coming from a different element.
  • Opacity: you’re using opacity on a parent, which fades everything (including text).
  • Gradient text: you used background-clip: text but forgot color: transparent.
  • Link styles: the browser’s default link styles (or your theme) override your base text color.

In DevTools, select the element, look at the “Styles” panel, and find which color rule is crossed out. The crossed-out one is the loser. The one that isn’t crossed out is the winner.

Recap

  • Use color for text color.
  • Named colors are fine for demos; hex/rgb/hsl are common for real UI work.
  • color inherits, which is powerful for theming sections/components.
  • Interactive changes usually use :hover, :focus, and state classes.
  • Gradient text is done with background-clip: text and color: transparent.
  • currentColor helps borders/icons follow text color automatically.

CSS Text Color Conclusion

Changing text color in CSS is straightforward once you understand the color property and how it interacts with inheritance, specificity, and different color formats. With these basics under your belt, you can confidently style text for readability, accessibility, and visual impact.

w