Module 3: Box Model & Spacing
Backgrounds and Borders: Colors, Images, Gradients and Rounded Corners
How backgrounds paint, how to size and layer them, how gradients really work, and the border and radius details that cause surprises.
Backgrounds and borders are where the page starts to look like a design. They are also easy to get subtly wrong, because the shorthand properties reset more than you expect and the defaults are not always what you want.
What a background covers#
A box's background paints under its content and padding, and under its border by default, but never under its margin.
┌ margin (transparent) ─────────────────┐
│ ┌ border ───────────────────────┐ │
│ │ ┌ padding ──────────────────┐ │ │
│ │ │ content │ │ │
│ │ └───────────────────────────┘ │ │
│ └───────────────────────────────┘ │
└───────────────────────────────────────┘
background paints from the border edge inward (background-clip: border-box)
You can change where it stops with background-clip: border-box (default), padding-box or content-box. A value of text paints the background only inside the glyphs, for gradient text:
.gradient-text {
background: linear-gradient(90deg, #0b5fff, #7c3aed);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
}
Background properties#
.hero {
background-color: #0b1220;
background-image: url("hero.jpg");
background-repeat: no-repeat;
background-position: center;
background-size: cover;
}
background-coloris the fallback layer and shows behind images, and while images load.background-imageacceptsurl()and gradients.background-repeattiles by default. Almost always you wantno-repeat, except for patterns.background-positionaccepts keywords (top left,center), lengths and percentages.background-sizeis the one people forget. Without it, the image shows at its natural size, probably cropped, in a corner.coverscales the image until it fills the whole box, and crops overflow.containscales it until it fits entirely, and may leave empty space.- You can also give lengths, like
200px auto.
background-attachment: fixedpins the image to the viewport for a parallax feel. It performs poorly on mobile browsers and is often ignored there.
Shorthand#
.hero {
background: #0b1220 url("hero.jpg") center / cover no-repeat;
}
Position and size are separated by a slash. Because it is a shorthand, anything you omit is reset to its default, which is how a later background: #111 wipes out an image set earlier. Use background-color when you want to change only the color.
Background vs img#
If the image is content, meaning the page would be less informative without it, use an <img> with alt text. If it is decoration, use a CSS background. A CSS background has no alt text, and search engines and screen readers ignore it.
Gradients#
A gradient is an image generated by the browser, not a color. That is why it goes in background-image (or the background shorthand), and why background-color: linear-gradient(...) does nothing.
.a { background: linear-gradient(to right, #0b5fff, #7c3aed); }
.b { background: linear-gradient(135deg, #0b5fff 0%, #7c3aed 100%); }
.c { background: radial-gradient(circle at top left, #fde68a, transparent 60%); }
.d { background: conic-gradient(#0b5fff, #7c3aed, #0b5fff); }
You can create hard edges by putting two color stops at the same position:
.stripe {
background: linear-gradient(
90deg,
#0b5fff 0 50%, /* blue from 0 to 50% */
#f5a524 50% 100% /* amber from 50% to 100% */
);
}
Layering several backgrounds#
Comma-separate layers. The first one is on top.
.card-hero {
background:
linear-gradient(to top, rgb(0 0 0 / 0.6), transparent 50%), /* top layer: dark fade */
url("photo.jpg") center / cover; /* bottom layer: image */
background-color: #222; /* fallback */
}
This is the standard way to make white text readable on top of a photo. The gradient darkens the bottom of the image where the text sits.
Borders#
A border needs three things: width, style and color. If you skip the style, there is no border at all, because the default style is none.
.box { border: 2px solid #333; } /* all sides */
.box { border-bottom: 1px dashed #aaa; } /* one side */
.box { border-width: 1px 0; } /* top & bottom only */
Styles worth knowing: solid, dashed, dotted, double, none. If color is omitted, the border uses currentColor.
Outline is not a border#
.btn:focus-visible {
outline: 3px solid #f5a524;
outline-offset: 2px;
}
An outline is drawn outside the border edge, does not take up space, does not change the layout, and does not follow border-radius perfectly in older browsers (modern ones do follow it). It is the right tool for focus rings, because adding a border on focus would shift the layout.
Rounded corners#
.card { border-radius: 12px; }
.pill { border-radius: 999px; } /* a huge value always makes a pill */
.circle { width: 80px; height: 80px; border-radius: 50%; }
.leaf { border-radius: 24px 0 24px 0; }
.blob { border-radius: 60% 40% 30% 70% / 60% 30% 70% 40%; }
Radius values follow the same order as margin shorthand, but start from the top-left and go clockwise. A percentage is relative to the box's own size on each axis, so 50% on a non-square element produces an ellipse, not a circle. For a circle you need a square element.
A rounded box clips its own background and border, but not its children. If you want an image child to follow the rounded corners, add overflow: hidden to the parent, or round the image too.
Common mistakes#
- Setting
background-imagewithoutbackground-size, then wondering why the picture looks cropped or tiny. - Writing a border without a style.
border: 2px #333shows nothing. - Using a shorthand and wiping out other background layers.
- Putting a gradient in
background-color. - Using
border-radius: 50%on a rectangle and getting an oval. - No fallback
background-colorbehind an image, so white text becomes unreadable while the image loads. - Replacing a content image with a CSS background and losing alt text.
Practice#
- Make a hero section with a photo and a dark gradient overlay on top, and white text that remains readable. Add a
background-colorfallback. - Create a card with a 1px border, a pill-shaped badge and a circular avatar, all using only
border-radiusand a size. - Build a two-color striped background with hard stops, and then use
repeating-linear-gradientto make diagonal stripes. - Make gradient text for a heading and test what happens when
background-clip: textis unsupported, then add a fallback color.