La siguiente es una publicación de invitado de Nick Williams. Nick me envió un correo electrónico sobre una nueva biblioteca que creó para ayudar a trabajar con diseño receptivo. Específicamente, estaba implementando una idea que encontró aquí en CSS-Tricks, pero quería hacerlo de manera más inteligente al ejecutar el script solo cuando fuera necesario. ¡Así nació esta nueva mini biblioteca! Hay algunos similares, pero este es muy pequeño y funciona con consultas de medios nativos. Dejaré que Nick te cuente más al respecto…
Enquire.js es una biblioteca de JavaScript que creé para manejar consultas de medios en JavaScript.
“¡Vaya! ¡haz una copia de seguridad! ¿Consultas de medios en JavaScript? ¿Qué clase de abominación es esta?”
Si bien la premisa puede parecer extraña, realmente es una adición útil a la caja de herramientas de respuesta.
El detalle
Enquire.js es una biblioteca JavaScript pura y liviana para manejar consultas de medios. Tiene menos de 1kb cuando está comprimido en GZIP y minimizado, y no tiene absolutamente ninguna dependencia. Sí, leíste bien, sin dependencias, ¡ni siquiera jQuery! Lo máximo que tendrá que hacer es proporcionar un polyfill de matchMedia si desea admitir navegadores sin una implementación nativa.
Casos de uso
- Diseño de respuesta
- Diseño móvil primero
- Ayudar a los navegadores más antiguos con consultas de medios
Razón de ser
Entonces, ¿cómo y por qué sucedió esto? Creo que la forma más fácil de explicar es a través de un escenario simple…
Imagine que tiene un sitio web establecido, actualmente de ancho fijo y dirigido a dispositivos de pantalla grande. Ha escuchado todo el alboroto sobre este negocio de “diseño receptivo” y desea participar en algo de la acción. Por lo tanto, debe comenzar a diseñar y planificar diligentemente cómo puede funcionar su sitio web en dispositivos de pantalla pequeña. Recortó toda la basura, limpió su barra lateral flotante y aumentó el tamaño de los elementos de su formulario. ¡Estupendo!
Pero ¿qué pasa con ese molesto menú? Es robusto, tiene varios niveles y se basa en los efectos de desplazamiento de CSS para exponer la jerarquía más profunda; en otras palabras, ¡no funcionará en un dispositivo táctil de pantalla pequeña!
Así que investiga un poco en Google y encuentra una solución inteligente para convertir un menú en un menú desplegable. Choque los cinco, ¡su menú ahora es funcional en dispositivos móviles basados en el tacto! Pero tienes esta sensación persistente. No estás muy seguro de lo que es, pero algo todavía no está del todo bien. Ah, sí, eso es todo; está ejecutando este código incluso para dispositivos de pantalla grande, ¡aunque no lo necesiten en absoluto! Derramó una pequeña lágrima por los ciclos de CPU desperdiciados, deseando que hubiera una manera de ejecutar selectivamente este JavaScript.
¡Aparece un nuevo retador!
Aquí es donde inquire interviene para ayudar.
Por ahora, ejecutaremos la conversión de un menú a un escenario desplegable, haciendo que el menú aparezca cuando la ventana tenga menos de 960 px. Con enquire, es tan simple como esto:
enquire.register("max-width: 960px", function() {
// put Chris' code here to convert your menu to a dropdown
});
Todo lo que hace es decirle a inquire que invoque la función suministrada solo si la consulta de medios dada coincide. Y así, guarda esos valiosos ciclos de CPU para dispositivos de pantalla grande. De acuerdo, me doy cuenta de que es un poco tonto, ya que los dispositivos móviles suelen tener CPU de menor potencia en comparación con los dispositivos con pantallas más grandes, pero también funciona desde la otra dirección: ¡el muy legendario primer enfoque móvil!
Cavar más profundo
En este punto, vale la pena ejecutar rápidamente la API de consulta antes de entrar en algunos escenarios más sustanciosos. El ejemplo anterior mostró el caso de uso más simple para la consulta: proporcionar una función como el segundo parámetro que se ejecutará cuando coincida una consulta de medios. Esto será suficiente en la mayoría de los escenarios, sin embargo, consultar puede hacer mucho más si tiene requisitos más exigentes. Puedes pasar el register
método un objeto como tal:
enquire.register("screen and (max-width: 1000px)", {
// REQUIRED
// Triggered when the media query transitions
// from *unmatched* to *matched*
match : function() {},
// OPTIONAL
// Triggered when the media query transitions
// from a *matched* to *unmatched*
unmatch : function() {},
// OPTIONAL
// Triggered once immediately upon registration of handler
setup : function() {},
// OPTIONAL
// Defaults to false
// If true, defers execution of the setup function
// until the first media query is matched (still just once)
deferSetup : true
});
Esta firma le da control total y le permite definir exactamente lo que quiere que suceda y cuándo quiere que suceda. Esto solo se vuelve realmente útil cuando realiza una llamada para consultar listen
función (más sobre esto en breve).
Ejemplos
Entonces, veamos algunos ejemplos que muestran las funciones más avanzadas en acción.
Consultas de medios falsos en navegadores heredados
Enquire.js se puede usar para falsificar algunas consultas de medios rudimentarias en navegadores más antiguos. Sin embargo, no use este enfoque como un reemplazo de las consultas de medios genuinas en su CSS, solo utilícelo como un parche mono para navegadores más antiguos (jQuery usado en este ejemplo):
$(function() {
// cache body for speed
var $body = $("body");
// DRY up handler creation
function handlerFactory(className) {
return {
match : function() {
$body.addClass(className);
},
unmatch : function() {
$body.removeClass(className);
}
};
}
// hook up our "media queries"
enquire
.register("screen and (max-width : 320px)", handlerFactory("lt-320"))
.register("screen and (max-width : 640px)", handlerFactory("lt-640"))
.listen();
});
Aquí estamos usando match
y unmatch
controladores para agregar o quitar clases al <body>
elemento, que nos permite apuntar a estilos en pantallas de diferentes tamaños. Tenga en cuenta que podemos encadenar llamadas a todas las funciones de enquire.
De particular interés aquí es la llamada a la listen
para que la consulta responda a los eventos de cambio de tamaño y orientación del navegador (aunque, por supuesto, en este ejemplo, los eventos de cambio de orientación son poco probables en los navegadores heredados). Para un rendimiento óptimo, listen
está limitado para responder solo a un evento en un período de tiempo determinado. De forma predeterminada, esto es 500 ms, pero puede especificar su propio acelerador pasándolo como parámetro para escuchar:
// 10000 milliseconds = 10 seconds. Why not?!
enquire.listen(10000);
dogfooding
Veamos un ejemplo de un uso de enquire en el mundo real, tomado de la página del proyecto enquire.js (¡FTW dogfooding!). Aquí quería hacer que la página se cargara lo más rápido posible cargando solo la cantidad mínima de JavaScript de forma predeterminada, optando por cargar cualquier cosa más allá de eso de forma asíncrona, solo cuando sea necesario. Esto es para que los dispositivos de pantalla pequeña (y por medio de proxy, aquellos que tienen más probabilidades de estar en una conexión lenta) carguen la página lo más rápido posible, y solo los dispositivos de pantalla grande tienen que lidiar con los recursos adicionales.
En particular, este patrón se utiliza para extraer todo el código necesario para generar y representar la barra lateral “Ir a” de la página del proyecto. Este ejemplo está ligeramente simplificado para no distraer la atención de los conceptos importantes:
$(function() {
$toc = $(".toc");
enquire.register("screen and (min-width: 1310px)", [{
deferSetup : true,
setup : function () {
// use Modernizr's yepnope to load
// additional scripts and manage callbacks
Modernizr.load([
{
load: "js/jquery.toc.js",
callback : function() {
// code to generate "Jump To" list
// and append to body
}
},
// load in the bootstrap plugins.
// they hook themselves up via their data-API
"js/vendor/bootstrap-scrollspy.js",
"js/vendor/bootstrap-affix.js"
]);
},
match : function() {
$toc.fadeIn();
},
unmatch : function() {
$toc.hide();
}
}]).listen();
});
Aquí se han introducido dos nuevas opciones: setup
y deferSetup
. setup
es una función que se llama solo una vez, lo cual es excelente para eliminar toda su costosa manipulación DOM por adelantado. Por defecto, setup
se invoca tan pronto como registra su controlador de consultas, independientemente de si la consulta ya ha coincidido. Sin embargo, si proporciona el deferSetup
flag podemos posponer la configuración hasta la primera vez que se coincida con una consulta.
En este caso, obviamente tiene sentido, ya que los scripts solo se cargan para dispositivos de pantalla grande. El match
y unmatch
se dejan simplemente para mostrar y ocultar la lista “Saltar a”.
Otros ejemplos
Algunos escenarios más que consultar se manejarían sin esfuerzo:
- Imágenes receptivas
- Usar
data-*
atributos y cambiar una imagensrc
según la consulta de medios que coincida
- Usar
- Mezclar el contenido
- A veces no es tan fácil como simplemente apilar elementos en pantallas pequeñas, es posible que desee que el contenido aparezca en un orden completamente diferente.
- Nuevamente, recomendaría un enfoque declarativo con
data-*
atributos para que pueda seleccionar elementos de origen y elementos de destino.
Hay más…
¡Enquire.js todavía tiene más que ofrecer! Puede registrar múltiples controladores por consulta y también múltiples consultas, lo que significa que tiene la máxima flexibilidad. Para leer más sobre esto, visite la página del proyecto enquire.js.
¡Descarga, Bifurca y Contribuye!
Para descargas y código fuente, visite el proyecto en github. Si desea contribuir, por favor hágalo, me encantaría conocer las opiniones, pensamientos e ideas de otras personas. Bifurque al contenido de su corazón y haga una solicitud de extracción con cualquier cambio. Si encuentra algún problema, siéntase libre de crear un problema en github y lo solucionaré debidamente 🙂
Licencia
El proyecto tiene la licencia MIT, por lo que puede usarlo de la forma que desee.