CSS Border Table
| Piece | What it does | Field note |
|---|---|---|
border: 1px solid #333 | The three-part shorthand | Width, style, color - style is REQUIRED (none erases the border) |
border-radius | Round the corners | 50% on a square = circle; per-corner lists go clockwise from top-left |
border-width per side | border-top-width etc. | The shorthand resets all four - longhands for mixed sides |
border-style values | solid/dashed/dotted/double | hidden vs none: hidden wins over collapsed-table conflicts |
transparent border | border: 1px solid transparent | Reserves layout space invisibly - the hover-without-jump trick |
outline vs border | Outside, no layout | Outline draws over neighbors, no box growth - focus rings live here |
border-image | Image as the frame | slice/stretch mechanics - niche but zero-extra-element framing |
logically: border-inline-start | Flow-relative border | The start side follows reading direction - pairs with logical properties |
The border shorthand is three decisions (width, style, color) applied to all four sides at once - and style is the load-bearing one: border: 1px #333 renders NOTHING, because the default style is none. Width and color only matter once a style exists.
Bottom line: the transparent-border trick is the layout saver - border: 1px solid transparent reserves the exact pixels a hover border will occupy, so buttons and cards stop jumping when the border appears. Outline is the no-layout sibling: it draws outside the box without moving anything, which is why focus rings belong to outline, not border.
The honest part: border-radius composes - one value rounds all corners, but the per-corner syntax goes clockwise from top-left, and the elliptical slash syntax (border-radius: 50% / 20%) makes ovals. An element that is square with radius 50% is the entire circle recipe.
How to use
- Stop hover jumps: give interactive elements border: 1px solid transparent in the rest state, then recolor on hover - the layout box never changes size.
- Focus with outline: outline: 2px solid + outline-offset: 2px on :focus-visible - outside the box, no layout shift, and offset gives it air.
- Mix sides with longhands: border + border-bottom: none for separators-in-a-row - the shorthand first, longhand overrides second, cascade does the rest.
Frequently asked questions
Why doesn't my border show even though I set width and color?
The style is missing - it defaults to none, and none means no border regardless of width or color. border: 1px solid #333 works; border: 1px #333 paints nothing. This bites twice in practice: the shorthand written without a style keyword, and a stylesheet that sets border: none somewhere with higher specificity, silently erasing styled borders - the longhand border-style: solid is the surgical revival. The shorthand resets all three components, which is why 'border: red' also produces no border: it resets style to initial (none) too.
How is outline different from border, and when should each be used?
Border is part of the box model: it takes layout space, pushes neighbors, participates in width calculations (unless box-sizing says otherwise). Outline paints OVER the surrounding content without affecting layout at all - it can overlap neighbors freely. That difference assigns their jobs: borders are structural (separators, card edges, input frames) and participate in size; outlines are annotation (focus rings, validation highlights, debug outlines) that must never shift the page. The accessibility pairing: :focus-visible with a 2px outline and a small outline-offset is the standard keyboard focus indicator - moving focus to a border change instead would make every focus click jiggle the layout.
What is the per-corner radius syntax actually doing?
It maps clockwise from the top-left corner: border-radius: 8px 0 0 8px rounds only the left side (top-left, top-right, bottom-right, bottom-left). Two values mean corners diagonal-paired, four values walk the corners individually. The slash syntax adds elliptical control - the value before the slash is horizontal radii, after is vertical: border-radius: 50% / 20% makes an oval by curving more horizontally than vertically. And the circle recipe remains the classic: a square element with border-radius: 50% - the radius is a percentage of the box, so any square becomes a perfect circle.
When do logical border properties earn their keep?
Whenever the border marks the reading direction rather than the screen direction: border-inline-start draws on the leading side (left in English, right in Arabic), border-block-end sits under the text flow's end. Blockquotes, active nav indicators and list markers are flow-relative decorations - an RTL translation flips them for free, while border-left keeps pointing at the same physical side and breaks the design. The migration rule from the logical properties playbook applies: new components use the logical names, existing screen-locked decoration stays physical until touched.