【CSS】バツ(×)マークの作り方|疑似要素・Unicode・SVG・アニメーション付き実装

【CSS】バツ(×)マークの作り方|疑似要素・Unicode・SVG・アニメーション付き実装 HTML/CSS

CSSでバツ(×)マークを作る方法を解説します。

閉じるボタン、モーダルの×アイコン、削除ボタンなど、バツマークはWebサイトのいたるところで使われる基本的なUIパーツです。しかし、実装方法は1つではありません。::before / ::after の疑似要素Unicode文字SVGなど複数のアプローチがあり、それぞれにメリット・デメリットがあります。

この記事では、バツマークの作り方を基本から実務レベルまで体系的に解説します。サイズや色のカスタマイズ、ホバーアニメーション、モーダルやハンバーガーメニューでの実装パターン、さらにアクセシビリティ対応まで、この1記事で完全にマスターできます。

この記事で学べること

  • ::before / ::after 疑似要素でバツマークを作る方法
  • Unicode文字(× / ✕ / ✖)で手軽に表示する方法
  • SVGで高品質なバツマークを描く方法
  • ホバーアニメーション(回転・スケール・色変化)の実装
  • モーダル・ハンバーガーメニュー・タグ削除での実務パターン
  • アクセシビリティ(aria-label・キーボード操作)の対応
  • よくあるミスと注意点
スポンサーリンク

::before / ::after 疑似要素でバツマークを作る(基本)

もっとも汎用的で実務でよく使われる方法が、CSSの疑似要素を使ったバツマークです。2本の線を45度と-45度に回転させて交差させることで、バツの形を作ります。

基本のコード

まず、HTMLにボタン要素を用意します。

HTML
<button class="close-btn" aria-label="閉じる"></button>

CSSで疑似要素を使い、2本の線をバツ型に配置します。

CSS
.close-btn {
  position: relative;
  width: 40px;
  height: 40px;
  border: none;
  background: transparent;
  cursor: pointer;
}

.close-btn::before,
.close-btn::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 24px;
  height: 2px;
  background: #333;
}

.close-btn::before {
  transform: translate(-50%, -50%) rotate(45deg);
}

.close-btn::after {
  transform: translate(-50%, -50%) rotate(-45deg);
}

仕組みの解説:

  1. position: relative を親要素に指定し、疑似要素の基準点にする
  2. ::before::after で2本の細長い長方形(線)を作る
  3. top: 50%; left: 50%; transform: translate(-50%, -50%) で要素の中央に配置
  4. rotate(45deg)rotate(-45deg) で線を交差させ、バツ型にする

ポイント:content: '' は必須です。疑似要素は content プロパティがないと表示されません。空文字でも構いませんが、省略するとバツマークが表示されなくなります。

サイズのカスタマイズ

バツマークのサイズは width(線の長さ)と height(線の太さ)で調整します。親要素のサイズも合わせて変更するとバランスが取れます。

サイズ ボタンサイズ 線の長さ(width) 線の太さ(height) 用途
24px × 24px 14px 1.5px タグ・チップの削除
中(デフォルト) 40px × 40px 24px 2px モーダル・通知の閉じるボタン
56px × 56px 32px 3px 全画面オーバーレイの閉じるボタン
CSS – CSS変数でサイズを一元管理
.close-btn {
  --btn-size: 40px;
  --line-length: 24px;
  --line-weight: 2px;
  --line-color: #333;

  position: relative;
  width: var(--btn-size);
  height: var(--btn-size);
  border: none;
  background: transparent;
  cursor: pointer;
}

.close-btn::before,
.close-btn::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: var(--line-length);
  height: var(--line-weight);
  background: var(--line-color);
}

.close-btn::before {
  transform: translate(-50%, -50%) rotate(45deg);
}

.close-btn::after {
  transform: translate(-50%, -50%) rotate(-45deg);
}

CSS変数を使えば、値を1か所変えるだけでサイズ・太さ・色をまとめて変更できます。

角丸のバツマーク

線の端を丸くすると、柔らかい印象のバツマークになります。

CSS
.close-btn::before,
.close-btn::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 24px;
  height: 3px;
  background: #333;
  border-radius: 2px;
}

border-radius を線の太さの半分程度にすると、自然な角丸になります。

円形背景付きのバツマーク

閉じるボタンとして使う場合、円形の背景を付けるとクリック可能であることが視覚的に伝わりやすくなります。

CSS
.close-btn-circle {
  position: relative;
  width: 40px;
  height: 40px;
  border: none;
  background: #f1f5f9;
  border-radius: 50%;
  cursor: pointer;
  transition: background 0.2s;
}

.close-btn-circle:hover {
  background: #e2e8f0;
}

.close-btn-circle::before,
.close-btn-circle::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 18px;
  height: 2px;
  background: #64748b;
  border-radius: 1px;
}

.close-btn-circle::before {
  transform: translate(-50%, -50%) rotate(45deg);
}

.close-btn-circle::after {
  transform: translate(-50%, -50%) rotate(-45deg);
}

HTMLエンティティ・Unicode文字で作る方法

CSSを書かずに、HTML文字だけでバツマークを表示する方法もあります。手軽に使えるため、簡単なUIやプロトタイプで重宝します。

使えるバツ文字の一覧

文字 HTMLエンティティ Unicode 名前 特徴
× &times; U+00D7 Multiplication Sign 最もよく使われる。フォントによって見た目が変わりにくい
&#10005; U+2715 Multiplication X 細めのバツ。繊細な印象
&#10006; U+2716 Heavy Multiplication X 太めのバツ。強調したい場面向き
&#10060; U+274C Cross Mark 絵文字スタイル。カラフルに表示される環境あり
&#x2573; U+2573 Box Drawings Light Diagonal Cross 罫線文字。均一な線の太さ

HTMLでの使い方

HTML
<button class="close-btn-text" aria-label="閉じる">
  &times;
</button>
CSS
.close-btn-text {
  font-size: 24px;
  color: #333;
  border: none;
  background: transparent;
  cursor: pointer;
  padding: 4px 8px;
  line-height: 1;
  transition: color 0.2s;
}

.close-btn-text:hover {
  color: #dc2626;
}

CSSの content プロパティで挿入する方法

HTMLを変更せずに、CSSだけでUnicode文字を挿入することもできます。

CSS
.close-btn-unicode::before {
  content: '�0D7';
  font-size: 24px;
}

content プロパティではHTMLエンティティは使えません。代わりに、Unicodeのコードポイントを \00D7 のようにバックスラッシュ付きの16進数で指定します。コードポイントは「U+00D7」の「00D7」部分です。

この方法は、HTMLを一切変更せずにCSSだけでバツアイコンを追加できるため、CSSフレームワークやユーティリティクラスを設計する際に重宝します。

文字 HTMLエンティティ CSSのcontent値
× &times; '�0D7'
&#10005; '2715'
&#10006; '2716'

注意:Unicode文字はフォントによって見た目が変わります。特に &#10060;(Cross Mark)は、OSやブラウザによって絵文字として表示されることがあり、色やサイズの制御が難しくなります。統一的な見た目が必要な場合は、疑似要素やSVGを使いましょう。

Unicode文字の注意点まとめ

Unicode文字でバツマークを作る方法は手軽ですが、以下の点に注意が必要です。

  • フォントによる見た目の差:同じUnicode文字でも、游ゴシック、メイリオ、San Franciscoなどフォントによってサイズや太さが微妙に異なります
  • 絵文字化の問題:U+274C(Cross Mark)などは、一部の環境で絵文字として表示され、CSSの color プロパティが効かなくなります
  • line-height の影響:Unicode文字はテキストとして扱われるため、line-height の値によって上下の位置がずれることがあります。line-height: 1 を指定するとずれを最小限にできます
  • vertical-align:ボタン内で縦方向の中央揃えが必要な場合は、display: inline-flex; align-items: center; を使うと確実です

SVGで作る方法

SVGはベクター形式なので、どんなサイズに拡大・縮小してもシャープに表示されます。Retinaディスプレイでもぼやけることがありません。色やサイズの変更も柔軟に行えるため、デザインシステムやコンポーネントライブラリでよく採用されます。

インラインSVGで作る

HTML
<button class="close-btn-svg" aria-label="閉じる">
  <svg width="24" height="24" viewBox="0 0 24 24"
       fill="none" stroke="currentColor"
       stroke-width="2" stroke-linecap="round">
    <line x1="6" y1="6" x2="18" y2="18" />
    <line x1="18" y1="6" x2="6" y2="18" />
  </svg>
</button>

コードのポイント:

  • stroke="currentColor" を指定すると、CSSの color プロパティでSVGの線の色を変更できる
  • stroke-width で線の太さを調整
  • stroke-linecap="round" で線の端を丸くする
  • fill="none" で塗りつぶしを無効にする(これがないと黒い四角になる)
CSS
.close-btn-svg {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border: none;
  background: transparent;
  color: #333;
  cursor: pointer;
  transition: color 0.2s;
}

.close-btn-svg:hover {
  color: #dc2626;
}

CSSの mask-image でSVGの色を変更する

背景画像としてSVGを使い、mask-image で色を自由に変えるテクニックです。外部SVGファイルを使う場合に便利です。

CSS
.close-btn-mask {
  width: 40px;
  height: 40px;
  border: none;
  background-color: #333;
  cursor: pointer;
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'%3E%3Cline x1='6' y1='6' x2='18' y2='18'/%3E%3Cline x1='18' y1='6' x2='6' y2='18'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'%3E%3Cline x1='6' y1='6' x2='18' y2='18'/%3E%3Cline x1='18' y1='6' x2='6' y2='18'/%3E%3C/svg%3E");
  -webkit-mask-size: contain;
  mask-size: contain;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  transition: background-color 0.2s;
}

.close-btn-mask:hover {
  background-color: #dc2626;
}

mask-image は、要素の表示領域をSVGの形状で切り抜き、background-color で色を付ける仕組みです。background-color を変えるだけで色が変わるため、ホバー時の色変更も簡単です。

SVGをdata URIで埋め込む際のエンコード

mask-imagebackground-image でSVGを使う場合、URLエンコードが必要です。以下の文字を変換します。

文字 エンコード後 説明
< %3C タグの開始
> %3E タグの終了
# %23 色コード
" %22 または '(シングルクォート) 属性値

data URIの先頭は data:image/svg+xml,(Base64ではなくURLエンコード)にするとファイルサイズが小さくなります。

ポイント:2024年以降、主要ブラウザすべてで mask-image がサポートされています。ただし、Safari(特に古いバージョン)では -webkit-mask-image が必要な場合があるため、両方記述しておくと安全です。

方法別の比較

ここまで紹介した3つの方法を比較します。

項目 疑似要素 Unicode文字 SVG
見た目の統一性 ◎ 完全に統一 △ フォント依存 ◎ 完全に統一
サイズ変更の柔軟性 ◎ CSS変数で自在 ○ font-sizeで変更 ◎ viewBoxで自在
色変更 ◎ background ◎ color ◎ stroke / color
アニメーション ◎ transform対応 △ 限定的 ◎ CSS/SMIL対応
コード量 ○ やや多い ◎ 最小限 ○ やや多い
おすすめ用途 実務全般 簡易UI・プロトタイプ デザインシステム

ホバーアニメーション付きバツボタン

バツボタンにホバーアニメーションを加えると、「この要素はクリックできる」というフィードバックをユーザーに与えられます。アニメーションなしのバツマークと比べて、操作性が大きく向上します。

ここでは実務でよく使われる3つのアニメーションパターンを紹介します。いずれもCSSだけで実装でき、JavaScriptは不要です。

回転アニメーション(rotate)

ホバー時にバツマークが90度回転するアニメーションです。もっともポピュラーなパターンで、操作対象であることが直感的に伝わります。

CSS
.close-btn-rotate {
  position: relative;
  width: 40px;
  height: 40px;
  border: none;
  background: transparent;
  cursor: pointer;
  transition: transform 0.3s ease;
}

.close-btn-rotate:hover {
  transform: rotate(90deg);
}

.close-btn-rotate::before,
.close-btn-rotate::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 24px;
  height: 2px;
  background: #333;
  border-radius: 1px;
  transition: background 0.3s;
}

.close-btn-rotate::before {
  transform: translate(-50%, -50%) rotate(45deg);
}

.close-btn-rotate::after {
  transform: translate(-50%, -50%) rotate(-45deg);
}

.close-btn-rotate:hover::before,
.close-btn-rotate:hover::after {
  background: #dc2626;
}

スケール + 色変化

ホバー時にバツマークが少し大きくなり、色も変わるアニメーションです。ユーザーに「押せる」という印象を強く与えるため、主にアクションボタンとしてのバツマークに適しています。

CSS
.close-btn-scale {
  position: relative;
  width: 40px;
  height: 40px;
  border: none;
  background: transparent;
  cursor: pointer;
  transition: transform 0.2s ease;
}

.close-btn-scale:hover {
  transform: scale(1.2);
}

.close-btn-scale::before,
.close-btn-scale::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 24px;
  height: 2px;
  background: #333;
  border-radius: 1px;
  transition: background 0.2s;
}

.close-btn-scale::before {
  transform: translate(-50%, -50%) rotate(45deg);
}

.close-btn-scale::after {
  transform: translate(-50%, -50%) rotate(-45deg);
}

.close-btn-scale:hover::before,
.close-btn-scale:hover::after {
  background: #dc2626;
}

背景フェードインアニメーション

ホバー時に円形の背景がフェードインし、バツマークの色も変わるパターンです。Google Material Designのような洗練された印象を与えます。

CSS
.close-btn-fade {
  position: relative;
  width: 40px;
  height: 40px;
  border: none;
  background: transparent;
  border-radius: 50%;
  cursor: pointer;
  transition: background 0.25s ease;
}

.close-btn-fade:hover {
  background: rgba(0, 0, 0, 0.08);
}

.close-btn-fade::before,
.close-btn-fade::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 20px;
  height: 2px;
  background: #555;
  border-radius: 1px;
}

.close-btn-fade::before {
  transform: translate(-50%, -50%) rotate(45deg);
}

.close-btn-fade::after {
  transform: translate(-50%, -50%) rotate(-45deg);
}

border を使ったバツマーク

疑似要素の background ではなく border を使ってバツマークを作る方法もあります。border を使うと、点線や二重線のバツマークも作れます。

CSS
.close-btn-border {
  position: relative;
  width: 40px;
  height: 40px;
  border: none;
  background: transparent;
  cursor: pointer;
}

.close-btn-border::before,
.close-btn-border::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 24px;
  height: 0;
  border-top: 2px solid #333;
}

.close-btn-border::before {
  transform: translate(-50%, -50%) rotate(45deg);
}

.close-btn-border::after {
  transform: translate(-50%, -50%) rotate(-45deg);
}

height: 0 にして border-top で線を表現しています。border-topborder-top: 2px dashed #333 にすれば点線のバツマーク、border-top: 3px double #333 にすれば二重線のバツマークになります。

box-shadow を使ったバツマーク

box-shadow を使うと、影付きのバツマークを1つの疑似要素だけで作ることもできます。ただし、コードが複雑になるため、実務では疑似要素2つのパターンが推奨です。

CSS – 影付きバツマーク
.close-btn-shadow::before,
.close-btn-shadow::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 24px;
  height: 2px;
  background: #333;
  border-radius: 1px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
}

疑似要素の代わりに子要素を使うパターン

疑似要素を使わず、<span> で線を作る方法もあります。JavaScriptで個別の線にアニメーションを付けたい場合に有用です。

HTML
<button class="close-btn-spans" aria-label="閉じる">
  <span class="close-line close-line-1"></span>
  <span class="close-line close-line-2"></span>
</button>
CSS
.close-btn-spans {
  position: relative;
  width: 40px;
  height: 40px;
  border: none;
  background: transparent;
  cursor: pointer;
}

.close-line {
  display: block;
  position: absolute;
  top: 50%;
  left: 50%;
  width: 24px;
  height: 2px;
  background: #333;
  border-radius: 1px;
  transition: transform 0.3s ease, background 0.3s ease;
}

.close-line-1 {
  transform: translate(-50%, -50%) rotate(45deg);
}

.close-line-2 {
  transform: translate(-50%, -50%) rotate(-45deg);
}

この方法のメリットは、JavaScriptから各線を個別に操作できることです。たとえば、一方の線だけ遅延させてアニメーションする演出が可能になります。

実務での使い方

バツマークは、さまざまなUIコンポーネントで「閉じる」「削除する」というアクションを表すアイコンとして使われます。ここでは、実務でよく登場する4つのパターンを紹介します。

モーダルの閉じるボタン

モーダル(ダイアログ)の右上に配置する閉じるボタンは、バツマークの最も代表的な使い方です。

HTML
<div class="modal-overlay">
  <div class="modal" role="dialog" aria-modal="true"
       aria-labelledby="modal-title">
    <button class="modal-close" aria-label="閉じる"></button>
    <h2 id="modal-title">タイトル</h2>
    <p>モーダルの内容</p>
  </div>
</div>
CSS
.modal {
  position: relative;
  max-width: 500px;
  margin: auto;
  padding: 2em;
  background: #fff;
  border-radius: 12px;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
}

.modal-close {
  position: absolute;
  top: 12px;
  right: 12px;
  width: 36px;
  height: 36px;
  border: none;
  background: transparent;
  border-radius: 50%;
  cursor: pointer;
  transition: background 0.2s;
}

.modal-close:hover {
  background: #f1f5f9;
}

.modal-close::before,
.modal-close::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 18px;
  height: 2px;
  background: #64748b;
  border-radius: 1px;
}

.modal-close::before {
  transform: translate(-50%, -50%) rotate(45deg);
}

.modal-close::after {
  transform: translate(-50%, -50%) rotate(-45deg);
}

ハンバーガーメニュー → バツの変形アニメーション

ハンバーガーメニュー(三本線)をクリックすると、バツマークに変形するアニメーションは、スマートフォンサイトで定番のUIパターンです。

HTML
<button class="hamburger" aria-label="メニュー"
        aria-expanded="false">
  <span class="hamburger-line"></span>
  <span class="hamburger-line"></span>
  <span class="hamburger-line"></span>
</button>
CSS
.hamburger {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 5px;
  width: 44px;
  height: 44px;
  border: none;
  background: transparent;
  cursor: pointer;
}

.hamburger-line {
  display: block;
  width: 24px;
  height: 2px;
  background: #333;
  border-radius: 1px;
  transition: transform 0.3s ease, opacity 0.3s ease;
}

/* メニューが開いたとき(.is-activeクラスを付与) */
.hamburger.is-active .hamburger-line:nth-child(1) {
  transform: translateY(7px) rotate(45deg);
}

.hamburger.is-active .hamburger-line:nth-child(2) {
  opacity: 0;
}

.hamburger.is-active .hamburger-line:nth-child(3) {
  transform: translateY(-7px) rotate(-45deg);
}

仕組みの解説:

  1. 3本の線は gap: 5px で等間隔に配置されている
  2. .is-active クラスが付くと、1本目が下に移動して45度回転、3本目が上に移動して-45度回転
  3. 2本目は opacity: 0 で非表示にする
  4. translateY の値は gap + height に合わせる(5px + 2px = 7px)

補足:JavaScriptで .is-active クラスの付け外しを行います。document.querySelector('.hamburger').addEventListener('click', function() { this.classList.toggle('is-active'); });

タグ・チップの削除ボタン

タグやチップ(ラベル)の右端に小さなバツマークを付けて、削除ボタンとして使うパターンです。

HTML
<div class="tag">
  JavaScript
  <button class="tag-remove" aria-label="JavaScriptタグを削除">
    &times;
  </button>
</div>
CSS
.tag {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 8px 4px 12px;
  background: #e0f2fe;
  color: #0369a1;
  border-radius: 16px;
  font-size: 14px;
}

.tag-remove {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  border: none;
  background: rgba(3, 105, 161, 0.15);
  color: #0369a1;
  border-radius: 50%;
  font-size: 14px;
  line-height: 1;
  cursor: pointer;
  transition: background 0.2s;
}

.tag-remove:hover {
  background: rgba(3, 105, 161, 0.3);
}

通知バナーの閉じるボタン

画面上部に表示される通知バナーに、右端の閉じるボタンを設置するパターンです。

HTML
<div class="notification" role="alert">
  <p>新機能が追加されました!</p>
  <button class="notification-close"
          aria-label="通知を閉じる">&times;</button>
</div>
CSS
.notification {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 16px;
  background: #0284c7;
  color: #fff;
  border-radius: 8px;
}

.notification p {
  margin: 0;
}

.notification-close {
  flex-shrink: 0;
  border: none;
  background: transparent;
  color: rgba(255, 255, 255, 0.8);
  font-size: 24px;
  line-height: 1;
  cursor: pointer;
  padding: 4px 8px;
  transition: color 0.2s;
}

.notification-close:hover {
  color: #fff;
}

フォーム入力欄のクリアボタン

検索フォームやテキスト入力欄に、入力内容をクリアするバツボタンを配置するパターンです。GoogleやYouTubeの検索バーで見られるUIです。

HTML
<div class="search-field">
  <input type="text" class="search-input"
         placeholder="検索...">
  <button class="search-clear"
          aria-label="入力をクリア">&times;</button>
</div>
CSS
.search-field {
  position: relative;
  display: inline-flex;
  align-items: center;
  width: 300px;
}

.search-input {
  width: 100%;
  padding: 10px 40px 10px 16px;
  border: 1px solid #e2e8f0;
  border-radius: 8px;
  font-size: 16px;
  outline: none;
}

.search-input:focus {
  border-color: #0284c7;
  box-shadow: 0 0 0 3px rgba(2, 132, 199, 0.15);
}

.search-clear {
  position: absolute;
  right: 8px;
  width: 28px;
  height: 28px;
  border: none;
  background: transparent;
  color: #94a3b8;
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
  border-radius: 50%;
  transition: color 0.2s, background 0.2s;
}

.search-clear:hover {
  color: #475569;
  background: #f1f5f9;
}

padding-right: 40px を入力欄に指定して、クリアボタンのスペースを確保しているのがポイントです。ボタンが入力テキストと重ならないようにします。

アクセシビリティの考慮

バツマークのボタンは見た目だけでなく、すべてのユーザーが操作できるように実装する必要があります。スクリーンリーダーのユーザー、キーボード操作のユーザー、視覚障害のあるユーザーなど、さまざまな状況を想定した対応が重要です。WAI-ARIA(Web Accessibility Initiative – Accessible Rich Internet Applications)のガイドラインに沿った実装を心がけましょう。

button要素を使う

バツマークのクリック要素には、必ず <button> 要素を使いましょう。<div><span> にクリックイベントを付けるのはNGです。

要素 キーボード操作 スクリーンリーダー フォーカス可能 判定
<button> Enter / Space で実行 「ボタン」と読み上げ Tab で移動可能 推奨
<div onclick> 反応しない 何も読み上げない Tab で移動不可 NG
<a href="#"> Enterのみ 「リンク」と読み上げ Tab で移動可能 非推奨

aria-label を設定する

疑似要素やアイコンだけのボタンには、スクリーンリーダーが読み上げるためのテキストが必要です。

HTML
<!-- NG: 読み上げ内容がない -->
<button class="close-btn"></button>

<!-- OK: aria-labelで読み上げテキストを指定 -->
<button class="close-btn" aria-label="閉じる"></button>

<!-- OK: visually-hiddenクラスでテキストを非表示にする -->
<button class="close-btn">
  <span class="visually-hidden">閉じる</span>
</button>

フォーカスリングの表示

キーボードで操作するユーザーは、どの要素にフォーカスが当たっているかを視覚的に確認する必要があります。outline を消さないようにするか、独自のフォーカススタイルを設定しましょう。

CSS
/* デフォルトのoutlineを消すのはNG */
.close-btn:focus {
  outline: none; /* これだけだとアクセシビリティ違反 */
}

/* OK: focus-visibleで独自スタイルを設定 */
.close-btn:focus-visible {
  outline: 2px solid #0284c7;
  outline-offset: 2px;
  border-radius: 4px;
}

:focus-visible は、キーボード操作時のみフォーカスリングを表示する疑似クラスです。マウスクリック時にはフォーカスリングが表示されないため、デザインを損なわずにアクセシビリティを確保できます。

キーボード操作のまとめ

操作 キー button要素の場合
フォーカス移動 Tab / Shift + Tab 自動で対応
ボタン実行 Enter / Space 自動で対応
モーダルを閉じる Escape JavaScriptで実装が必要

ポイント:<button> 要素を使えば、Tab移動やEnter/Spaceでの実行はブラウザが自動で処理してくれます。<div> を使うと、tabindexrole="button"、キーイベントのハンドリングをすべて自分で実装する必要があり、バグの原因にもなります。

よくあるミスと注意点

バツマークの実装で、初心者がはまりやすいミスと対処法をまとめます。

position: relative の付け忘れ

疑似要素に position: absolute を指定する場合、親要素に position: relative を付けないと、疑似要素の配置基準が意図しない要素になります。

CSS
/* NG: positionが指定されていない */
.close-btn {
  width: 40px;
  height: 40px;
}

/* OK: position: relativeを追加 */
.close-btn {
  position: relative;
  width: 40px;
  height: 40px;
}

タッチターゲットサイズが小さすぎる

スマートフォンでは、タッチ可能な要素のサイズを最低でも 44px × 44px にすることが推奨されています(WCAG 2.5.5)。バツマークの線のサイズを小さくしても、ボタン要素自体のサイズは44px以上を確保しましょう。

CSS
/* NG: ボタンが小さすぎる */
.close-btn-small {
  width: 20px;
  height: 20px;
}

/* OK: ボタンは44px以上、線は小さく */
.close-btn-accessible {
  position: relative;
  width: 44px;
  height: 44px;
  border: none;
  background: transparent;
  cursor: pointer;
}

.close-btn-accessible::before,
.close-btn-accessible::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 16px;  /* 線は小さく */
  height: 2px;
  background: #333;
}

content プロパティの書き忘れ

::before / ::after 疑似要素は、content プロパティがないとブラウザにレンダリングされません。空文字列 '' でも必ず指定してください。

CSS
/* NG: contentがないので表示されない */
.close-btn::before {
  position: absolute;
  width: 24px;
  height: 2px;
  background: #333;
}

/* OK: content: '' を追加 */
.close-btn::before {
  content: '';
  position: absolute;
  width: 24px;
  height: 2px;
  background: #333;
}

transform の原点ずれ

transform-origin のデフォルト値は center center(50% 50%)ですが、要素の配置方法によっては回転の中心がずれることがあります。translate(-50%, -50%) で中央に配置してから rotate する方法が最も確実です。

CSS
/* NG: 回転の中心がずれる */
.close-btn::before {
  top: 50%;
  left: 50%;
  transform: rotate(45deg);
  /* 線が中央からずれてしまう */
}

/* OK: translateで中央配置してからrotate */
.close-btn::before {
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%) rotate(45deg);
}

色のコントラスト不足

バツマークの色が背景と近すぎると、視認性が低くなります。WCAG 2.1では、UIコンポーネントに対して3:1以上のコントラスト比が求められます。

背景色 NG色(コントラスト不足) OK色(3:1以上)
#ffffff(白) #d4d4d4(1.3:1) #767676(4.5:1)
#f1f5f9(薄グレー) #cbd5e1(1.5:1) #64748b(4.2:1)
#1e293b(ダーク) #334155(1.4:1) #94a3b8(4.6:1)

注意:コントラスト比はChromeのDevToolsで簡単に確認できます。要素を検査して、色の横に表示されるコントラスト比の値を確認しましょう。

まとめ

CSSでバツマークを作る方法を、基本から実務パターンまで解説しました。最後に方法ごとのおすすめ用途をまとめます。

方法 おすすめ用途 メリット デメリット
::before / ::after モーダル、通知、ハンバーガーメニュー アニメーション自在、見た目が統一 コード量がやや多い
Unicode文字 タグ削除、簡易UI コード量が最小限 フォント依存で見た目が変わる
SVG デザインシステム、アイコンセット 高精細、currentColorで色変更 HTMLが冗長になる

実装の際は、以下のチェックリストを確認しましょう。

実装チェックリスト

  • <button> 要素を使っているか(<div><span> ではなく)
  • aria-label="閉じる" などのラベルを設定しているか
  • タッチターゲットサイズが44px以上あるか
  • フォーカスリング(:focus-visible)を設定しているか
  • バツマークの色が背景に対して十分なコントラストがあるか(3:1以上)
  • ホバー時の状態変化があるか(色変化やスケールなど)

バツマークは小さなUIパーツですが、正しく実装することで、すべてのユーザーにとって使いやすいWebサイトになります。疑似要素による基本的な作り方をマスターしたら、SVGやアニメーションにもぜひ挑戦してみてください。