読者です 読者をやめる 読者になる 読者になる

☆CSSテクニック☆Borderの継ぎ目

まず最初に、ありがちな次のようなものを作ってみました。

HTMLはだいたいこんな感じ。

<!doctype html>
<html>
	<head>
		<meta charset="UTF-8" />
		<title>HTML+CSS3で作る×ボタン</title>
		<style>
		.popup {
			background-color: white;
			color: #888;
			border: solid 1px;
			border-radius: 10px;
			position: absolute;
			top: 5em;
			left: 5em;
			width: 8em;
			height: 10em;
		}

		.popup > .content {
			position: absolute;
			top: 0.5em ;
			bottom: 0.5em ;
			left: 0.5em ;
			right: 0.5em ;
			color: black;
			border: solid 1px;
		}

		.popup > .close {
			border: inherit;
			border-radius: inherit;
			width: 14px;
			height: 14px;
			position: absolute;
			top: -7px;
			right: -7px;
			overflow: hidden;
		}

		.popup > .close > .base {
			border: solid 10px ;
			width: 0px;
			height: 0px;
			position: absolute;
		}

		.popup > .close > .border {
			border: solid 14px transparent;
			width: 0px;
			height: 0px;
			position: absolute;
		}

		.popup > .close:hover {
			color: red;
			border-color: red;
		}

		.popup > .close > .l {
			border-left: solid white 14px;
			top: -7px;
			left: -8px;
		}

		.popup > .close > .r {
			border-right: solid white 14px;
			top: -7px;
			left: -6px;
		}

		.popup > .close > .t {
			border-top: solid white 14px;
			top: -8px;
			left: -7px;
		}

		.popup > .close > .b {
			border-bottom: solid white 14px;
			top: -6px;
			right: -7px;
		}
		</style>
	</head>
	<body style="background-color:#FFC0FF">
		<div class="popup">
			<div class="close">
				<div class="base"></div>
				<div class="border l"></div>
				<div class="border r"></div>
				<div class="border t"></div>
				<div class="border b"></div>
			</div>
			<div class="content">
				<p>Contents</p>
			</div>
		</div>
	</body>
</html>

右上の×印を、borderを用いて作った4つの三角で切り取って作っています。それぞれ、中心から微妙に上下左右に1pxずつずらすことにより、×型の隙間を作っている……という形ですね。
.base なる要素があるのは、わざわざborder-colorとbackground-colorを個別に設定しなくても、colorを設定するだけで一気に色が変わるようにするための工夫です。

これを実際に適用すると、次のようになりました:

WindowsInternet Explorer 10

WindowsIGoogle Chrome 28.0

Windows版IOpera15.0

Windows版IFirefox 22.0

Mac OS XSafari 6.0.5

Mac OS XGoogle Chrome 28.0

Mac OS XOpera 15.0

Mac OS XFirefox 22.0

……なんかFirefoxだけ怪しい。

原因は

1ピクセルずらしをせずに、全く同じ場所に重ねてみると一目瞭然かと思います。

Internet ExplorerGoogle Chrome


Borderの継ぎ目にアンチエイリアスがかかっていることがわかります。

WindowsFirefox

よく見ると、微妙にアンチエイリアスがかかってるような気がしないでもありません。
が……背景色が#7d7d7dだというのに、そのアンチエイリアスっぽいところは#787878だとか#797979だとか。より暗くなっている……何故??
試しに、他の辺のborder-colorをtransparentではなく#888(背景色。実際には#7d7d7dになるのは恐らくOS側が原因)にしてみます。結果は……。


どうやらWindowsFirefox 22.0では、透明borderと不透明borderをブレンドする辺りが上手く行っていないっぽいような予感がしてきます。

Mac OS XFirefox

こちらはそもそも、アンチエイリアスが表示されません。境界線上にあるピクセルは、反時計回りの側のborderの情報をそのまま使っています。
Windows版と同様に、他のborderを#888にしてみましたが、結果は同じ。最初からそういう機能自体がないようです(border-radius等のアンチエイリアスはできるのですが……)。

これらを踏まえて

WindowsFirefoxは少々太い×になってしまうけれども問題はないものとして、MacFirefoxだけ微妙に1ピクセルずつずらした×を作る、ということにすれば、軒並み綺麗な×が作れるような気がします。
JavaScriptFirefox専用のCSSハックを組み合わせて、こんな感じ。

<style>
/* (省略) */

.popup > .close > .l {
	border-left: solid white 14px;
	bottom: -7px;
	left: -8px;
}

.popup > .close > .r {
	border-right: solid white 14px;
	top: -7px;
	right: -8px;
}

.popup > .close > .t {
	border-top: solid white 14px;
	top: -8px;
	left: -7px;
}

.popup > .close > .b {
	border-bottom: solid white 14px;
	bottom: -8px;
	right: -7px;
}
</style>
<script>
jQuery.ready(function() {
	if (navigator.platform.match(/^Mac/i)) {
		jQuery('head').append('<style> @-moz-document url-prefix() { .popup > .close { width: 15px; height: 15px; } } </style>');
	}
}) ;
</script>

上下左右の三角の基準点を反時計回り側の頂点にしておくことで、元は14x14ピクセルの大きさで作っていた×ボタンを15x15にするだけで上手くゆくようになります。

余談

どうやら完璧に見えたGoogle Chrome 28.0でしたが、非transparentなborderが複数になった途端、アンチエイリアスがかからなくなる模様。

もっとも、×印を作る時には各辺バラバラに作るので、関係のないことですが。