Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
Use box-shadow to cast a shadow around an element’s box, and text-shadow to add a shadow to its text. Both properties let you control direction, softness, size, and color; neither changes the element’s layout dimensions. Here’s how to write the CSS, layer effects, and avoid common clipping and legibility problems.
Add a shadow to an element with box-shadow
The smallest useful declaration has horizontal and vertical offsets, followed by an optional blur radius, optional spread radius, and color:
.card {
box-shadow: 0 8px 20px 0 rgb(0 0 0 / 0.18);
}
The shadow sits outside the element because this declaration does not include inset. The values are illustrative: the right amount depends on the element, background, and visual system around it.
Free tools Windows power users keep installed
One-click scans. No signup required.
What each value controls
- Horizontal offset: moves the shadow left or right. A positive value moves it right; a negative value moves it left.
- Vertical offset: moves it down or up. A positive value moves it down; a negative value moves it up.
- Blur radius: softens the edge. A larger blur makes the shadow more diffuse; omitting it gives a sharp-edged shadow.
- Spread radius: expands or contracts the shadow’s extent. Positive spread grows it; negative spread shrinks it. This value is optional.
- Color: sets the shadow hue and opacity. A translucent dark color is a common starting point for a subtle raised-card effect.
The blur and spread are different controls: blur softens an edge, while spread changes the shadow’s apparent size. You can omit optional values, but offsets and a color are needed for a useful declaration.
#1 Best Overall
- HTML CSS Design and Build Web Sites
- Comes with secure packaging
- It can be a gift option
Choose an outset or inset shadow
By default, a box shadow appears outside the element’s frame. Add inset to draw it inside the padding box, above the background and below the content. An inset shadow can suggest a recessed surface or provide subtle inner shading.
.pressed {
box-shadow: inset 0 2px 5px rgb(0 0 0 / 0.2);
}
Here, the positive vertical offset places the darker shading toward the bottom. Change the offsets and color to suit the effect you want; there is no single set of values that works for every interface.
Layer multiple shadows
Separate shadow layers with commas. The first listed shadow is painted on top of the next one, so order matters when layers overlap.
The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →.card {
box-shadow:
inset 0 1px 2px rgb(255 255 255 / 0.7),
0 8px 20px rgb(0 0 0 / 0.18);
}
This example places a light inset layer above an outer shadow. Each layer can have its own offsets, blur, spread, color, and inset setting. Multiple layers are still visual effects; they do not reserve extra layout space.
Use a shadow as a ring carefully
An all-zero offset and blur with a spread can create a sharp outline-like ring. For example, box-shadow: 0 0 0 2px blue; expands a solid shadow by two pixels. If the intent is to communicate an outline or boundary, consider whether outline or border expresses it more clearly in your interface.
Rank #2
Make rounded shadows follow the element
If an element has border-radius, the box shadow follows its rounded corners. The shadow is associated with the element’s frame, so you usually do not need to apply a matching radius to the shadow separately.
.card {
border-radius: 12px;
box-shadow: 0 8px 20px rgb(0 0 0 / 0.18);
}
Check the rendered result against the actual background. A shadow that looks soft on a light canvas may look too heavy or disappear on a different surface.
Use text-shadow for text
text-shadow styles glyphs, not the surrounding element box. It takes horizontal and vertical offsets, an optional blur radius, and a color; it has no spread-radius or inset value.
.title {
text-shadow: 1px 2px 4px rgb(0 0 0 / 0.45);
}
As with box shadows, multiple text shadows are comma-separated, and the first one is painted on top:
.title {
text-shadow:
0 1px 1px rgb(255 255 255 / 0.8),
0 3px 6px rgb(0 0 0 / 0.45);
}
A text shadow does not change the box model or the text’s layout dimensions. Judge legibility against the real background: a shadow alone does not guarantee accessible contrast, and a heavy effect can make letterforms harder to read.
Rank #3
- Brand: Wiley
- Set of 2 Volumes
- A handy two-book set that uniquely combines related technologies Highly visual format and accessible language makes these books highly effective learning tools Perfect for beginning web designers and front-end developers
Keep shadows from colliding or being clipped
Shadows do not take up layout space. An outer shadow may visually overlap neighboring content even though the elements’ measured boxes do not overlap. Allow room around a component when the effect needs it, and inspect nearby content at the sizes where the page will be used.
Recommended Free Tools
A shadow can also be cut off by a containing boundary or the viewport. If an effect seems to disappear abruptly, inspect the rendered composition and the ancestors around the element; the shadow may extend beyond a boundary that clips overflowing content. Provide visual room where possible rather than assuming the shadow will expand the container for you.
Tune the effect in a predictable order
- Choose the property. Use
box-shadowfor a component’s frame andtext-shadowfor text itself. - Set direction. Adjust the horizontal and vertical offsets until the shadow appears to come from the intended direction.
- Set softness and extent. Increase blur for a softer edge; adjust spread when the shadow needs to cover a larger or smaller area.
- Adjust color and opacity. Evaluate the shadow on the actual surface rather than choosing a color in isolation.
- Check layering and boundaries. Confirm comma-separated layer order and look for overlap or clipping around the component.
- Check text legibility. If you use
text-shadow, verify that the text remains easy to read against its background.
Keep the final values consistent with the rest of the design rather than treating a sample declaration as a universal preset.
Compatibility and syntax
The basic, unprefixed box-shadow property is widely available and well established; MDN reports browser availability since July 2015. That broad support is not a guarantee that every browser implements every part of newer syntax. If a project must support a specific legacy browser or relies on newer syntax, check compatibility for that target. For contemporary projects, use the unprefixed property unless your support requirements call for something else.
Troubleshooting CSS shadows
The shadow is missing
Check that the element matches the selector and that the declaration is not overridden. Confirm that the offsets, color, and opacity produce a visible effect against the page background. Also inspect whether a containing boundary clips the shadow.
Rank #4
The shadow appears on the wrong side
Look at the signs of the horizontal and vertical offsets. Positive horizontal values move right and positive vertical values move down; negative values move left and up.
The effect looks too fuzzy or too large
Reduce blur to sharpen the edge. If the shadow extends too far even with a suitable blur, adjust spread separately. Revisit opacity and color if the size is right but the effect still feels too strong.
A card’s shadow covers nearby content
The shadow does not add layout space. Add visual separation through the surrounding layout where appropriate, and inspect the parent and viewport for clipping boundaries if the shadow is cut off.
The text is harder to read
Reduce the shadow’s strength or blur, or remove it. Check the text against its actual background; a text shadow is not a substitute for sufficient contrast.
Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Clear out junk files and repair common Windows errorsFree Scan →Check the rendered result in a browser
CSS values are easiest to tune by viewing the component in the page where it will appear. A browser’s developer tools let you edit the declaration and see the result; when you need a saved view of a web page, a screenshot can preserve the rendered appearance for review.
Best Value
Or skip the browser setup
For a page you can access by URL, ScreenshotNeo returns a screenshot in one GET request. Replace the example URL with the page you want to inspect and provide your API key:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
See the ScreenshotNeo API documentation for request options. ScreenshotNeo removes cookie and consent banners, newsletter popups, and chat widgets before capture; those steps can each be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers report the page verdict and billing status. Its MCP server offers take_screenshot, get_page_info, and capture_pdf tools for AI agents and other MCP clients. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots.
Sign up for ScreenshotNeo free to try the monthly allowance with no card.
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Clear out junk files and repair common Windows errors3Fix the driver behind crashes, sound loss and screen glitchesOther runnable request examples
These examples request a screenshot of the same sample page. Replace the URL and API key for your use. The examples write the response body to a file; consult the API documentation for supported parameters and response details.
Python
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
timeout=90,
)
open("shot.webp", "wb").write(r.content)
Node.js
const q = new URLSearchParams({
access_key: 'YOUR_API_KEY',
url: 'https://stripe.com'
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
Keep API keys private rather than placing them in public client-side code. For details on response handling and available options, use the ScreenshotNeo docs.
Frequently Asked Questions
Does box-shadow support a negative spread radius?
Yes. A negative spread contracts the shadow’s extent; it does not change the element’s dimensions.
Can I combine an inset shadow and an outer shadow?
Yes. Put both in the comma-separated box-shadow list, with the layer you want painted on top first.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

