CSS Text Outline: The Guide to text-stroke, WebKit & SVG
Typography is the cornerstone of web design. One of the most impactful effects is the text stroke (or outline). In the past, this required Photoshop. Today, CSS gives us three ways to do it, but browser compatibility can still be confusing.
Table of Contents
- CSS Text Outline: The Guide to text-stroke, WebKit & SVG
- ⚡ TL;DR: Quick Copy Snippets
- Method 1: The Quick Way (-webkit-text-stroke)
- The "moz-text-stroke" Myth
- The Problem: "Eating" the Text
- Method 2: The "Old School" Shadow Hack
- Method 3: The "Gold Standard" (SVG)
- Advanced: The "Clone" Trick (::before)
- Summary: Which one should I use?
- Related Quiz - CSS Flexbox & Grid Mastery
⚡ TL;DR: Quick Copy Snippets
If you just want the code, here are the three best methods.
1. The Modern Standard (Works in Chrome, Firefox, Safari) Note: Yes, you must use the -webkit- prefix even for Firefox.
.stroke-text {
color: white; /* Fill color */
-webkit-text-stroke: 2px black; /* Width and Color */
}
2. The "Outline Only" (Transparent Fill)
.outline-text {
color: transparent;
-webkit-text-stroke: 2px red;
}
3. The "Perfect" Vector Stroke (SVG) Use this if the CSS stroke looks messy or "eats" the text.
svg text {
fill: white;
stroke: black;
stroke-width: 4px;
paint-order: stroke fill; /* Draws stroke BEHIND the text */
}
Advertisement
Method 1: The Quick Way (-webkit-text-stroke)
The most direct way to create a text stroke in CSS is using the text-stroke property. It's a shorthand for two properties: text-stroke-width and text-stroke-color.
The "moz-text-stroke" Myth
If you are searching for moz-text-stroke to make this work in Firefox, stop searching. It does not exist.
Firefox supports the standard non-prefixed property, but for maximum compatibility across all browsers (including legacy ones), the industry standard is to use the -webkit- prefix. This works in Firefox, Chrome, Edge, and Safari.
.simple-stroke {
font-family: sans-serif;
font-size: 6rem;
font-weight: 900;
color: white;
-webkit-text-stroke: 2px black;
}
The Problem: "Eating" the Text
The main downside of text-stroke is that the stroke is drawn centered on the edge of the letter. This means half the stroke is outside, and half is inside.
If you have a thin font and a thick stroke, the stroke will "eat" your letter, making it look thin and ugly.
❌ The limit: Generally, avoid strokes thicker than 2px when using this method.
Advertisement
Method 2: The "Old School" Shadow Hack
Before text-stroke was supported, developers used text-shadow to simulate an outline. This is still useful if you need to support ancient browsers (like Internet Explorer) or if you want a softer, glowing outline.
How it works: We create four (or more) shadows, each offset by 1 pixel in different directions.
.shadow-stroke {
color: #f1c40f;
text-shadow:
-1px -1px 0 #000, /* top left */
1px -1px 0 #000, /* top right */
-1px 1px 0 #000, /* bottom left */
1px 1px 0 #000; /* bottom right */
}
Pros:
- The stroke sits behind the text, so it never "eats" the letters.
- Works on 100% of browsers.
Cons:
- It looks "pixelated" or fuzzy at corners.
- It requires a lot of code for thicker strokes.
Method 3: The "Gold Standard" (SVG)
If you want a professional, crisp, pixel-perfect stroke that works at any size (even huge headlines), SVG is the only correct choice.
Unlike CSS borders, SVG gives us the magical paint-order property. This allows us to tell the browser: "Draw the stroke first, then paint the text on top of it."
This ensures the stroke is always strictly on the outside.
<svg width="100%" height="150">
<text x="50%" y="50%" dy=".35em" text-anchor="middle" class="svg-text">
SVG STROKE
</text>
</svg>
.svg-text {
font-family: 'Bangers', cursive;
font-size: 7rem;
fill: white; /* Text Color */
stroke: black; /* Stroke Color */
stroke-width: 6px; /* Thick Stroke! */
/* The Secret Sauce */
paint-order: stroke fill;
}
Why this wins:
- Scalable: You can have a 20px stroke and the text remains perfectly readable.
- Gradients: You can apply gradients to the stroke itself (using SVG defs).
- Animation: You can animate the stroke (the famous "self-drawing line" effect).
Advertisement
Advanced: The "Clone" Trick (::before)
If you can't use SVG but hate how text-stroke eats your letters, there is a CSS-only workaround using the data-text attribute.
We basically clone the text, put it behind the original, and add the stroke to the clone.
Step 1: HTML Add the text twice, once inside the tag and once in a data attribute.
<h1 class="clone-stroke" data-text="HELLO">HELLO</h1>
Step 2: CSS
.clone-stroke {
position: relative;
color: white; /* The clean fill on top */
z-index: 1;
}
.clone-stroke::before {
content: attr(data-text);
position: absolute;
left: 0;
top: 0;
z-index: -1; /* Sit behind */
/* The thick stroke */
-webkit-text-stroke: 8px red;
}
Summary: Which one should I use?
- For simple, thin outlines: Use Method 1 (
-webkit-text-stroke). It works in Firefox/Chrome/Safari. - For thick, bold headlines: Use Method 3 (SVG). It is the cleanest and most professional look.
- For ancient browser support: Use Method 2 (Shadows).
Stop searching for moz-text-stroke—it's a myth! Stick to -webkit- and you are good to go.
Related Quiz - CSS Flexbox & Grid Mastery
CSS Flexbox & Grid Mastery
Test your knowledge and reinforce what you've learned in this article.
Md Nasim Sheikh
Software Developer at softexForge