有効:キーボードの使用(またはタブの押下)のみにフォーカスする 質問する

有効:キーボードの使用(またはタブの押下)のみにフォーカスする 質問する

:focusフォーカスが当たったときのナビゲーションの見た目が気に入らないので、必要のないときは無効にしたいです。 と同じスタイルが使用されていて.active、わかりにくいです。ただし、キーボードを使用する人のために、これを削除したくありません。

enabled-focusタブを押したときに body にクラスを追加して、その後にクラスを追加することを考えていましたが、body.enabled-focus a:focus{...}そうするとフォーカスがあるすべての要素に余分な CSS が大量に追加されることになります。次に、最初のマウス ダウン時に body からそのクラスを削除します。

どうすればいいでしょうか? もっと良い解決策はあるでしょうか?

ベストアンサー1

更新:この問題はもはや関係ないかもしれない

いくつかの 他の ポスター擬似クラスについて言及しました:focus-visible- 今ではまともなブラウザのサポート...

付け加えておきたいのは、:focus-visible疑似クラスをカバーする仕様ブラウザは、焦点を示すユーザーにとって役立つ場合 - ユーザーがキーボードやその他の非ポインティングデバイスを使用してページを操作する場合など

これは基本的に、元の問題がもはや関係ないことを意味します。なぜなら、ユーザーがボタン (または別のフォーカス可能な要素) をクリック/タップすると、ボタンがフォーカスされているにもかかわらず、ユーザー エージェントはフォーカス リングを表示しなくなるからです。この場合、フォーカス リングはユーザーにとって役に立たないためです。

からスペック:

:focus疑似クラスは常に現在フォーカスされている要素と一致しますが、UAは時々目に見える形で焦点を示す(「フォーカス リング」を描画するなど)代わりに、さまざまなヒューリスティックを使用して、ユーザーにとって最も役立つ場合にのみフォーカスを視覚的に示すようにします。 :focus-visible 疑似クラスは、これらの状況でのみフォーカスされた要素と一致します...

実際、バージョン90では、Chromiumのユーザーエージェントスタイルシートはからに切り替わりました:focus:フォーカス可視この変更の結果、ボタンのクリックやタップでフォーカスリングが呼び出されなくなりました。

また、バージョン 87Firefox もユーザーエージェント スタイルで :focus-visible を使用します。

そうは言っても、カスタム フォーカス スタイルが必要な場合、フォーカス スタイルは から に移行したため:focus:focus-visibleデフォルトのスタイルをカスタム フォーカス スタイルで上書きするときには、:focus-visible疑似クラスを使用する必要があります。

このようなもの:

button:focus-visible {
  /* remove default focus style */
  outline: none;
  /* custom focus styles */
  box-shadow: 0 0 2px 2px #51a7e8;
  color: lime;
}

下位互換性:

このように :focus-visible を使用する場合に起こり得る問題は、 をサポートしていないブラウザでは:focus-visibleデフォルトのフォーカス リングが表示され、デザインによってはそれが明瞭でなかったり見えなかったりする可能性があることです。

シメ・ヴィダスこの記事:focus-visible 疑似クラスを現在使用する実行可能な戦略について説明します。これは、:focus-visible をまだサポートしていないブラウザでも機能します。

今日、:focus-visible を使い始める良い方法は、:focus ルールでフォーカス スタイルを定義し、すぐに :focus:not(:focus-visible) ルールで同じスタイルを元に戻すことです。これは確かに最もエレガントで直感的なパターンではありませんが、すべてのブラウザーでうまく機能します。

:focus-visible をサポートしていないブラウザは、:focus ルールで定義されたフォーカス スタイルを使用し、2 番目のスタイル ルールを完全に無視します (:focus-visible が不明であるため)。

:focus-visible をサポートしているブラウザでは、:focus-visible 状態もアクティブでない場合、2 番目のスタイル ルールによって :focus ルールで定義されたフォーカス スタイルが元に戻されます。つまり、:focus ルールで定義されたフォーカス スタイルは、:focus-visible もアクティブな場合にのみ有効になります。

button:focus {
  outline: none;
  background: #ffdd00; /* gold */
}

button:focus:not(:focus-visible) {
  background: white; /* undo gold */
}

元の回答:

この素晴らしい記事によるロマン・コマロフ達成するための実行可能な解決策を提示するキーボードのみのフォーカススタイルのためにボタンリンクその他のコンテナ要素としては、スパンまたはdiv要素(tabindex 属性によって人工的にフォーカス可能になります)

ソリューション:

button {
  -moz-appearance: none;
  -webkit-appearance: none;
  background: none;
  border: none;
  outline: none;
  font-size: inherit;
}

.btn {
  all: initial;
  margin: 1em;
  display: inline-block; 
}

.btn__content {
  background: orange;
  padding: 1em;
  cursor: pointer;
  display: inline-block;
}


/* Fixing the Safari bug for `<button>`s overflow */
.btn__content {
    position: relative;
}

/* All the states on the inner element */
.btn:hover > .btn__content  {
    background: salmon;
}

.btn:active > .btn__content  {
    background: darkorange;
}

.btn:focus > .btn__content  {
    box-shadow: 0 0 2px 2px #51a7e8;
    color: lime;
}

/* Removing default outline only after we've added our custom one */
.btn:focus,
.btn__content:focus {
    outline: none;
}
<h2>Keyboard-only focus styles</h2>

<button id="btn" class="btn" type="button">
    <span class="btn__content" tabindex="-1">
        I'm a button!
    </span>
</button>

<a class="btn" href="#x">
    <span class="btn__content" tabindex="-1">
        I'm a link!
    </span>
</a>

<span class="btn" tabindex="0">
    <span class="btn__content" tabindex="-1">
        I'm a span!
    </span>
</span>

<p>Try clicking any of the the 3 focusable elements above - no focus styles will show</p>
<p>Now try tabbing - behold - focus styles</p>

コードペン

  1. 元のインタラクティブ要素のコンテンツを、追加の内部要素で囲みますtabindex="-1"(以下の説明を参照)。

したがって、次のように言う代わりに:

<button id="btn" class="btn" type="button">I'm a button!</button>

これを行う:

<button id="btn" class="btn" type="button">
    <span class="btn__content" tabindex="-1">
        I'm a button!
    </span>
</button>
  1. CSS スタイルを内部要素に移動します (レイアウト CSS は元の外部要素に残ります)。これにより、外部要素の幅や高さが内部要素などから取得されます。

  2. 外側の要素と内側の要素の両方からデフォルトのフォーカス スタイルを削除します。

    .btn:focus、.btn__content:focus { アウトライン: なし; }

  3. 内部要素にフォーカススタイルを追加するの時だけ外側の要素にフォーカスがあります:

    .btn:focus > .btn__content { box-shadow: 0 0 2px 2px #51a7e8; /* キーボードのみのフォーカススタイル/ 色: ライム; /キーボードのみのフォーカススタイル */ }

なぜこれが機能するのでしょうか?

ここでのコツは、内部要素を設定することですtabindex="-1"翻訳:

負の値 (通常は tabindex="-1") は、要素はフォーカス可能であるが、順次キーボード ナビゲーションではアクセスできないことを意味します...

つまり、その要素はフォーカス可能マウスクリックまたはプログラムでアクセスできますが、一方でキーボードの「タブ」からはアクセスできません。

インタラクティブ要素をクリックすると、内部要素フォーカスを取得します。フォーカス スタイルは削除されているため表示されません。

.btn:focus,
.btn__content:focus {
    outline: none;
}

ご了承ください一度にフォーカスできるDOM要素は1つだけです(そしてdocument.activeElementこの要素を返す) - つまりのみ内部の要素に焦点が当てられます。

一方、キーボードでタブを押すと、外側の要素のみが焦点になります(覚えておいてください: 内側の要素には tabindex="-1" があり、キーボードの連続ナビゲーションではアクセスできません) [クリック可能な要素のような本質的にフォーカスできない外側の要素については<div>、 を追加して人工的にフォーカス可能にする必要があることに注意してくださいtabindex="0"]

ここで CSS が起動し、キーボードのみのフォーカス スタイルが に追加されますthe inner element

.btn:focus > .btn__content  {
    box-shadow: 0 0 2px 2px #51a7e8; /* keyboard-only focus styles */
    color: lime; /* keyboard-only focus styles */
} 

もちろん、タブキーを押して押したときにenter、インタラクティブ要素が壊れず、JavaScript が実行されることを確認する必要があります。

これが実際に当てはまることを示すデモがこちらにあります。ただし、ボタンやリンクなどの本質的にインタラクティブな要素に対してのみ、これを無料で利用できることに注意してください (つまり、Enter キーを押してクリック イベントを発生させる)。スパンなどの他の要素の場合は、手動でコーディングする必要があります :)

//var elem = Array.prototype.slice.call(document.querySelectorAll('.btn'));
var btns = document.querySelectorAll('.btn');
var fakeBtns = document.querySelectorAll('.btn[tabindex="0"]');


var animate = function() {
  console.log('clicked!');
}

var kbAnimate = function(e) {
  console.log('clicking fake btn with keyboard tab + enter...');
  var code = e.which;
  // 13 = Return, 32 = Space
  if (code === 13) {
    this.click();
  }  
}

Array.from(btns).forEach(function(element) {
  element.addEventListener('click', animate);
});

Array.from(fakeBtns).forEach(function(element) {
  element.addEventListener('keydown', kbAnimate);
});
button {
  -moz-appearance: none;
  -webkit-appearance: none;
  background: none;
  border: none;
  outline: none;
  font-size: inherit;
}

.btn {
  all: initial;
  margin: 1em;
  display: inline-block; 
}

.btn__content {
  background: orange;
  padding: 1em;
  cursor: pointer;
  display: inline-block;
}


/* Fixing the Safari bug for `<button>`s overflow */
.btn__content {
    position: relative;
}

/* All the states on the inner element */
.btn:hover > .btn__content  {
    background: salmon;
}

.btn:active > .btn__content  {
    background: darkorange;
}

.btn:focus > .btn__content  {
    box-shadow: 0 0 2px 2px #51a7e8;
    color: lime;
}

/* Removing default outline only after we've added our custom one */
.btn:focus,
.btn__content:focus {
    outline: none;
}
<h2>Keyboard-only focus styles</h2>

<button id="btn" class="btn" type="button">
    <span class="btn__content" tabindex="-1">
        I'm a button!
    </span>
</button>

<a class="btn" href="#x">
    <span class="btn__content" tabindex="-1">
        I'm a link!
    </span>
</a>

<span class="btn" tabindex="0">
    <span class="btn__content" tabindex="-1">
        I'm a span!
    </span>
</span>

<p>Try clicking any of the the 3 focusable elements above - no focus styles will show</p>
<p>Now try tabbing + enter - behold - our interactive elements work</p>

コードペン


注意:

  1. これは過度に複雑なソリューションのように思えますが、JavaScript 以外のソリューションとしては、実はかなり印象的です。疑似クラス スタイルを含む:hover:activeよりシンプルな CSS のみの「ソリューション」は、単純に機能しません。(もちろん、モーダル内のボタンのように、インタラクティブ要素がクリックするとすぐに消えると想定しない限り)

button {
  -moz-appearance: none;
  -webkit-appearance: none;
  background: none;
  border: none;
  font-size: inherit;
}

.btn {
  margin: 1em;
  display: inline-block; 
  background: orange;
  padding: 1em;
  cursor: pointer;
}

.btn:hover, .btn:active {
  outline: none;
}
<h2>Remove css :focus outline only on :hover and :active states</h2>

<button class="btn" type="button">I'm a button!</button>

<a class="btn" href="#x">I'm a link!</a>

<span class="btn" tabindex="0">I'm a span!</span>

<h3>Problem: Click on an interactive element.As soon as you hover out - you get the focus styling back - because it is still focused (at least regarding the button and focusable span) </h3>

コードペン

  1. この解決策は完璧ではありません。Windows上のFirefoxでは、クリックするとボタンのフォーカススタイルが取得されますが、これはFirefoxのバグのようです(記事

  2. ブラウザが:フォーカスリング疑似クラス - この問題にはもっと簡単な解決策があるかもしれない - (記事) 参考までに、ポリフィル:focus-ring~についてこの記事はクリス・デマルスによるものです


キーボードのみのフォーカススタイルに代わる実用的な代替手段

そのため、キーボードのみのフォーカススタイルを実現するのは驚くほど困難です。1つの代替手段/回避策ははるかにシンプルデザイナーの期待を満たし、アクセス可能にするには、ホバーのスタイルを設定するのと同じようにフォーカスのスタイルを設定することが考えられます。

コードペン

したがって、技術的にはキーボードのみのスタイルを実装しているわけではありませんが、本質的にはキーボードのみのスタイルの必要性がなくなります。

おすすめ記事