
Uso de la función CSS element() poco conocida para crear un navegador de minimapa

El Grupo de Trabajo CSS del W3C a menudo nos ofrece funciones CSS brillantes con las que experimentar. A veces nos encontramos con algo tan genial que nos dibuja una sonrisa en la cara, pero se desvanece de inmediato porque pensamos: “Eso es genial, pero ¿qué hago con eso?”. La element()
función era así para mí. Es una función CSS que toma un elemento de la página y lo presenta como una imagen para mostrarla en la pantalla. Impresionante, pero quijotesco.
A continuación se muestra un ejemplo sencillo de cómo funciona. Actualmente, solo es compatible con Firefox, lo cual sé que es un fastidio, pero quédese conmigo y verás lo útil que puede ser.
div pHello World! how're you?brI'm not doing thatbrgreat. Got a cold #x1F637;/p/divdiv/div
#eleImg { background: -moz-element(#ele) no-repeat center / contain; /* vendor prefixed */}
La element()
función (con prefijo del navegador) toma el id
valor del elemento que traducirá en una imagen. El resultado parece idéntico a la apariencia del elemento dado en la pantalla.
Cuando pienso en element()
el resultado, pienso en la palabra vista previa . Creo que ese es el tipo de caso de uso que aprovecha al máximo: donde podemos obtener una vista previa de un elemento antes de que se muestre en la página. Por ejemplo, la siguiente diapositiva de una presentación, la pestaña oculta o la siguiente foto de una galería. O… ¡un minimapa!
Un minimapa es una vista previa en tamaño pequeño de un documento o página extensa, que generalmente se muestra en un lado u otro de la pantalla y se usa para navegar al punto correspondiente en ese documento.
Es posible que lo hayas visto en editores de código como Sublime Text.
CSS element()
Es útil para hacer que la “vista previa” forme parte del minimapa.
A continuación se muestra la demostración del minimapa, y luego analizaremos su código. Sin embargo, te recomiendo que veas la demostración de página completa porque los minimapas son realmente útiles para documentos largos en pantallas grandes.
Si estás usando un teléfono inteligente, recuerda que, según la teoría de la relatividad, los minimapas se volverán súper mini en pantallas mini; y no, eso no es realmente lo que dice la teoría de la relatividad, pero entiendes lo que quiero decir.
Si estás diseñando el minimapa para toda la página, como para un sitio web de una sola página, puedes usar el elemento del cuerpo del documento para la imagen. De lo contrario, también funciona centrado en el elemento de contenido principal, como el artículo de mi demostración.
div/divdiv !-- content -- /div
#minimap { background: rgba(254,213,70,.1) -moz-element(#article) no-repeat center / contain; position: fixed; right: 10px; top: 10px; /* more style */}
Para la imagen de fondo del minimapa, alimentamos la id
del artículo como parámetro element()
y, como ocurre con la mayoría de las imágenes de fondo, tiene un estilo que no se repite ( no-repeat
) y cabe dentro ( contain
) y en el centro del cuadro ( center
) donde se muestra.
El minimapa también está fijado a la pantalla en la parte superior derecha de la ventana gráfica.
Una vez que el fondo esté listo, podemos agregar un control deslizante encima y nos servirá para operar el desplazamiento del minimapa. Para el control deslizante, elegí input: range
, el control deslizante HTML original, sencillo y sencillo.
div input type="range" max="100" value="0"/div
#minimap-range { /* Rotating the default horizontal slider to vertical */ transform: translateY(-100%) rotate(90deg); transform-origin: bottom left; background-color: transparent; /* more style */}#minimap-range::-moz-range-thumb { background-color: dodgerblue; cursor: pointer; /* more style */}#minimap-range::-moz-range-track{ background-color: transparent;}
No es del todo sencillo, ya que necesitó algunos ajustes. Gire el control deslizante hacia arriba para que coincida con el minimapa y aplique un poco de estilo a sus pseudoelementos (específicamente, el pulgar y la pista) para reemplazar sus estilos predeterminados. Nuevamente, solo nos preocupa Firefox en este momento, ya que estamos lidiando con un soporte limitado.
Lo único que queda es vincular el valor del control deslizante a un punto de desplazamiento correspondiente en la página cuando el usuario cambia el valor. Para ello se necesita algo de JavaScript, que se ve así:
onload = () = { const minimapRange = document.querySelector("#minimap-range"); const minimap = document.querySelector("#minimap"); const article = document.querySelector("#article"); const $ = getComputedStyle.bind(); // Get the minimap range width multiplied by the article height, then divide by the article width, all in pixels. minimapRange.style.width = minimap.style.height = parseInt($(minimapRange).width) * parseInt($(article).height) / parseInt($(article).width) + "px"; // When the range changes, scroll to the relative percentage of the article height minimapRange.onchange = evt = scrollTo(0, parseInt($(article).height) * (evt.target.value / 100));};
El signo de dólar ( $
) es simplemente un alias de getComputedStyle()
, que es el método para obtener los valores CSS de un elemento.
Vale la pena señalar que el ancho del minimapa ya está configurado en el CSS, por lo que en realidad sólo necesitamos calcular su altura. Entonces, estamos tratando con la altura del minimapa y el ancho del control deslizante porque, recuerde, el control deslizante en realidad está girado hacia arriba.
Así es como se calcula la ecuación en el guión, comenzando con las variables:
- x1 = altura del minimapa (así como el ancho del control deslizante dentro de él)
- y1 = ancho del minimapa
- x2 = altura del artículo
- y2 = ancho del artículo
x1/y1 = x2/y2x1 = y1 * x2/y2 height of minimap = width of minimap * height of article / width of article
Y, cuando el valor del control deslizante cambia ( minimapRange.onchange
), es cuando ScrollTo()
se llama al método para desplazar la página hasta su valor correspondiente en el artículo.
¡Retrocesos! ¡Necesitamos alternativas!
Obviamente, habrá muchas ocasiones en las que element()
no será compatible si usamos esto en este momento, por lo que es posible que queramos ocultar el minimapa en esos casos.
Comprobamos la compatibilidad con funciones en CSS:
@supports (background: element(#article)) or (background: -moz-element(#article)){ /* fallback style */}
…o en JavaScript:
if(!CSS.supports('(background: element(#article)) or (background: -moz-element(#article))')){ /* fallback code */}
Si no le importa que no aparezca la imagen de fondo, aún puede conservar el control deslizante y aplicarle un estilo diferente.
Hay otras formas ingeniosas de crear minimapas que flotan en la naturaleza (y que tienen más compatibilidad con el navegador). Aquí hay un gran bolígrafo de Shaw:
También existen herramientas como pagemap y xivimap que pueden resultar de ayuda. La element()
función se encuentra especificada actualmente en el Módulo de Valores de Imagen CSS y Contenido Reemplazado Nivel 4 del W3C. Definitivamente vale la pena leerla para comprender completamente la intención y el pensamiento detrás de ella.
Estos datos de soporte del navegador son de Caniuse, que tiene más detalles. Un número indica que el navegador admite la función en esa versión y superiores.
Escritorio
Cromo | Firefox | ES DECIR | Borde | Safari |
---|---|---|---|---|
No | 4* | No | No | No |
Móvil / Tableta
Android Cromo | Android Firefox | Androide | Safari en iOS |
---|---|---|---|
No | 126* | No | No |
¡Pst! ¿Intentas seleccionar el texto del artículo en la demostración? Mira lo que sucede en el minimapa.
Deja una respuesta