CSS Tutorial / CSS Borders, Rounded Corners, and Shadows
CSS borders define a box's visible edge, border-radius rounds its corners, and box-shadow adds a shadow without increasing its layout size. Shadows can still be clipped by an ancestor's overflow settings, and a rounded border does not automatically crop every child.
Set border width, style, and color
.card { border: 2px solid #3d6b89; }
The border shorthand combines width, style, and color. solid draws a continuous line, dashed draws dashes, and dotted draws dots. A none style suppresses the expected border even if a width and color are present. Use border-bottom or border-block-end when only one edge needs a border. For further detail, see The CSS Box Model: Content, Padding, Border, and Margin.
| Property | Box size effect | Main uses |
|---|---|---|
| border | In content-box, it is added outside, and in border-box, it is included within the specified size. | border of element |
| outline | Does not increase layout space | Shows outlines around focused elements |
| box-shadow | Does not increase layout space | Shadows and Visual Depth |
With a fixed border-box width, increasing border thickness reduces the inner space while keeping the outer width. A decorative border or shadow has a different role from the focus outline that identifies the current keyboard target. Keep that indicator visible. See MDN: border.
Compare corner lengths and percentages
.round { border-radius: 12px; }
.circle { width: 80px; height: 80px; border-radius: 50%; }
.oval { width: 160px; height: 80px; border-radius: 50%; }
A length value such as 12px specifies the corner radius. You can give different values to the four corners, but compare them to one value first. If you apply 50% to a box with the same width and height, it will look like a circle, and if the horizontal and vertical sizes are different, it will look like an ellipse. The horizontal radius of the percentage is based on the width, and the vertical radius is based on the height.
The rounded corners of the parent do not automatically crop the child image. Choose between giving the border-radius to the image itself or cutting the overflow from the parent, depending on your purpose. If you add hidden to the parent, the child's shadow/focus display may also be cut off at the border. The following comparison distinguishes which box is being cut. You can check the radius calculation in MDN's border-radius description.
Read the shadow values
.shadow { box-shadow: 0 8px 24px 4px rgb(0 0 0 / 16%); }
| value | meaning | Results to change |
|---|---|---|
| first 0 | move horizontally | Positive numbers move to the right, negative numbers move to the left |
| second 8px | vertical movement | Positive numbers move downward, negative numbers move upward. |
| third 24px | blur radius | Closer to 0, it becomes clearer and larger, it becomes softer. |
| fourth 4px | spread radius | Positive numbers increase the shadow size, negative numbers decrease it. |
| rgb(0 0 0 / 16%) | Color and Opacity | The degree to which it is distinguished from the background varies. |
The first two lengths are required and blur and spread can be omitted. The blur radius cannot be negative. Adding inset is the inner shadow, the default is the outer shadow. There is also a way to add multiple shadows, but first check by changing the movement and size of one shadow separately.
A shadow does not reserve layout space. It will not push away a following card by the amount of its blur or spread. Large shadows can obscure nearby content, so supply actual spacing with margins or layout gaps when needed. See MDN: box shadow.
Find the ancestor that clips a shadow
.frame { padding: 12px; overflow: visible; }
.frame.clip { overflow: hidden; }
.frame .card { box-shadow: 0 18px 20px 8px rgb(0 0 0 / 25%); }
The last two cards have separate .frame parents. Their child shadows are identical, but one parent allows visible overflow and the other clips it. The shadow extends beyond the 12px parent padding, so the hidden-overflow version cuts it at the parent boundary. Inspect that ancestor when diagnosing a clipped shadow. See CSS Overflow, Long Text Wrapping, and Ellipsis.
Don't confuse giving yourself overflow: hidden with having the parent element cut off its child's shadow. This exercise is a situation where a parent cuts off the outer shadow of a child card. If the shadow is not visible on the actual page, you should check not only the value of the card itself, but also the overflow and border of the parent element.
Run the example and compare changes
Save the code below as UTF-8 in borders.html. Comparisons of borders, rounded corners, outer shadows, inner shadows, circles and ellipses, and truncation are all included.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Comparing borders, corners, and shadows</title>
<style>
* { box-sizing: border-box; }
body { margin: 24px; color: #333; font: 16px/1.6 sans-serif; background: #f6f8fa; }
.card { width: 100%; max-width: 320px; margin-block: 24px; padding: 20px; background: white; }
.border { border: 2px solid #3d6b89; }
.round { border: 2px solid #3d6b89; border-radius: 12px; }
.shadow { border-radius: 12px; box-shadow: 0 8px 24px 4px rgb(0 0 0 / 16%); }
.inset { box-shadow: inset 0 0 12px 2px rgb(0 0 0 / 20%); }
.shape { width: 80px; height: 80px; margin-block: 16px; border-radius: 50%; background: #6eb898; }
.oval { width: 160px; }
.frame { width: 100%; max-width: 320px; padding: 12px; margin-block: 24px; background: #dce8f1; overflow: visible; }
.frame .card { margin: 0; max-width: none; height: 100px; box-shadow: 0 18px 20px 8px rgb(0 0 0 / 25%); }
.clip { overflow: hidden; }
</style>
</head>
<body>
<h1>Card boundaries and shadows</h1>
<div class="card border">Card with a border only</div>
<div class="card round">Border and rounded corners</div>
<div class="card shadow">Outer shadow</div>
<div class="card inset">Inset shadow</div>
<h2>50% Edges: Circles and Ovals</h2><div class="shape" role="img" aria-label="80×80 won"></div><div class="shape oval" role="img" aria-label="160×80 ellipse"></div>
<h2>Parent: overflow: visible</h2><div class="frame"><div class="card">Child shadow visible outside the parent</div></div>
<h2>Parent: overflow: hidden</h2><div class="frame clip"><div class="card">Child shadow clipped at the parent boundary</div></div>
</body>
</html>
- Change the thickness of the .border from 2px to 8px. In wide windows, make sure the outer width is maintained and the inner space is reduced, then return it to 2px.
- Change the width of the .shape from 80px to 160px. Make sure the circle becomes an ellipse if you keep the height at 80px. Restore to original width.
- Change the horizontal shift of the .shadow to 20px and the vertical shift to -8px. Keep the blur 24px and compare only the direction of movement. Next, change the blur to 0, compare it to the sharp edge, and then return it to its original value.
- Change spread 4px to -4px. Notice if the shadow size decreases. When I change the hidden to visible in the second .frame, I check if the shadow outside the parent is visible again and restore it to hidden.
If the shadow is blurry, check the color opacity and background contrast, and if only one side is cut off, check the parent's border and overflow. If the child content inside the corner protrudes, we also compare the method of giving rounded corners to the child itself. Rather than increasing effectiveness, base your judgment on keeping content clear and easy to manipulate.










