📘

ボックス全体リンク(カードリンク)を擬似要素で実装した時にaltキーを押してテキスト選択できるようにする方法

に公開
1

投稿記事へのリンクとか、複数のコンテンツのグループをまるっとリンクにするやつ(カードリンク?ブロックリンク?ボックスリンク?)をどうやってマークアップするか問題。

5億年前から議論されている話題ではあるものの、何かを考慮すると何かを犠牲にしなくてはいけず、完璧な最適解が未だに見つかっていないですよね。(自分が見つけれていないだけなのかもしれないが...)

今日また X でこれ関連の話題を見かけまして、改めてちょっと考えてみると ふと 新たに解決策を見つけたかもしれないので、公開してみます。

個人的な必須要件

  • マウスホイールクリックで別窓で開いたり、ボックス全体が普通のリンクと同じ挙動をする。
  • 内部に別のリンクも配置できる。
  • メインリンクも内部のリンクも、ちゃんとタブ操作できる。
  • スクリーンリーダーでちゃんとリンクタイトルとなる部分が読める。

基本これで十分だと個人的には思ってるやつ

わざわざ js まで用意する必要は自分はないと思っていて、基本的にはよく見かける擬似要素を広げるパターンのやつで十分だと思っています。

自分は以下のような実装をしています。

また、以下の CSS を加えると Tab キーでフォーカスした時にアウトラインをボックス全体に表示することもできたりします。

@supports selector(:has(*)) {
  .is--linkBox:has(._link:focus-visible) {
    outline: auto 1px;
    outline: auto 1px -webkit-focus-ring-color;
  }
  ._link:focus {
    outline: 0;
  }
}

これ(擬似要素使う手法)の問題点

リンク部分って普通は内部のテキストをドラッグで選択できないんですが、alt キーを押しながらドラッグするとできるようになってるんですよね。(最近まで知らなかった...)

この手法だと、それができません。擬似要素が邪魔になります。

以下に普通のテストリンクを置いておくので、alt 押しながらテキスト選択してみてください。

Zenn とっぷぺーじへのリンクだよ

自分はこれまで、リンクテキストをコピーしたい時、その前後の段落テキストも含めた広い範囲を適当にドラッグして無理やり選択してました。
無駄なテキストも含まれるので適当にペーストしてからいらんとこ消してましたが、その必要はなかったようです。(alt キーのテクニック知ってからも癖でやっちゃいますが)

無理やりスクリプトで対応する必要はないと思ってる派

この alt 選択問題は、個人的にはもう無視でいいと思ってます。

理由は以下の通り。

  • そもそも問題となる alt キー押しながらのテクニック知ってる人が少ない。(しらんけど。)
  • リンクテキストの一部分だけをピンポイントでコピーしたいこともそんなない。(しらんけど。)
  • 前後含めて選択すれば、リンク全体は無理やりコピーできる。

これらを踏まえると、もう十分じゃね...?と思ってます。
CSS だけで済むし。

スクリプトでごちゃごちゃがんばったところで何かしら別の問題は残ってしまうのであれば、もうこれくらいの問題は妥協していいでしょう。

実際、こういうボックスリンク?カードリンク?に関しては大手サイトやサービスでも alt キー押しながらテキスト選択はできない状態が一般的ですしね。

もちろん、自分もめっちゃがんばって色々トライしたことはありましたが、クリック操作をスクリプトでごちゃごちゃしようとすると、ブラウザのデフォルト挙動を全て再現するのが無理ゲーでした。(それを再現するパッケージもあるらしい?)

例えば、マウスホイールクリックで別タブで開く時の挙動が自分はどうしても完全再現できませんでした(別タブでは開けるが、その新しいウインドウの方に移動しちゃう、など...。)

しかし、閃いた(かも)!

ふと思ったんですよね。
ボックス全体リンクの問題を考えるとクリックの挙動をなんとかしようとしてしまうけど、擬似要素使った手法の問題がテキスト選択だけなのであれば、そのテキスト選択の方をスクリプトでできるようにしたらよくない...?
なんか、そっちの方が、できそうじゃない...?

ということで、やってみたのが以下の例です。

どうでしょう?
スクリプトが長ったらしいので実際に採用するかというと微妙ですが、問題は解決できたような気がします。

思いついてから取り急ぎ(ほぼ AI が)パパッと書いたスクリプトなので、もっと短く書けるとは思います。(スマートな実装できた人がいたらぜひ教えてください!)

Discussion

piepie

全面的に主題を取り違えていたようです。
混乱させてごめんなさい。
元コメントは他の方が混乱しそうなので削除しますね。

特に主要部分をaタグで囲んではいけない縛りはきついですね。
なぜその縛りが発生するのか想像できませんでしたが、今回の例では、aタグ縛りがなければ解決できそうですね。

<a class="_link" href="#linkbox-demo">
    <h3>Heading Link</h3>
    <p>
      Lorem ipsum dolor sit, amet consectetur adipisicing elit, sed do eiusmod tempor. Non facere laudantium ex eos doloribus aut dolore nisi provident.
    </p>
</a>
<p>
    <a href='#inner-link' class="inner-link">Inner Link</a>
</p>
._link {
  text-decoration: none;
  color: inherit;
  &::before {
    position: absolute;
    inset: 0;
    z-index: 0;
    content: "";
  }
  > :is(p, h3) {
    position: relative;
    z-index: 1;
  }
}
.inner-link {
  position: relative;
  z-index: 1;
}