CSS 강좌 / 테두리, 둥근 모서리, 그림자 만들기
CSS의 border는 경계선, border-radius는 모서리의 둥근 정도, box-shadow는 박스의 그림자를 정합니다. 테두리는 박스 크기 계산에 영향을 주고 그림자는 주변 공간을 자동으로 확보하지 않습니다. 경계를 구분하는 목적에 맞게 선택하고 키보드 포커스 표시를 함께 유지해야 합니다.
테두리의 두께·선 종류·색상 지정하기
.card { border: 2px solid #3d6b89; }
border 축약 속성으로 두께, 선 종류, 색을 함께 지정할 수 있습니다. solid는 실선, dashed는 점선 형태, dotted는 점으로 된 선입니다. 선 종류가 none이면 두께나 색을 적어도 기대한 테두리가 나타나지 않을 수 있습니다. 한쪽 경계만 필요하면 border-bottom 같은 물리 방향 속성이나 border-block-end 같은 논리 속성을 사용합니다.
| 속성 | 박스 크기 영향 | 주요 용도 |
|---|---|---|
| border | content-box에서는 밖에 더해지고 border-box에서는 지정 크기 안에 포함 | 요소의 경계 |
| outline | 레이아웃 공간을 늘리지 않음 | 포커스 등 주변 윤곽 표시 |
| box-shadow | 레이아웃 공간을 늘리지 않음 | 그림자와 시각적 깊이 |
border-box 카드의 테두리를 두껍게 바꾸면 바깥 너비는 유지되지만 안쪽 공간이 줄어듭니다. 테두리와 그림자를 추가해도 기본 포커스 윤곽선을 없애지 마세요. 장식 경계가 있는 것과 현재 키보드 대상이 표시되는 것은 다른 역할입니다. 구문은 MDN의 border 설명를 참고하세요.
모서리의 길이 값과 백분율 비교하기
.round { border-radius: 12px; }
.circle { width: 80px; height: 80px; border-radius: 50%; }
.oval { width: 160px; height: 80px; border-radius: 50%; }
12px 같은 길이 값은 모서리 반지름을 지정합니다. 네 모서리에 다른 값을 줄 수도 있지만 먼저 한 값으로 비교해 보세요. 50%를 같은 너비와 높이의 상자에 적용하면 원처럼 보이고, 가로세로 크기가 다르면 타원처럼 보입니다. 백분율의 가로 반지름은 너비, 세로 반지름은 높이를 기준으로 합니다.
부모의 둥근 모서리가 자식 이미지까지 자동으로 잘라 주는 것은 아닙니다. 이미지 자체에 border-radius를 주거나 부모에서 넘침을 자르는 방식 중 목적에 맞게 선택하세요. 부모에 hidden을 추가하면 자식의 그림자·포커스 표시도 경계에서 잘릴 수 있습니다. 다음 비교에서는 어느 박스가 잘라내는지 구분합니다. MDN의 border-radius 설명에서 반지름 계산을 확인할 수 있습니다.
그림자 값은 어떤 순서로 읽을까요?
.shadow { box-shadow: 0 8px 24px 4px rgb(0 0 0 / 16%); }
| 값 | 뜻 | 바꾸어 볼 결과 |
|---|---|---|
| 첫 번째 0 | 가로 이동 | 양수는 오른쪽, 음수는 왼쪽으로 이동 |
| 두 번째 8px | 세로 이동 | 양수는 아래쪽, 음수는 위쪽으로 이동 |
| 세 번째 24px | 흐림 반지름 | 0에 가까우면 선명하고 커지면 부드러워짐 |
| 네 번째 4px | 퍼짐 반지름 | 양수는 그림자 크기를 늘리고 음수는 줄임 |
| rgb(0 0 0 / 16%) | 색상과 불투명도 | 배경과 구분되는 정도가 달라짐 |
첫 두 길이는 필요하고 흐림과 퍼짐은 생략할 수 있습니다. 흐림 반지름에는 음수를 사용할 수 없습니다. inset을 추가하면 안쪽 그림자이며 기본은 바깥 그림자입니다. 그림자를 여러 개 넣는 방법도 있지만 먼저 한 그림자의 이동과 크기를 따로 바꾸며 확인하세요.
그림자의 흐림은 실제 레이아웃 여백이 아닙니다. 아래에 다른 카드가 있어도 그림자만큼 자동으로 밀려나지 않습니다. 지나치게 큰 그림자는 주변 글자나 다른 상자의 경계를 가릴 수 있으므로 필요하면 margin 등으로 실제 간격을 확보합니다. 자세한 구문은 MDN의 box-shadow 설명를 참고하세요.
그림자를 자르는 부모를 명확히 만들기
.frame { padding: 12px; overflow: visible; }
.frame.clip { overflow: hidden; }
.frame .card { box-shadow: 0 18px 20px 8px rgb(0 0 0 / 25%); }
전체 예제의 마지막 두 카드에는 각각 별도 .frame 부모가 있습니다. 같은 자식 그림자를 쓰되 첫 부모는 visible, 두 번째는 hidden입니다. 그림자가 부모의 12px padding보다 멀리 퍼지므로 hidden 쪽에서는 부모 경계에서 잘리는 모습을 볼 수 있습니다.
자기 자신에게 overflow: hidden을 주는 것과 상위 요소가 자식의 그림자를 자르는 것을 혼동하지 마세요. 이 실습은 부모가 자식 카드의 바깥 그림자를 자르는 상황입니다. 실제 페이지에서 그림자가 안 보이면 카드 자체의 값뿐 아니라 상위 요소의 overflow와 경계도 확인해야 합니다.
전체 예제와 변경 실습
아래 코드를 borders.html에 UTF-8로 저장합니다. 테두리·둥근 모서리·바깥 그림자·안쪽 그림자, 원과 타원, 잘림 비교를 모두 포함했습니다.
<!doctype html>
<html lang="ko">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>테두리·모서리·그림자 비교</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>카드 경계와 그림자</h1>
<div class="card border">테두리만 있는 카드</div>
<div class="card round">테두리와 둥근 모서리</div>
<div class="card shadow">바깥 그림자</div>
<div class="card inset">안쪽 그림자</div>
<h2>50% 모서리: 원과 타원</h2><div class="shape" role="img" aria-label="80×80 원"></div><div class="shape oval" role="img" aria-label="160×80 타원"></div>
<h2>부모 overflow: visible</h2><div class="frame"><div class="card">부모 밖으로도 보이는 자식 그림자</div></div>
<h2>부모 overflow: hidden</h2><div class="frame clip"><div class="card">부모 경계에서 잘리는 자식 그림자</div></div>
</body>
</html>
- .border의 두께를 2px에서 8px로 바꿉니다. 넓은 창에서 바깥 너비는 유지되고 안쪽 공간이 줄어드는지 확인한 뒤 2px로 되돌립니다.
- .shape의 너비를 80px에서 160px로 바꿉니다. 높이 80px을 유지하면 원이 타원이 되는지 확인하세요. 원래 너비로 복원합니다.
- .shadow의 가로 이동을 20px로, 세로 이동을 -8px로 각각 바꿉니다. 흐림 24px은 유지해 이동 방향만 비교하세요. 다음으로 흐림을 0으로 바꿔 선명한 경계와 비교한 뒤 원래 값으로 되돌립니다.
- 퍼짐 4px을 -4px로 바꿉니다. 그림자 크기가 줄어드는지 확인합니다. 두 번째 .frame의 hidden을 visible로 바꾸면 부모 밖의 그림자가 다시 보이는지 확인하고 hidden으로 복원합니다.
그림자가 흐리면 색의 불투명도와 배경 대비를, 한쪽만 잘리면 부모의 경계와 overflow를 확인하세요. 모서리 안의 자식 콘텐츠가 삐져나오면 자식 자체에 둥근 모서리를 주는 방식도 비교합니다. 효과를 늘리기보다 콘텐츠의 구분과 조작 대상을 읽기 쉽게 유지하는 것을 기준으로 판단하세요.










