What three parts does a border need?
A border has a width, a style and a colour. The border shorthand takes all three in any order, separated by spaces: border: 2px solid #2f6b3c. The width is a length such as 1px or 0.25rem, or one of the keywords thin, medium and thick. The colour is any CSS colour, and if you leave it out the border uses the element's text colour, currentColor.
The style is the part people forget, and it is the most important one. The default border-style is none, and a border with style none is not drawn and has a computed width of zero. Writing border: 2px #333 gives you nothing on screen. Every visible border needs a style keyword.
The styles you will use are solid, dashed and dotted. There is also double, which draws two thin lines and needs at least 3px of width to show both, plus groove, ridge, inset and outset, which fake a bevel with lighter and darker shades. The bevel styles look dated, and their exact shading differs between browsers, so most sites avoid them.
.notice {
border: 2px solid #2f6b3c;
}
.coupon {
border: 2px dashed #b4541a;
}

How do you set one side or one property at a time?
Every border is really twelve longhand properties: a width, a style and a colour for each of the four sides. You can set them at three levels. border-top, border-right, border-bottom and border-left take the same three values as border for a single side. border-width, border-style and border-color set one property on every side, and accept one to four values in the same top, right, bottom, left order as padding. The fully split names such as border-left-color set one property on one side.
A common pattern is a full border followed by a single override. Writing border: 1px solid #ddd and then border-left: 4px solid #2f6b3c gives a quiet box with a strong coloured stripe on the left, which works well for callouts and quotes. The order matters: the shorthand resets all four sides, so it has to come first.
Single-side borders also make good dividers. A border-bottom on each item in a list draws lines between rows without any extra elements. Add border-bottom: none to the last item, or use border-top on every item except the first, when you do not want a line under the final row.
For the logical direction, border-inline-start and border-block-end follow the writing mode. In a right-to-left language the inline-start side is on the right, so a quote stripe set with border-inline-start flips with the text.
.tip {
border: 1px solid #dddddd;
border-left: 4px solid #2f6b3c;
padding: 12px 16px;
}
.rides li {
border-bottom: 1px solid #e5e5e5;
}How does border-radius round corners?
The border-radius property rounds the corners of the box. It rounds the background and the border together, so it works on boxes with no border at all. One value rounds all four corners equally: border-radius: 8px. Four values go clockwise from the top left: top-left, top-right, bottom-right, bottom-left. Two values set the top-left and bottom-right corners with the first, and the other two with the second.
Each corner also has its own longhand, such as border-top-left-radius. That is handy for tabs, which round only the top two corners, or for a chat bubble that keeps one sharp corner pointing at the speaker.
Rounding does not clip the content. Text sits inside the padding, so it rarely reaches a corner, but an image that fills a rounded card will poke out at the corners. Put overflow: hidden on the card, or give the image its own matching radius on the top corners.
A radius can also take two lengths separated by a slash, border-radius: 40px / 20px, which gives elliptical corners with a different horizontal and vertical curve. You will rarely need it, but it explains the odd slash when you see one in generated code.
.tab {
border-radius: 8px 8px 0 0;
}
.bubble {
border-radius: 16px 16px 16px 2px;
}How do you make circles and pill shapes?
Percentages in border-radius are measured against the box itself: horizontal curves use the width and vertical curves use the height. A square element with border-radius: 50% becomes a circle. This is the standard way to make round profile photos, dots and icon buttons. Give the element equal width and height, and for photos add object-fit: cover so a wide picture fills the circle without stretching.
On a rectangle, 50% gives an ellipse, which is usually not what you want for a button. For a pill, with straight sides and fully round ends, use a very large length such as 999px. When two adjacent radii would add up to more than the side they share, the browser scales them down until they fit. The result is that each short end becomes a perfect semicircle at any width and any font size, and the badge stays a pill as its text changes.
A tag, a badge, a filter chip and a toggle track are all pill shapes. The 999px trick works for all of them, and you never have to recalculate when the padding or text size changes.
.avatar {
width: 96px;
height: 96px;
object-fit: cover;
border-radius: 50%;
}
.chip {
padding: 4px 12px;
border-radius: 999px;
}How is outline different from border?
An outline looks like a border but follows different rules. It takes no space in the layout, so adding or removing one never moves anything. It draws on top of neighbouring content if it is wide enough to reach it. It has no per-side longhands: you get the same line on all four sides. Since 2021 the outline follows border-radius in every current browser, so a rounded button gets a rounded outline.
The outline shorthand takes the same width, style and colour values as border. The extra property is outline-offset, which moves the outline away from the border edge with a positive value or inside it with a negative one. A 2px or 3px offset leaves a clear gap that makes the ring easy to see even when the button has a border of a similar colour.
Because outlines take no space, they are ideal for debugging. Adding outline: 1px solid red to a suspect element shows exactly where its box is without nudging the layout, which a temporary border would do.
.btn:focus-visible {
outline: 3px solid #1d4ed8;
outline-offset: 3px;
}Why must you never delete focus outlines?
Browsers draw an outline around the element that has keyboard focus. People who use a keyboard, a switch device or voice control rely on that ring to know which link or button will activate. Removing it with outline: none or outline: 0 leaves them guessing, and it fails WCAG success criterion 2.4.7, Focus Visible.
Many old resets and a lot of AI-generated CSS still include *:focus { outline: none; } because the default ring looked out of place in a design. If you want a different look, restyle it instead of removing it. The :focus-visible pseudo-class matches when the browser decides the user needs a visible indicator, which in practice means keyboard focus, and not after a mouse click on a button. Style the ring there with a colour that contrasts with both the button and the page.
To test, click in the address bar and press Tab repeatedly. You should always be able to see where you are. If focus disappears at any point, search your CSS for outline: none and outline: 0.
/* Replace the default ring, never remove it */
a:focus-visible,
button:focus-visible {
outline: 3px solid #1d4ed8;
outline-offset: 2px;
}How do borders behave on images?
An <img> is a replaced element, and it takes borders, padding and radius like any box. A border on an image draws around the picture, and padding adds a gap between the picture and the border that shows the image's background colour. That gives a passe-partout look with padding: 6px, background-color: #fff and a thin border.
Watch the size. Under the default content-box, a 300px image with a 4px border takes 308px. With a box-sizing: border-box reset, the same image stays 300px and the picture itself shrinks to 292px. Either is fine as long as you know which one you have.
Images inside links used to get a blue border in old browsers, which is why legacy resets contain img { border: 0; }. No current browser does this, so that line is safe to delete. If you see a thin line under a linked image, that is the link's text underline or the gap for text descenders, fixed with display: block on the image.
.print {
padding: 6px;
background-color: #ffffff;
border: 1px solid #cccccc;
}What do AI tools get wrong with borders?
The most frequent slip is a border with no style, such as border: 1px #e5e5e5, often produced when a tool splits a design token into width and colour and forgets the third part. The second is outline: none on focus with no replacement. The third is a hover state that adds a border where there was none, which makes the element grow by the border width and nudges everything after it. Give the element a transparent border of the same width in its resting state, or use an outline or box-shadow for the hover effect.
Also check that a rounded card with a full-bleed image either clips with overflow: hidden or rounds the image too. In DevTools, the Computed tab lists every border longhand, which shows quickly whether border-top-style is really none.
.card {
border: 2px solid transparent;
}
.card:hover {
border-color: #2f6b3c;
}Field notes
- A border needs a width, a style and a colour to show up.
- You can set borders on one side or one property at a time.
border-radiusrounds the background and the border together.- Keep focus outlines visible, since keyboard users rely on them.
Easy to get wrong
Without a style keyword the style stays none, so the border is not drawn and takes no space.
Deleting the focus ring hides where keyboard users are. Restyle it so it suits the design and stays visible.
On a wide rectangle 50% makes an ellipse. A large fixed length gives straight sides and round ends at any width.
Adding a border only on hover makes the element 2px taller and shifts the content below. Reserve the space with a transparent border.
Questions people ask
Why does my rounded card show square image corners?
The radius rounds the card's own background and border, and child content is allowed to spill past the curve. Add overflow: hidden to the card or give the image a matching radius.
Can I put a gradient on a border?
Not with border-color, which only takes plain colours. Use border-image with a gradient, or layer two backgrounds with background-clip. Note that border-image ignores border-radius.
Does outline follow border-radius?
Yes, in every current browser. Older versions of Safari and Chrome drew square outlines around rounded boxes, which is why some old tutorials use box-shadow for focus rings.
What is the difference between outline: none and outline: 0?
Both remove the outline. outline: 0 sets the width to zero and outline: none sets the style to none. Neither is acceptable on focus unless you add another visible indicator.
Which is better for dividers, border or hr?
Use <hr> when the break has meaning, such as a change of topic. Use a border when the line is decoration, such as rules between list rows.