本文へ

開発記録

記事の外部リンクを新しいタブで開くときに、ほかに考えること

記事本文の外部リンクを例に、origin の判定、target、noopener、noreferrer、アクセシブルな名前の役割を分け、属性による案内がすべての読者に見えるとは限らない理由を説明します。

林予晴
公開
  • HTML
  • リンク
  • アクセシビリティ
  • プログレッシブエンハンスメント

技術記事の参照リンクから、別のサイトへ移動することはよくあります。2026 年 10 月 25 日に記録したこのサイトの動作では、記事本文にある外部の HTTP(S) リンクは新しいウィンドウかタブで開き、サイト内の記事へのリンクは元のタブで開いていました。これは読み進め方についての選択であり、すべてのサイトが採用すべき唯一の答えではありません。

target="_blank" を付けるだけでは、扱うべきことの一部しか決まりません。何を外部と見なすか、opener の関係を残すか、参照元の情報を送るか、操作する前に読者が動作を把握できるかも決める必要があります。

以下では、その時点の記事本文用スクリプトとローカルの DOM の観察をもとに説明します。このルールは記事本文だけが対象で、サイト全体のすべてのリンクに共通する実装ではありません。

外部リンクかどうかは、解析後の origin で判断します

このスクリプトは、まず [data-note-body] 内から href を持つリンクを探し、アドレスを URL として解析していました。新しく開くための設定を加えるのは、プロトコルが http: または https: で、origin が現在のページと異なる場合だけです。

文字列がスラッシュで始まるかを見るより、この方法のほうが正確です。同じサイトの URL でも、完全な絶対 URL で書けます。一方、プロトコル、ホスト、ポートが違えば、よく似た URL 同士でも別の origin になることがあります。

この判定では、リンクは次のように分かれます。表が示しているのはコードの分岐であり、すべての種類を実際の記事で見つけて操作したという意味ではありません。

リンクの種類 本文用スクリプトの処理
同じ origin の記事 URL 新しいウィンドウやタブで開くための属性は追加しません
同じページ内のフラグメントリンク 新しいウィンドウやタブで開くための属性は追加しません
異なる origin の HTTP(S) URL target、rel と、条件を満たす場合は動作の案内を含む名前を追加します
mailto: などの HTTP(S) 以外のプロトコル 処理をスキップし、外部のウェブページを新しく開く設定にはしません

「追加しない」ことは、既存の設定を積極的に削除することではありません。リンクに target がすでに指定されていても、この分岐では取り除きません。一般的なサイト内リンクに target がなかったという観察から、すべての例外をスクリプトが修正すると考えることはできません。

target と rel は、それぞれ別のことを決めます

条件を満たすリンクには target="_blank" が設定され、rel="noopener noreferrer" が書き込まれていました。

noopener は、新しく開いたページと元のページの opener の関係を扱います。HTML 仕様では、対応する新しいウィンドウはこの opener への参照を受け取らないと説明しています。noreferrer は、リンク先への移動に referrer 情報を付けないよう求めるもので、noopener の動作も含みます。[2]

つまり、この二つは互いに独立した二重の保護ではなく、付ければ安全が完全に保証されるものでもありません。両方を明示すれば設定の意図は読み取りやすくなりますが、noreferrer を指定すると、リンク先はこの移動からその参照元情報を受け取れなくなります。特定の参照元トラッキングが必要なサイトでは、このトレードオフを確認する必要があります。見た目だけの設定として扱うことはできません。

これらの属性は、外部サイトが信頼できるかを読者の代わりに確認してくれるわけではありません。匿名で閲覧するための機能でもありません。参照先そのものの確認は引き続き必要です。リンクの開き方と、引用する情報の質は別の問題です。

操作する前に、動作を伝えます

このスクリプトは、もともと aria-label がなく、テキストを含む外部リンクについて、リンクのテキストと新しく開くことを伝える案内を組み合わせたアクセシブルな名前を作っていました。繁体字中国語版では「另開新視窗」(新しいウィンドウで開く)を加え、英語版と日本語版では、それぞれの言語の案内を使っていました。

元のリンクテキストを残すことが大切です。名前をどれも「另開新視窗」だけにしてしまうと、読者はそのリンクの移動先が分からなくなります。案内は移動先の情報を補うもので、置き換えるものではありません。

もともと aria-label があるリンクは、上書きしない設計です。そのため、すべての外部リンクの既存の名前に、新しく開くことの案内が含まれるとは保証されません。名前に必要な情報がそろっているかは、そのリンクを書くときに確認する必要があります。画像だけでテキスト内容のないリンクも、この文字列の組み立てだけで適切な名前を自動生成することはできません。

W3C の G201 は、通常の操作で新しいウィンドウを開くリンクやボタンをユーザーが操作する前に、警告や案内を提供することを勧めています。ただし、文書はこれを助言的な方法(advisory)と明記しています。特定の達成基準で必須とされる要件そのものとして扱うことはできません。[3]

アクセシブルな名前があっても、画面に案内があるとは限りません

このスクリプトが変更していたのは属性であり、本文に「新しいウィンドウで開く」という文字やアイコンを追加していたわけではありません。通常の画面表示では、aria-label の内容がリンクの横に自動表示されることはありません。

G201 の例には、画面に見えるテキストや、支援技術向けの説明と組み合わせた可視のアイコンが含まれています。[3] そのため私は、DOM に aria-label があるというだけで、すべての読者に十分な事前案内があったとは判断しません。このスクリプトを、サイト全体のアクセシビリティ適合を証明するものとして扱うこともしません。

ここでは、差が残っていることをはっきりさせておく必要があります。三つの言語で案内を含む名前を確認できたことと、画面上の案内が十分に設計されていることは同じではありません。補うのであれば、アイコンやテキストをどう見せるか、読み進める妨げにならないか、既存の名前とどう一貫性を保つかを別に決める必要があります。記事を書くついでに、サイト全体のルールを作り替えるべきではありません。

スクリプトがなくても、リンクであることは保ちます

本文の href は Markdown から HTML を生成した時点ですでに存在し、新しく開くための設定はブラウザー側のスクリプトが後から加えていました。ページのスクリプトを無効にして記事を読み込み直したところ、外部の参照先は移動先を持つ通常のリンクのままでした。ただし、新しく開くための追加属性と、補足した名前はなくなっていました。

このフォールバックが保つのは基本的なナビゲーションであり、「JavaScript の有無にかかわらず、まったく同じ動作をする」ことではありません。読者は引き続き、ブラウザーが備えるリンク操作を使えます。開き方を統一するために、参照先の URL をクリックハンドラーでしか動かない操作部品の中に隠すべきではありません。

このときローカルで確認したのは、HTML のセマンティクスを扱った記事の三つの言語版です。各版には、外部の参照リンクが二つと、サイト内の関連記事へのリンクが一つありました。スクリプト実行後は、外部リンクの target、rel、各言語の案内が設定どおりになり、サイト内リンクには新しく開く target がありませんでした。スクリプトを無効にすると、外部の参照先は通常のリンクに戻りました。

これらは属性と、スクリプトを無効にした状態の DOM の観察です。このときは、外部サイトを実際に開いて window.opener、HTTP Referer、移動先の動作を測定したわけではなく、スクリーンリーダーでもテストしていませんでした。仕様が裏付けるのは属性の意味であり、この確認が裏付けるのは選んだページの設定です。二種類の根拠を混ぜて、より大きな「すべて安全」という主張に広げる必要はありません。

ボタンに見えても、<button> にすべきとは限りませんでは、リンクの基本的な意味を先に扱いました。外部リンクでは、もう一つ問いを加えたいと考えています。読み進めている記事の位置を保ちながら、次の操作でどこへ移るのかも読者に伝えられているでしょうか。

参考資料

[2] https://html.spec.whatwg.org/multipage/links.html [3] https://www.w3.org/WAI/WCAG22/Techniques/general/G201