「ボーダー(border)をつけたいけど、外側に膨らむのは困る」
「paddingで余白を確保しているのに、borderが外に広がってレイアウトがずれる…」
そんな経験はありませんか?
実は、CSSのborder
はデフォルトではボックスの外側に付くため、サイズや位置が思わぬ形でずれてしまうことがあります。
この記事では、CSSで枠線(border)を内側に引くための方法を、初心者にもわかりやすく解説します。
そもそもCSSのborderはどこにつくの?

標準的なボックスモデルの仕組み
CSSの標準的なボックスモデルは以下の順序で構成されています:
content → padding → border → margin
つまり、border
は常にコンテンツの外側に付くため、以下のような構造になります:
- 要素のwidthやheightはコンテンツ領域の大きさ
- その外側にpadding(内側の余白)
- さらに外側にborder(枠線)
- 一番外側にmargin(外側の余白)
視覚的な理解
┌──────────── margin ────────────┐
│ ┌─────────── border ───────────┐ │
│ │ ┌──────── padding ────────┐ │ │
│ │ │ │ │ │
│ │ │ content area │ │ │
│ │ │ │ │ │
│ │ └────────────────────────┘ │ │
│ └─────────────────────────────┘ │
└───────────────────────────────────┘
これがズレの原因になる理由
例えば以下のCSSを書いた場合:
.box {
width: 200px;
height: 100px;
padding: 20px;
border: 5px solid #333;
}
実際に描画されるサイズは:
- 横幅:200px(content)+ 40px(padding左右)+ 10px(border左右)= 250px
- 縦幅:100px(content)+ 40px(padding上下)+ 10px(border上下)= 150px
となり、指定したサイズより大きくなってしまいます。
よくある問題
レイアウト崩れの例
/* 3つ並べたいカード */
.card {
width: 33.33%;
float: left;
border: 1px solid #ddd; /* これで幅が増えてしまう */
}
この場合、borderの分だけ幅が増えて、3つのカードが1行に収まらなくなってしまいます。
グリッドレイアウトでの問題
.grid-item {
width: calc(25% - 10px);
border: 5px solid #333; /* 計算が狂ってしまう */
}
calcで計算しても、borderの分が考慮されていないとレイアウトがずれます。
borderを内側にする方法
実はCSS単体には「borderを内側だけに付ける」プロパティはありません。
そのため、以下の方法で実現します。
方法1:box-sizingで調整する(推奨)
基本的な使い方
box-sizing: border-box;
を使えば、指定したwidthやheightの中にpaddingとborderを含めることができます。
.box {
width: 200px;
height: 100px;
padding: 20px;
border: 5px solid #333;
box-sizing: border-box;
}
こうすると、見た目のサイズは常に200×100pxのままで、内側にborderとpaddingを収めた形になります。
box-sizingの種類
content-box(デフォルト)
.box {
box-sizing: content-box; /* デフォルト値 */
width: 200px;
/* 実際のサイズ = width + padding + border */
}
border-box(推奨)
.box {
box-sizing: border-box;
width: 200px;
/* 実際のサイズ = width(paddingとborderを含む) */
}
全体に適用する方法
多くの開発者が以下のリセットCSSを使用します:
*, *::before, *::after {
box-sizing: border-box;
}
これで、すべての要素が直感的なサイズ計算になります。
実際の使用例
カードレイアウト
.card {
width: 300px;
height: 200px;
padding: 20px;
border: 2px solid #ddd;
box-sizing: border-box;
/* 実際のサイズは300×200pxのまま */
}
グリッドアイテム
.grid-item {
width: 25%;
padding: 10px;
border: 1px solid #333;
box-sizing: border-box;
float: left;
/* 4つがぴったり横に並ぶ */
}
方法2:outlineを使う
outlineの特徴
outline
はborderと似ていますが、ボックスの外側に重なる形で描画され、サイズに影響しないのが特徴です。
.box {
width: 200px;
height: 100px;
padding: 20px;
outline: 5px solid #333;
/* サイズは変わらない */
}
borderとoutlineの違い
プロパティ | サイズへの影響 | 位置 | 角丸対応 |
---|---|---|---|
border | あり | ボックス境界 | あり |
outline | なし | ボックス外側 | なし |
outlineのメリット・デメリット
メリット
- レイアウトに影響しない
- アニメーションでの表示・非表示が簡単
- フォーカス表示に最適
デメリット
- 角丸(border-radius)が効かない
- 要素の外側にはみ出す
- 細かい位置調整ができない
実際の使用例
ボタンのホバー効果
.button {
padding: 10px 20px;
background: #007BFF;
color: white;
transition: outline 0.3s ease;
}
.button:hover {
outline: 3px solid rgba(0, 123, 255, 0.5);
outline-offset: 2px;
}
方法3:擬似要素を使って完全に内側に描く
基本的な実装
::before
や::after
で擬似要素を作り、内側にborderを引くテクニックです。
.box {
position: relative;
width: 200px;
height: 100px;
padding: 20px;
}
.box::before {
content: "";
position: absolute;
top: 5px;
left: 5px;
right: 5px;
bottom: 5px;
border: 2px solid #333;
pointer-events: none; /* クリック操作の邪魔をしない */
}
これでpaddingの内側にborderを引いたような見た目にできます。
より高度な実装
内側の任意の位置にborder
.inner-border {
position: relative;
}
.inner-border::after {
content: '';
position: absolute;
top: 10px;
left: 10px;
right: 10px;
bottom: 10px;
border: 3px solid #FF6B6B;
border-radius: 8px;
pointer-events: none;
}
複数の内側border
.double-inner-border {
position: relative;
}
/* 外側の内側border */
.double-inner-border::before {
content: '';
position: absolute;
top: 5px;
left: 5px;
right: 5px;
bottom: 5px;
border: 2px solid #333;
pointer-events: none;
}
/* 内側の内側border */
.double-inner-border::after {
content: '';
position: absolute;
top: 15px;
left: 15px;
right: 15px;
bottom: 15px;
border: 1px solid #666;
pointer-events: none;
}
擬似要素の注意点
pointer-events: none が重要
.box::before {
pointer-events: none; /* マウスイベントを無視 */
}
これがないと、擬似要素がクリックやホバーの邪魔をしてしまいます。
z-indexでの重なり制御
.box::before {
z-index: 1; /* 必要に応じて重なり順を調整 */
}
方法4:insetプロパティ(現代的なアプローチ)
CSS Inset Propertyを活用
比較的新しいCSSプロパティinset
を使うと、より簡潔に書けます:
.box {
position: relative;
}
.box::before {
content: '';
position: absolute;
inset: 10px; /* top, right, bottom, left すべてに10px */
border: 2px solid #333;
pointer-events: none;
}
insetの書き方
/* 全方向同じ値 */
inset: 10px;
/* 上下、左右 */
inset: 10px 20px;
/* 上、左右、下 */
inset: 10px 20px 30px;
/* 上、右、下、左 */
inset: 10px 20px 30px 40px;
応用テクニックと実践例
レスポンシブデザインでの活用
メディアクエリと組み合わせ
.responsive-border {
box-sizing: border-box;
border: 2px solid #333;
}
@media (max-width: 768px) {
.responsive-border {
border-width: 1px; /* スマホでは細く */
}
}
@media (max-width: 480px) {
.responsive-border {
border: none; /* 小さい画面では非表示 */
outline: 1px solid #999;
}
}
アニメーション効果
border-boxでのアニメーション
.animated-border {
box-sizing: border-box;
width: 200px;
height: 100px;
border: 0px solid #007BFF;
transition: border-width 0.3s ease;
}
.animated-border:hover {
border-width: 5px;
}
擬似要素でのアニメーション
.slide-border {
position: relative;
overflow: hidden;
}
.slide-border::before {
content: '';
position: absolute;
top: 0;
left: -100%;
right: 100%;
bottom: 0;
border: 3px solid #FF6B6B;
transition: left 0.5s ease, right 0.5s ease;
}
.slide-border:hover::before {
left: 10px;
right: 10px;
}
特殊な形状のborder
角だけのborder
.corner-border {
position: relative;
}
.corner-border::before,
.corner-border::after {
content: '';
position: absolute;
width: 20px;
height: 20px;
}
.corner-border::before {
top: 10px;
left: 10px;
border-top: 3px solid #333;
border-left: 3px solid #333;
}
.corner-border::after {
bottom: 10px;
right: 10px;
border-bottom: 3px solid #333;
border-right: 3px solid #333;
}
グラデーションborder風
.gradient-inner-border {
position: relative;
background: white;
}
.gradient-inner-border::before {
content: '';
position: absolute;
inset: 5px;
border: 3px solid;
border-image: linear-gradient(45deg, #FF6B6B, #4ECDC4, #45B7D1) 1;
}
よくある質問と解決方法

Q. box-sizing: border-boxでpadding領域が狭くなる
A. paddingの値を調整するか、widthを大きくする
/* 調整前 */
.box {
width: 200px;
padding: 20px;
border: 5px solid #333;
box-sizing: border-box;
/* 実際のcontent領域は150px×50px */
}
/* 調整後:content領域を広くしたい場合 */
.box {
width: 250px; /* widthを大きく */
padding: 20px;
border: 5px solid #333;
box-sizing: border-box;
/* content領域は200px×100px */
}
Q. 擬似要素のborderがクリックの邪魔をする
A. pointer-events: none を設定
.box::before {
content: '';
/* その他のスタイル */
pointer-events: none; /* 必須 */
}
Q. 古いブラウザでbox-sizingが効かない
A. ベンダープレフィックスを追加
.box {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
Q. outlineとborderを両方使いたい
A. 重ねて使用可能
.double-line {
border: 2px solid #333;
outline: 1px solid #666;
outline-offset: 2px;
}
パフォーマンスとブラウザ対応
パフォーマンスの考慮
最も軽い方法
推奨順位
box-sizing: border-box
(最軽量)outline
(軽量)- 擬似要素(やや重い)
大量の要素での注意点
/* 重い:大量の擬似要素 */
.item::before { /* 100個の要素で100個の擬似要素 */ }
/* 軽い:box-sizingの活用 */
.item {
box-sizing: border-box;
border: 1px solid #ddd;
}
ブラウザ対応状況
box-sizing
- IE8+:対応
- Chrome/Firefox/Safari:完全対応
- モバイル:完全対応
outline
- IE8+:基本対応
- outline-offset:IE15+
insetプロパティ
- Chrome 87+
- Firefox 66+
- Safari 14.1+
まとめ
CSSのborderは標準ではボックスの外側に付くため、意図せずサイズが大きくなってしまいがちです。
手法の使い分け
box-sizing: border-box
- 最も実用的で推奨
- レスポンシブデザインに最適
- 計算が簡単
outline
- レイアウトに影響させたくない場合
- ホバー効果やフォーカス表示
- アニメーションが簡単
擬似要素
- 完全に内側にborderを引きたい場合
- 複雑なデザイン効果
- 特殊な形状のborder
基本的な推奨パターン
/* 全体的なリセット */
*, *::before, *::after {
box-sizing: border-box;
}
/* 通常のborder */
.element {
border: 1px solid #ddd;
/* サイズ計算が直感的 */
}
/* 特殊効果 */
.special-effect {
position: relative;
}
.special-effect::before {
content: '';
position: absolute;
inset: 5px;
border: 2px solid #333;
pointer-events: none;
}
コメント