Modos de fusión domesticados: “diferencia” y “exclusión”

Hasta 2020, los modos de fusión eran una característica que no había usado mucho porque rara vez tenía idea del resultado que podía producir sin probarlos primero. Y adoptar el enfoque de “pruébalo y mira qué pasa” parecía dejarme siempre horrorizado por el vómito visual que había logrado crear en la pantalla.

El problema surgió por no saber muy bien cómo funcionan en la parte trasera. Casi todos los artículos que ha visto sobre el tema se basan en ejemplos, comparaciones con Photoshop o descripciones artísticas detalladas. Los ejemplos me parecen geniales, pero cuando no tienes idea de cómo funcionan las cosas en el fondo, adapta una demostración atractiva a algo que implemente una idea diferente que tienes en la cabeza se convierte en una aventura que requiere mucho tiempo, es frustrante y, en última instancia, inútil. Entonces las comparaciones de Photoshop son prácticamente inútiles para alguien que tiene experiencia técnica. Y las descripciones artísticas detalladas me parecen lenguaje de pingüinos.

Así que se me iluminó cuando encontré la especificación y descubrí que también incluye fórmulas matemáticas según las cuales funcionan los modos de fusión. Esto significó que finalmente pude entender cómo funcionan estas cosas en la parte trasera y dónde pueden ser realmente útiles. Y ahora que lo sé mejor, compartiré este conocimiento en una serie de artículos.

Hoy, nos centraremos en cómo funciona la mezcla en general, luego veremos más de cerca dos modos de mezcla algo similar differencey exclusion, finalmente, llegaremos al meollo de este artículo donde analizaremos algunos casos de uso interesantes como los que aparecen a continuación. .

Analizamos el “cómo” de los modos de fusión.

Mezclar significa combinar dos capas (que se apilan una encima de la otra) y obtener una sola capa. Estas dos capas podrían ser dos hermanas, en cuyo caso la propiedad CSS que utilizamos es mix-blend-mode. También podrían ser dos backgroundcapas, en cuyo caso la propiedad CSS que utilizamos es background-blend-mode. Tenga en cuenta que cuando hablo de combinar “hermanos”, esto incluye combinar un elemento con los pseudoelementos o con el contenido del texto o el backgroundde su padre. Y cuando se trata de backgroundcapas, no background-imageme refiero sólo a las capas: background-colortambién es una capa.

Al combinar dos capas, la capa de arriba se llama origen , mientras que la capa de abajo se llama destino . Esto es algo que tomo como está porque estos nombres no tienen mucho sentido, al menos para mí. Esperaría que el destino fuera una salida, pero en cambio ambas son entradas y la capa resultante es la salida.

La forma exacta en que combinamos las dos capas depende del modo de fusión particular utilizado, pero siempre es por píxel. Por ejemplo, la siguiente ilustración utiliza el multiplymodo de fusión para combinar las dos capas, representadas como cuadrículas de píxeles.

Muy bien, pero ¿qué pasa si tenemos más de dos capas? Bueno, en este caso, el proceso de mezcla ocurre en etapas, comenzando desde abajo.

En una primera etapa, la segunda capa desde abajo es nuestro origen y la primera capa desde abajo es nuestro destino. Estas dos capas se mezclan y el resultado se convierte en el destino de la segunda etapa, donde la tercera capa desde abajo es la fuente. Fusionar la tercera capa con el resultado de fusionar las dos primeras nos da el destino para la tercera etapa, donde la cuarta capa desde abajo es la fuente.

Por supuesto, podemos utilizar un modo de fusión diferente en cada etapa. Por ejemplo, podemos usar differencepara mezclar las dos primeras capas desde abajo y luego usar multiplypara mezclar el resultado con la tercera capa desde abajo. Pero esto es algo en lo que profundizaremos un poco más en artículos futuros.

El resultado producido por los dos modos de fusión que analizamos aquí no depende de cuál de las dos capas esté encima. Tenga en cuenta que este no es el caso de todos los modos de fusión posibles, pero sí de los que estamos analizando en este artículo.

También son modos de fusión separables, lo que significa que la operación de fusión se realiza en cada canal por separado. Nuevamente, este no es el caso para todos los modos de fusión posibles, pero sí lo es para differencey exclusion.

Más exactamente, el canal rojo resultante sólo depende del canal rojo del origen y del canal rojo del destino; el canal verde resultante sólo depende del canal verde del origen y del canal verde del destino; y finalmente, el canal azul resultante solo depende del canal azul del origen y del canal azul del destino.

R = fB(Rs, Rd)G = fB(Gs, Gd)B = fB(Bs, Bd)

Para un canal genérico, sin especificar si es rojo, verde o azul, tenemos que es función de los dos canales correspondientes en la capa de origen (superior) y en la capa de destino (inferior):

Ch = fB(Chs, Chd)

Algo a tener en cuenta es que los valores RGB se pueden representar en el [0, 255]intervalo o como porcentajes en el [0%, 100%]intervalo, y lo que realmente usamos en nuestras fórmulas es el porcentaje expresado como un valor decimal. Por ejemplo, crimsonse puede escribir como cualquiera rgb(220, 20, 60)o como rgb(86.3%, 7.8%, 23.5%): ambos son válidos. Los valores de canal que utilizamos para los cálculos si un píxel es crimsonson los porcentajes expresados ​​como valores decimales, es decir .863, .078, .235.

Si un píxel es black, los valores de canal que usamos para los cálculos son todos 0, ya que blackse pueden escribir como rgb(0, 0, 0)o como rgb(0%, 0%, 0%). Si un píxel es white, los valores de canal que usamos para los cálculos son todos 1, ya que whitese pueden escribir como rgb(255, 255, 255)o como rgb(100%, 100%, 100%).

Tenga en cuenta que siempre que tengamos transparencia total (un alfa igual a 0), el resultado es idéntico al de la otra capa.

difference

El nombre de este modo de fusión podría proporcionar una pista sobre lo que hace la función de fusión. El resultado es el valor absoluto de la diferencia entre los valores del canal correspondiente para las dos capas.fB()

Ch = fB(Chs, Chd) = |Chs - Chd|

En primer lugar, esto significa que si los píxeles correspondientes en las dos capas tienen valores RGB idénticos (es decir, para cada uno de los tres canales), entonces el píxel de la capa resultante es porque las diferencias para los tres canales son .Chs = Chdblack0

Chs = ChdCh = fB(Chs, Chd) = |Chs - Chd| = 0

En segundo lugar, dado que el valor absoluto de la diferencia entre cualquier número positivo 0deja ese número sin cambios, el píxel de resultado correspondiente tiene el mismo valor RGB que el píxel de la otra capa si el píxel de una capa es black(todos los canales iguales 0).

Si el blackpíxel está en la capa superior (fuente), reemplazar los valores de su canal 0en nuestra fórmula nos da:

Ch = fB(0, Chd) = |0 - Chd| = |-Chd| = Chd

Si el blackpíxel está en la capa inferior (destino), reemplazar los valores de su canal 0en nuestra fórmula nos da:

Ch = fB(Chs, 0) = |Chs - 0| = |Chs| = Chs

Finalmente, dado que el valor absoluto de la diferencia entre cualquier número subunitario positivo y 1nos da el complemento de ese número, resulta que si el píxel de una capa está white(tiene todos los canales 1), el píxel resultante correspondiente es el píxel de la otra capa completamente invertido (lo que filter: invert(1)le haría).

Si el whitepíxel está en la capa superior (fuente), reemplazar los valores de su canal 1en nuestra fórmula nos da:

Ch = fB(1, Chd) = |1 - Chd| = 1 - Chd

Si el whitepíxel está en la capa inferior (destino), reemplazar los valores de su canal 1en nuestra fórmula nos da:

Ch = fB(Chs, 1) = |Chs - 1| = 1 - Chs

Esto se puede ver en acción en el lápiz interactivo a continuación, donde puede alternar entre ver las capas separadas y verlas superpuestas y combinadas. Al pasar el cursor sobre las tres columnas en el caso superpuesto también se revela lo que sucede en cada una.

exclusion

Para el segundo y último modo de combinación que veremos hoy, el resultado es el doble del producto de los valores de los dos canales, restado de su suma:

Ch = fB(Chs, Chd) = Chs + Chd - 2·Chs·Chd

Como ambos valores están en el [0, 1]intervalo, su producto siempre es como máximo igual al menor de ellos, por lo que el doble del producto siempre es como máximo igual a su suma.

Si consideramos un blackpíxel en la capa superior (fuente), y luego lo reemplazamos con en la fórmula anterior, obtenemos el siguiente resultado para los canales del píxel resultante correspondiente:Chs0

Ch = fB(0, Chd) = 0 + Chd - 2·0·Chd = Chd - 0 = Chd

Si consideramos un blackpíxel en la capa inferior (destino), y luego lo reemplazamos con en la fórmula anterior, obtenemos el siguiente resultado para los canales del píxel resultante correspondiente:Chd0

Ch = fB(Chs, 0) = Chs + 0 - 2·Chs·0 = Chs - 0 = Chs

Entonces, si el píxel de una capa es black, el resultado correspondiente es idéntico al píxel de la otra capa.

Si consideramos un whitepíxel en la capa superior (fuente), y luego lo reemplazamos con en la fórmula anterior, obtenemos el siguiente resultado para los canales del píxel resultante correspondiente:Chs1

Ch = fB(1, Chd) = 1 + Chd - 2·1·Chd = 1 + Chd - 2·Chd = 1 - Chd

Si consideramos un whitepíxel en la capa inferior (destino), y luego lo reemplazamos con en la fórmula anterior, obtenemos el siguiente resultado para los canales del píxel resultante correspondiente:Chd1

Ch = fB(Chs, 1) = Chs + 1 - 2·Chs·1 = Chs + 1 - 2·Chs = 1 - Chs

Entonces, si el píxel de una capa es white, el resultado correspondiente es idéntico al píxel de la otra capa invertido.

Todo esto se muestra en la siguiente demostración interactiva:

Tenga en cuenta que siempre que al menos una de las capas solo tenga blackpíxeles whitey produzca exactamente el mismo resultado.differenceexclusion

Ahora, pasemos al "qué" de los modos de fusión.

Aquí viene la parte interesante: ¡los ejemplos!

Efecto de cambio de estado del texto

Digamos que tenemos un párrafo con un enlace:

pHello, a href='#'World/a!/div

Comenzamos configurando algunos estilos básicos para colocar nuestro texto en el medio de la pantalla, aumentarlo font-size, establecer un backgroundy bodyun colortanto en el párrafo como en el enlace.

body {  display: grid;  place-content: center;  height: 100vh;  background: #222;  color: #ddd;  font-size: clamp(1.25em, 15vw, 7em);}a { color: gold; }

No parece mucho hasta ahora, ¡pero pronto cambiaremos eso!

El siguiente paso es crear un pseudoelemento absolutamente posicionado que cubra todo el enlace y que esté backgroundconfigurado en currentColor.

a {  position: relative;  color: gold;    ::after {    position: absolute;    top: 0;    bottom: 0;    right: 0;    left: 0;    background: currentColor;    content: '';  }}

Parece que lo anterior hemos estropeado las cosas... pero, ¿realmente lo hemos hecho? Lo que tenemos aquí es un goldrectángulo encima del goldtexto. Y si ha prestado atención a cómo funcionan los dos modos de combinación discutidos anteriormente, entonces probablemente ya haya adivinado lo que sigue: combinamos los dos nodos hermanos dentro del enlace (el rectángulo del pseudoelemento y el contenido del texto) usando differencey puesto que son ambos gold, resulta que lo que tienen en común –el texto– se convierte en black.

p { isolation: isolate; }a {  /* same as before */    ::after {    /* same as before */    mix-blend-mode: difference;  }}

Tenga en cuenta que tenemos que isolateel párrafo para evitar que se mezcle con el cuerpo background. Si bien esto es solo un problema en Firefox (y dado que tenemos una backgroundpantalla muy oscura body, no se nota demasiado) y está bien en Chrome, tenga en cuenta que, según las especificaciones, lo que hace Firefox es realmente correcto. Es Chrome el que se comporta con errores aquí, por lo que deberíamos tener la isolationpropiedad configurada en caso de que se solucione el error.

Muy bien, pero queremos que esto suceda sólo si el vínculo está enfocado o suspendido. De lo contrario, el pseudoelemento no es visible; digamos que está reducido a nada.

a {  /* same as before */  text-decoration: none;    ::after {    /* same as before */    transform: scale(0);  }  :focus { outline: none }  :focus, :hover { ::after { transform: none; } }}

También eliminamos el subrayado del enlace y el esquema de enfoque. A continuación, ahora puede ver el efecto de diferencia :hover(el mismo efecto ocurre en :focus, que es algo que puede probar en la demostración en vivo).

Ahora tenemos nuestro cambio de estado, pero parece difícil, así que agreguemos un transition!

a {  /* same as before */    ::after {    /* same as before */    transition: transform .25s;  }}

¡Mucho mejor!

Se vería aún mejor si nuestro pseudo creciera no de la nada en el medio, sino de una delgada línea en la parte inferior. Esto significa que debemos establecer el valor transform-originen el borde inferior ( 100%verticalmente y cualquier valor horizontalmente) e inicialmente escalar nuestro pseudo a algo un poco más que nada a lo largo del eje y .

a {  /* same as before */    ::after {    /* same as before */    transform-origin: 0 100%;    transform: scaleY(.05);  }}

Otra cosa que me gustaría hacer aquí es reemplazar el fontpárrafo por uno más atractivo estéticamente, ¡así que ocupémonos de eso también! Pero ahora tenemos un tipo diferente de problema: el final de la 'd' sobresale del rectángulo en :focus/ :hover.

Podemos solucionar esto con una horizontal paddingen nuestro enlace.

a {  /* same as before */  padding: 0 .25em;}

En caso de que se pregunte por qué configuramos esto paddingtanto en el lado derecho como en el izquierdo en lugar de simplemente configurar un padding-right, el motivo se ilustra a continuación. Cuando el texto de nuestro enlace se convierte en "Alien World", el comienzo rizado de la 'A' terminaría fuera de nuestro rectángulo si no tuviéramos un padding-left.

Esta demostración con un enlace de varias palabras arriba también resalta otro problema cuando reducimos el ancho de la ventana gráfica.

Una solución rápida aquí sería configurar display: inline-blockel enlace. Esta no es una solución perfecta. También se rompe cuando el texto del enlace es más largo que el ancho de la ventana gráfica, pero funciona en este caso particular, así que dejémoslo aquí ahora y volveremos a este problema en un momento.

Consideremos ahora la situación de un tema ligero. Dado que no hay forma de obtener whiteel blacktexto del enlace :hovero :focusfusionando dos capas de resaltado idénticas que no lo son white, necesitamos un enfoque un poco diferente aquí, uno que no implique el uso solo de modos de fusión.

Lo que hacemos en este caso es primero configurar el backgroundtexto del párrafo normal colory el texto del enlace colorcon los valores que queremos, pero invertidos. Inicialmente estaba haciendo esta inversión manualmente, pero luego me sugirieron usar la invert()función Sass, que es una idea genial que realmente simplifica las cosas. Luego, después de tener este tema oscuro que es básicamente el tema claro que queremos invertido, obtenemos el resultado deseado invirtiendo todo nuevamente con la ayuda de la invert()función de filtro CSS.

Pequeña advertencia aquí: no podemos configurar filter: invert(1)los elementos bodyo htmlporque esto no se comportará de la manera que esperamos y no obtendremos el resultado deseado. Pero podemos configurar tanto the backgroundcomo the filteren un contenedor alrededor de nuestro párrafo.

section  pHello, a href='#'Alien World/a!/p/section
body {  /* same as before,      without the place-content, background and color declarations,      which we move on the section */}section {  display: grid;  place-content: center;  background: invert(#ddd) /* Sass invert(color) function */;  color: invert(#222); /* Sass invertcolor) function */;  filter: invert(1); /* CSS filter invert(number|percentage) function */}a {  /* same as before */  color: invert(purple); /* Sass invert(color) function */}

Aquí hay un ejemplo de una barra de navegación que emplea este efecto (y muchos otros trucos inteligentes, pero están fuera del alcance de este artículo). Seleccione una opción diferente para verlo en acción:

Algo más con lo que debemos tener cuidado es lo siguiente: todos los descendientes nuestros sectionse invierten cuando usamos esta técnica. Y probablemente esto no sea lo que queremos en el caso de imglos elementos; ciertamente no espero ver las imágenes en una publicación de blog invertidas cuando cambio del tema oscuro al claro. En consecuencia, deberíamos revertir la filterinversión en cada imgdescendiente de nuestro section.

section {  /* same as before */    ,  img { filter: invert(1); }}

En conjunto, la siguiente demostración muestra los casos de tema oscuro y claro con imágenes:

Ahora volvamos al tema del texto del enlace envolvente y veamos si no tenemos mejores opciones que crear elementos a inline-block.

Bueno, ¡lo hacemos! Podemos combinar dos backgroundcapas en lugar de combinar el contenido del texto y un pseudo. Una capa se recorta en text, mientras que la otra se recorta en border-boxy su tamaño vertical se anima entre 5%los casos iniciales y 100%en los casos enfocados y suspendidos.

a {  /* same as before */  -webkit-text-fill-color: transparent;     -moz-text-fill-color: transparent;  --full: linear-gradient(currentColor, currentColor);  background:     var(--full),     var(--full) 0 100%/1% var(--sy, 5%) repeat-x;  -webkit-background-clip: text, border-box;          background-clip: text, border-box;  background-blend-mode: difference;  transition: background-size .25s;  :focus, :hover { --sy: 100%; }}

Tenga en cuenta que ya ni siquiera tenemos un pseudoelemento, por lo que tomamos parte del CSS, lo movimos en el enlace y lo modificamos para adaptarlo a esta nueva técnica. Hemos pasado de usar mix-blend-modea usar background-blend-mode; ahora estamos en la transición background-sizede transformy, en los estados :focusy :hover; y ahora no estamos cambiando el transform, sino una propiedad personalizada que representa el componente vertical del background-size.

Mucho mejor, aunque tampoco es una solución perfecta.

El primer problema es uno que seguramente habrás notado si revisaste el enlace de demostración en vivo del título en Firefox: no funciona en absoluto. Esto se debe a un error de Firefox que aparentemente informé en 2018, luego lo olvidé por completo hasta que comencé a jugar con los modos de fusión y lo presioné nuevamente.

El segundo problema se nota en la grabación. Los enlaces parecen algo descoloridos. Esto se debe a que, por alguna razón, Chrome combina elementos en línea como enlaces (tenga en cuenta que esto no sucederá con elementos de bloque como divs) con los backgroundde su ancestro más cercano ( sectionen este caso) si estos elementos en línea se han background-blend-modeconfigurado en cualquier otro valor que no sea normal.

Aún más extraño, configurar isolation: isolateel enlace o su párrafo principal no evita que esto suceda. Todavía tenía la sensación persistente de que debía tener algo que ver con el contexto, así que decidí seguir lanzando posibles trucos y esperar que algo termine funcionando. Bueno, no tuve que dedicarle mucho tiempo. Establecer opacityun 1valor subunitario (pero aún lo suficientemente cercano como para que no se note que no es completamente opaco) soluciona el problema.

a {  /* same as before */  opacity: .999; /* hack to fix blending issue ¯_(ツ)_/¯ */}

El problema final es otro que se nota en la grabación. Si observas la 'r' al final de “Amur”, podrás notar que su extremo derecho está recortado porque cae fuera del rectángulo de fondo. Esto es particularmente notable si lo comparas con la 'r' de "leopardo".

No tenía grandes esperanzas de solucionar este problema, pero de todos modos lancé la pregunta a Twitter. ¡Y qué sabes, se puede arreglar! ¡Usarlo box-decoration-breaken combinación con lo que paddingya hemos configurado puede ayudarnos a lograr el efecto deseado!

a {  /* same as before */  box-decoration-break: clone;}

Tenga en cuenta que box-decoration-breaktodavía se necesita el -webkit-prefijo para todos los navegadores WebKit, pero a diferencia del caso de propiedades como background-clipdonde está al menos un valor text, las herramientas de prefijo automático pueden solucionar el problema sin problemas. Es por eso que no he incluido la versión con prefijo en el código anterior.

Otra sugerencia que recibí fue agregar un negativo marginpara compensar el padding. Estoy yendo y viniendo sobre esto; no puedo decidir si me gusta más el resultado con o sin él. En cualquier caso, es una opción digna de mención.

$p: .25em;a {  /* same as before */  margin: 0 (-$p); /* we put it within parenthesis so Sass doesn't try to perform subtraction */  padding: 0 $p;}

Aún así, tengo que admitir que animar sólo la parte background-positiono la parte background-sizede un degradado es un poco aburrido. Pero gracias a Houdini, ahora podemos ser creativos y animar cualquier componente de un gradiente que deseemos, aunque esto solo es compatible con Chromium por el momento. Por ejemplo, el radio de un radial-gradient()me gusta a continuación o el progreso de un conic-gradient().

Invertir solo un área de un elemento (o un background)

Este es el tipo de efecto que a menudo veo logrado al usar la duplicación de elementos: las dos copias se colocan en capas una encima de la otra, donde una de ellas tiene una inversión filtery clip-pathse usa en la superior para mostrar ambas capas. Otra ruta es colocar un segundo elemento en capas con un alfa lo suficientemente bajo como para que ni siquiera puedas notar que está ahí y un backdrop-filter.

Ambos enfoques hacen el trabajo si queremos invertir una parte del elemento completo con todo su contenido y descendientes, pero no pueden ayudarnos cuando queremos invertir solo una parte de backgroundambos filtery backdrop-filterafectar elementos completos, no solo sus antecedentes. Y aunque la nueva filter()función (ya compatible con Safari) tiene efecto únicamente en backgroundlas capas, afecta a toda el área del fondo, no sólo a una parte.

Aquí es donde entra en juego la fusión. La técnica es bastante sencilla: tenemos una backgroundcapa, parte de la cual queremos invertir y una o más capas de degradado que nos dan un whiteárea donde queremos invertir la otra capa y transparencia (o black) en caso contrario. . Luego mezclamos usando uno de los dos modos de mezcla discutidos hoy. A los efectos de la inversión, prefiero exclusion(es un carácter más corto que difference).

He aquí un primer ejemplo. Tenemos un elemento cuadrado que tiene dos capas background. Las dos capas son una imagen de un gato y un degradado con una transición brusca entre whitey transparent.

div {  background:     linear-gradient(45deg, white 50%, transparent 0),     url(cat.jpg) 50%/ cover;}

Esto nos da el siguiente resultado. También establecimos dimensiones, a border-radius, sombras y embellecimos el texto en el proceso, pero todo eso no es realmente importante en este contexto:

A continuación, sólo necesitamos una declaración CSS más para invertir la mitad inferior izquierda:

div {  /* same as before */  background-blend-mode: exclusion; /* or difference, but it's 1 char longer */}

Observe cómo el texto no se ve afectado por la inversión; solo se aplica al background.

Probablemente conozcas los controles deslizantes interactivos de imágenes de antes y después. Es posible que incluso hayas visto algo así aquí mismo en CSS-Tricks. Lo he visto en Compressor.io, que uso a menudo para comprimir imágenes, ¡incluidas las que se usan en estos artículos!

Nuestro objetivo es crear algo así utilizando un único elemento HTML, menos de 100 bytes de JavaScript, ¡y ni siquiera mucho CSS!

Nuestro elemento va a ser un rango input. No configuramos sus atributos mino max, por lo que de forma predeterminada son 0y 100, respectivamente. Tampoco configuramos el atributo de valor, por lo que el valor predeterminado es 50, que también es el valor que le damos a una propiedad personalizada, --kestablecida en su styleatributo.

input type='range' style='--k: 50'/

En CSS, comenzamos con un reinicio básico, luego creamos inputun blockelemento que ocupa toda la altura de la ventana gráfica. También le damos dimensiones y fondos ficticios a su pista y pulgar para que podamos comenzar a ver cosas en la pantalla de inmediato.

$thumb-w: 5em;@mixin track() {  border: none;  width: 100%;  height: 100%;  background: url(flowers.jpg) 50%/ cover;}@mixin thumb() {  border: none;  width: $thumb-w;  height: 100%;  background: purple;}* {  margin: 0;  padding: 0;}[type='range'] {  , ::-webkit-slider-thumb,   ::-webkit-slider-runnable-track { -webkit-appearance: none; }    display: block;  width: 100vw; height: 100vh;    ::-webkit-slider-runnable-track { @include track; }  ::-moz-range-track { @include track; }    ::-webkit-slider-thumb { @include thumb; }  ::-moz-range-thumb { @include thumb; }}

El siguiente paso es agregar otra backgroundcapa en la pista, una linear-gradientdonde la línea de separación entre transparenty whitedependa del inputvalor del rango actual, --ky luego fusionar las dos.

@mixin track() {  /* same as before */  background:    url(flowers.jpg) 50%/ cover,     linear-gradient(90deg, transparent var(--p), white 0);  background-blend-mode: exclusion;}[type='range'] {  /* same as before */  --p: calc(var(--k) * 1%);}

Tenga en cuenta que el orden de las dos backgroundcapas de la pista no importa ya que ambas exclusionson differenceconmutativas.

Está empezando a parecerse a algo, pero arrastrar el pulgar no hace nada para mover la línea de separación. Esto sucede porque el valor actual --k(del cual depende la posición de la línea de separación del gradiente --p) no se actualiza automáticamente. Arreglemos eso con un poquito de JavaScript que obtiene el valor del control deslizante cada vez que cambia y luego se establece --ken este valor.

addEventListener('input', e = {  let _t = e.target;  _t.style.setProperty('--k', +_t.value)})

¡Ahora todo parece estar funcionando bien!

¿Pero lo es realmente? Digamos que hacemos algo un poco más sofisticado para el pulgar background:

$thumb-r: .5*$thumb-w;$thumb-l: 2px;@mixin thumb() {  /* same as before */  --list: #fff 0% 60deg, transparent 0%;  background:     conic-gradient(from 60deg, var(--list)) 0/ 37.5% /* left arrow */,     conic-gradient(from 240deg, var(--list)) 100%/ 37.5% /* right arrow */,     radial-gradient(circle,       transparent calc(#{$thumb-r} - #{$thumb-l} - 1px) /* inside circle */,       #fff calc(#{$thumb-r} - #{$thumb-l}) calc(#{$thumb-r} - 1px) /* circle line */,       transparent $thumb-r /* outside circle */),     linear-gradient(      #fff calc(50% - #{$thumb-r} + .5*#{$thumb-l}) /* top line */,       transparent 0 calc(50% + #{$thumb-r} - .5*#{$thumb-l}) /* gap behind circle */,       #fff 0 /* bottom line */) 50% 0/ #{$thumb-l};  background-repeat: no-repeat;}
				
	
	

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Subir