ventanas ventana una teclado pestaña para mac google con como comando chrome cerrar cambiar atajos abrir javascript css focus

javascript - ventana - como cerrar una pestaña con el teclado



Habilitar: centrarse solo en el uso del teclado(o presionar las pestañas) (6)

Caso de estudio: página de inicio de sesión de Facebook

Facebook está usando un poco de Javascript en su página de inicio de sesión ahora (junio de 2018).

El Javascript detecta cuando el usuario ha hecho clic en su mouse o usado su teclado, y activa y desactiva una clase en el cuerpo: <body class="using-mouse">

Luego, las reglas de CSS pueden usar esa clase para mostrar u ocultar el estilo de enfoque apropiado en los elementos relevantes.

Aquí hay un código de ejemplo (también disponible en CodePen ):

// Let the document know when the mouse is being used document.body.addEventListener(''mousedown'', function() { document.body.classList.add(''using-mouse''); }); document.body.addEventListener(''keydown'', function() { document.body.classList.remove(''using-mouse''); });

/* The default outline styling, for greatest accessibility. */ /* You can skip this to just use the browser''s defaults. */ :focus { outline: #08f auto 2px; } /* When mouse is detected, ALL focused elements have outline removed. */ /* You could apply this selector only to buttons, if you wanted. */ body.using-mouse :focus { outline: none; }

<input> <button>Submit</button>

Caso de estudio: GMail página de inicio de sesión

Alternativamente, GMail es simplemente diseñar botones enfocados con una sombra más gruesa que los botones desenfocados, independientemente de si el usuario está usando el mouse o el teclado.

Esto es consistente, más fácil de implementar y probar, y no requiere Javascript.

Pero es un compromiso. Transmite información de enfoque en la que los usuarios del mouse no están realmente interesados, y podría decirse que es un poco demasiado sutil para los usuarios de teclado.

Aún así, este compromiso es mucho mejor que uno de los extremos (un contorno sólido en todas partes o ningún esquema).

Quiero deshabilitar :focus cuando no es necesario porque no me gusta cómo se ve mi navegación cuando está enfocado. Utiliza el mismo estilo que .active y es confuso. Sin embargo, no quiero deshacerme de él para las personas que usan el teclado.

Estaba pensando en agregar un enabled-focus clase en el cuerpo al presionar las pestañas y luego tener body.enabled-focus a:focus{...} pero eso agregaría una gran cantidad de CSS adicional para cada elemento que tiene el foco. Luego retire esa clase del cuerpo con el primer mouse hacia abajo.

¿Cómo lo haría? ¿Hay una solución mejor?


¡Eliminar el outline es terrible para la accesibilidad! Idealmente, el anillo de enfoque aparece solo cuando el usuario tiene la intención de usar el teclado .

2018 Respuesta: Uso :focus-visible . Actualmente es una propuesta del W3C para estilizar el enfoque solo con el teclado usando CSS. Hasta que los principales navegadores lo admitan, puede utilizar este robusto polyfill . No requiere agregar elementos adicionales o alterar el tabindex .

/* Remove outline for non-keyboard :focus */ *:focus:not(.focus-visible) { outline: none; } /* Optional: Customize .focus-visible */ .focus-visible { outline-color: lightgreen; }

También escribí una post más detallada en caso de que necesites más información.


Al jugar con la solución aceptada de Danield, encontré una forma alternativa, más simple, basada en el concepto de div interno / externo.

1) Crear un elemento externo e interno. Proporcione el elemento externo tabindex = "0" y el elemento interno tabindex = "- 1"

<div role="button" class="outer" tabindex="0"> <span class="inner" tabindex="-1"> I''m a button! </span> </div>

2) En el css, elimine el contorno del elemento interno cuando esté enfocado:

.inner:focus{ outline: none; }

3) Aplique cualquier ratón o haga clic en los controladores de eventos en el elemento interno. Aplique los eventos de enfoque (onfocus, onblur, onkeydown) al elemento externo.

Por ejemplo:

<div role="button" class="outer" tabindex="0" onfocus="focusEventHandler()" onkeydown="handleKeyDown.bind(this, myEventHandler)"> <div class="inner" tabindex="-1" onClick="myEventHandler()"> I''m a button! </div> </div>

** Mantenga el tamaño y la posición de manera que el elemento interior se superponga completamente al elemento exterior. Coloque todo el "botón" con estilo en el elemento exterior.

Cómo funciona esto:

Cuando el usuario hace clic en el "botón", hace clic en el elemento interno que tiene el contorno de enfoque eliminado. No es posible hacer clic en el elemento exterior ya que está cubierto por el elemento interior. Cuando el usuario usa el teclado para presionar el "botón", accede al elemento externo (tabindex = "0" hace que se pueda acceder al elemento con ''tab'') que obtiene un contorno de enfoque, pero no se puede acceder al elemento interno a través del pestaña (con tabindex = "- 1") y no recibe un esquema de enfoque cuando se hace clic.


Este es un problema que probablemente encontrará mucho. Lo bueno de estos problemas es que si una vez encuentras una solución, no te molestará más.

La solución más elegante parece ser la más simple: no elimines el esquema en: enfoca, hazlo en: en su lugar, activa: después de todo, activa es la pseudoclase dinámica que trata explícitamente los estilos que deben aplicarse cuando una El elemento enfocable se hace clic o se activa.

a:hover, a:active { outline: none; }

Los únicos problemas menores con este método: si un usuario activa un enlace y luego usa el botón de retroceso del navegador, el contorno se vuelve visible. Ah, y las versiones antiguas de Internet Explorer se confunden notoriamente por el significado exacto de: focus,: hover y: active, por lo que este método falla en IE6 y más abajo.

Tipp

Existe una solución trivial para evitar que los contornos se " overflow:hidden " al agregar un overflow:hidden simple overflow:hidden , que mantiene el contorno bajo control alrededor de la parte seleccionable del propio elemento.


No hay una solución clara. He hecho una solución de Hackish: aplique el evento de clic en su contenedor principal y escriba el siguiente código al hacer clic

_handleMouseClick = (event) => { if(event.detail){ document.activeElement.blur(); } }

Cuando haga clic con el mouse, obtendrá event.detail = 1 en ese clic. El elemento se difumina para que elimine el contorno y al hacer clic en el teclado obtenemos event.detail = 0, por lo que, en el caso del teclado, es normal.

O

En archivo css

body.disableOutline *:focus{ outline: none !important; }

En main js

document.addEventListener(''click'', _handleMouseClick,true); document.addEventListener(''keydown'',_keydown,true); function _handleMouseClick(event){ if(event.detail){ document.getElementsByTagName("body")[0].classList.add("disableOutline"); } } function _keydown(e){ document.getElementsByTagName("body")[0].classList.remove("disableOutline"); }


Este excelente artículo de Roman Komarov plantea una solución viable para lograr estilos de enfoque de solo teclado para botones , enlaces y otros elementos de contenedores como spans o divs (que se pueden enfocar artificialmente con el atributo tabindex)

La solución:

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>

Codepen

1) Envuelva el contenido del elemento interactivo original dentro de un elemento interno adicional con tabindex="-1" (consulte la explicación a continuación)

Así que en lugar de decir:

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

hacer esto:

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

2) Mueva el estilo css al elemento interior (el diseño css debe permanecer en el elemento exterior original), por lo que la anchura / altura del elemento exterior proviene del interior, etc.

3) Eliminar el estilo de enfoque predeterminado de los elementos externos e internos:

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

4) Agregue un estilo de enfoque al elemento interior solo cuando el elemento exterior tenga enfoque:

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

¿Por qué funciona esto?

El truco aquí es configurar el elemento interno con tabindex="-1" - ver MDN :

Un valor negativo (generalmente tabindex = "- 1" significa que el elemento debe ser enfocable, pero no debe ser accesible a través de la navegación secuencial del teclado ...

Por lo tanto, el elemento se puede enfocar a través de clics del mouse o programáticamente, pero por otro lado, no se puede acceder a través de las "pestañas" del teclado.

Entonces, cuando se hace clic en el elemento interactivo, el elemento interno se enfoca. No se mostrarán estilos de enfoque porque los hemos eliminado.

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

Tenga en cuenta que solo se puede enfocar 1 elemento DOM en un momento dado (y document.activeElement devuelve este elemento), por lo que solo se enfocará el elemento interno.

Por otro lado: cuando pulsamos el teclado, solo el elemento externo obtendrá el foco (recuerde: el elemento interno tiene tabindex = "- 1" y no se puede acceder a él mediante la navegación secuencial del teclado) [Tenga en cuenta que para los no inherentes elementos externos enfocables como un <div> tabindex="0" - tenemos que hacerlos tabindex="0" artificialmente agregando tabindex="0" ]

Ahora nuestro CSS se activa y agrega los estilos de enfoque solo para teclado al the inner element .

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

Por supuesto, queremos asegurarnos de que cuando presionamos y presionamos enter , no hemos roto nuestro elemento interactivo y el javascript se ejecutará.

Aquí hay una demostración para mostrar que este es realmente el caso, pero tenga en cuenta que solo obtendrá esto gratis (es decir, al presionar Intro para provocar un evento de clic) para elementos inherentemente interactivos, como botones y enlaces ... para otros elementos, como spans - necesitas codificar eso manualmente :)

//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>

Codepen

NÓTESE BIEN:

1) Aunque esto parece una solución demasiado complicada, para una solución que no sea javascript es realmente impresionante. Las ''soluciones'' más simples para css, que incluyen :hover y :active estilo de pseudo clase :active , simplemente no funcionan. (a menos que, por supuesto, asuma que el elemento interactivo desaparece inmediatamente al hacer clic como un botón dentro de un modo modal)

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>

Codepen

2) Esta solución no es perfecta: Firefox en Windows seguirá teniendo estilos de enfoque para los botones al hacer clic, pero parece ser un error de Firefox (consulte el artículo )

3) Cuando los navegadores implementan la :fo­cus-ring pseudo clase de :fo­cus-ring - puede haber una solución mucho más sencilla para este problema - (vea el artículo ) Para lo que vale, hay un polyfill para :focus-ring - vea este artículo por Chris DeMars

Una alternativa pragmática a los estilos de enfoque solo para teclado

Por lo tanto, lograr estilos de enfoque solo para el teclado es sorprendentemente difícil. Una alternativa / solución alternativa que es mucho más simple y que puede cumplir con las expectativas del diseñador y también ser accesible, sería enfocar el estilo al igual que lo haría con el estilo de vuelo estacionario.

Codepen

Entonces, aunque técnicamente esto no es la implementación de estilos de solo teclado, esencialmente elimina la necesidad de estilos de solo teclado.