CSS

Las pseudoclases y los pseudoelementos de los componentes web son más fáciles de lo que piensas | trucos CSS

Hemos discutido mucho sobre los elementos internos del uso de CSS en esta serie actual de componentes web, pero hay algunos pseudoelementos y pseudoclases especiales que, como buenos amigos, están felices de oler tu aliento potencialmente halitósico antes de irte. habla con este posible interés amoroso. Ya sabes, te ayudan cuando más lo necesitas. Y así como un buen amigo te dará un aliento de menta, estos pseudoelementos y pseudoclases te brindan algunas soluciones de ambos dentro de componente web y de fuera de componente web: el sitio web donde vive el componente web.

quiero decir especialmente ::part y ::slotted pseudo-elementos y :defined, :hosty :host-context pseudoclases Nos dan formas adicionales de interactuar con los componentes web. Veámoslos con más detalle.

Una serie de artículos

EN ::part pseudo-elemento

::parten resumen, te permite perforar el árbol de la sombra, que es solo mi forma de El Señor de los Anillos decir que te permite diseñar elementos en el interior sombra DOM de fuera de DOM a la sombra. En teoría, debe encapsular todos sus estilos shadow DOM dentro de un shadow DOM, es decir. <style> elemento en su <template> elemento.

Entonces, dado algo similar de la primera parte de esta serie, donde tienes <h2> en tus <template>tus estilos para eso <h2> todos deberían estar adentro <style> elemento.

<template id="zprofiletemplate">
  <style>
    h2 {
      font-size: 3em;
      margin: 0 0 0.25em 0;
      line-height: 0.8;
    }
    /* other styles */
  </style>
  <div class="profile-wrapper">
    <div class="info">
      <h2>
        <slot name="zombie-name">Zombie Bob</slot>
      </h2>
      <!-- other zombie profile info -->
    </div>
</template>

Pero a veces es posible que necesitemos diseñar un elemento en el DOM oculto en función de la información que existe en la página. Por ejemplo, digamos que tenemos una página para cada zombi en el sistema de amor silencioso con fósforos. Podemos agregar una clase a los perfiles según lo cerca que estén. Entonces podríamos, por ejemplo, enfatizar el nombre del partido si es un buen partido. La proximidad de la coincidencia variará según la lista de coincidencias potenciales que se muestre y no conoceremos esta información hasta que estemos en esta página, por lo que no podemos incluir la funcionalidad en el componente web. <h2> está en el DOM oculto, pero no podemos implementarlo ni diseñarlo fuera, lo que significa zombie-profile h2 en la página de coincidencias no funcionará.

Pero si hacemos un ligero ajuste a <template> marcar agregando un part atribuido a <h2>:

<template id="zprofiletemplate">
  <style>
    h2 {
      font-size: 3em;
      margin: 0 0 0.25em 0;
      line-height: 0.8;
    }
    /* other styles */
  </style>
  <div class="profile-wrapper">
    <div class="info">
      <h2 part="zname">
        <slot name="zombie-name">Zombie Bob</slot>
      </h2>
      <!-- other zombie profile info -->
    </div>
</template>

Al igual que el spray bucal de Bianca, ahora tenemos los superpoderes para atravesar la oscura barrera DOM y diseñar estos elementos de fuera de desde <template>:

/* External stylesheet */
.high-match::part(zname) {
  color: blue;
}
.medium-match::part(zname) {
  color: navy;
}
.low-match::part(zname) {
  color: slategray;
}

Hay muchas cosas a tener en cuenta cuando se trata de usar CSS ::partPor ejemplo, está prohibido estilizar un elemento dentro de una parte:

/* frowny-face emoji */
.high-match::part(zname) span { ... }

Pero puedes agregar un part atribuya este elemento y diseñelo con su propio nombre de parte.

¿Qué pasa si tenemos un componente web en otro componente web? ::part ¿aún funciona? Si el componente web aparece en el marcador de la página, es decir. lo pones en una ranura, ::part funciona bien desde CSS en la página principal.

<zombie-profile class="high-match">
  <img slot="profile-image" src="https://assets.codepen.io/1804713/leroy.png" />
  <span slot="zombie-name">Leroy</span>
  <zombie-details slot="zdetails">
    <!-- Leroy's details -->
  </zombie-details>
</zombie-profile>

Pero si el componente web está en la plantilla / shadow DOM, entonces ::part No se pueden romper los dos árboles de sombra, solo el primero. Tenemos que traer ::part en la luz … por así decirlo, podemos hacer esto con uno exportparts atributo.

Para demostrar esto, agregaremos una «marca de agua» detrás de los perfiles usando un componente web. (¿Por qué? Lo crea o no, este fue el ejemplo menos imaginario que se me ocurrió). Aquí están nuestras plantillas: (1) la plantilla para <zombie-watermark>y (2) la misma plantilla para <zombie-profile> pero con un añadido <zombie-watermark> elemento al final.

<template id="zwatermarktemplate">
  <style>
    div {
    text-transform: uppercase;
      font-size: 2.1em;
      color: rgb(0 0 0 / 0.1);
      line-height: 0.75;
      letter-spacing: -5px;
    }
    span {
      color: rgb( 255 0 0 / 0.15);
    }
  </style>
  <div part="watermark">
    U n d y i n g  L o v e  U n d y i n g  L o v e  U n d y i n g  L o v e  <span part="copyright">©2 0 2 7 U n d y i n g  L o v e  U n L t d .</span>
  <!-- Repeat this a bunch of times so we can cover the background of the profile -->
  </div> 
</template>
<template id="zprofiletemplate">
  <style>
    ::part(watermark) {
      color: rgb( 0 0 255 / 0.1);
    }
    /* More styles */
  </style>
  <!-- zombie-profile markup -->
  <zombie-watermark exportparts="copyright"></zombie-watermark>
</template>
<style>
  /* External styles */
  ::part(copyright) {
    color: rgb( 0 100 0 / 0.125);
  }
</style>

Desde ::part(watermark) es solo una sombra sobre DOM <zombie-watermark>funciona bien desde el interior <zombie-profile>Estilos de plantilla de . Además, como hemos usado exportparts="copyright" en <zombie-watermark>la sección de derechos de autor se ha subido a <zombie-profile>sombra de DOM y ::part(copyright) ahora funciona incluso en estilos exteriores, pero ::part(watermark) no funcionará afuera <zombie-profile>plantilla de.

También podemos reenviar y renombrar partes con este atributo:

<zombie-watermark exportparts="copyright: cpyear"></zombie-watermark>
/* Within zombie-profile's shadow DOM */

/* happy-face emoji */
::part(cpyear) { ... }

/* frowny-face emoji */
::part(copyright) { ... }

Pseudoclases estructurales (:nth-childetc.) tampoco funcionan en partes, pero puede usar pseudoclases como :hover. Animemos un poco los nombres de las altas coincidencias y hagámoslas temblar mientras buscan el amor. Vale, he oído eso y estoy de acuerdo en que es incómodo. Vamos a… eh… hacerlos más, digamos, notorios, con un poco de movimiento.

.high::part(name):hover {
  animation: highmatch 1s ease-in-out;
}

EN ::slotted pseudo-elemento

EN ::slotted El pseudo-elemento CSS en realidad apareció cuando miramos los componentes web interactivos. La idea básica es esta ::slotted representa cualquier contenido en un slot en un componente web, es decir el elemento que tiene slot atributo en él. Pero donde ::part atraviesa el shadow DOM para hacer que los elementos del componente web sean accesibles a los estilos externos, ::slotted permanece encapsulado en <style> elemento en el componente <template> y accede al elemento que está técnicamente fuera del DOM sombreado.

En nuestro <zombie-profile> componente, por ejemplo, cada imagen de perfil se inserta en el elemento mediante slot="profile-image".

<zombie-profile>
  <img slot="profile-image" src="https://css-tricks.com/web-component-pseudo-classes-and-pseudo-elements/photo.jpg" /> 
  <!-- rest of the content -->
</zombie-profile>

Eso significa que tenemos acceso a él. imagen, así como cualquier imagen en cualquier otra ranura, de la siguiente manera:

::slotted(img) {
  width: 100%;
  max-width: 300px;
  height: auto;
  margin: 0 1em 0 0;
}

De la misma manera podríamos elegir todo tragamonedas con ::slotted(*) no importa qué elemento sea. Solo ten cuidado con eso. ::slotted debe seleccionar un elemento: los nodos de texto están inmunizados ::slotted estilos de zombis. Y los hijos del elemento tragamonedas son inaccesibles.

EN :defined pseudo-clase

:defined coincide con todos los elementos definidos (lo sé, sorprendente, ¿verdad?), tanto integrados como personalizados. Si su artículo personalizado se mueve como un zombi, evitando las preguntas del padre de su novia sobre su situación «en vivo», es posible que no desee que se muestren los cadáveres del contenido mientras espera que vuelvan a la vida errr… carga.

Puedes usar :defined pseudo-clase para ocultar un componente web antes de que esté disponible, o «definido», de la siguiente manera:

:not(:defined) {
  display: none;
}

puedes ver como :defined actúa como una especie de moneda en la boca de nuestros estilos de componentes, evitando que aparezca contenido roto (o mal aliento) mientras la página aún se está cargando. Una vez que se define el elemento, aparecerá automáticamente porque ahora está, ya sabes, definido y no no definido.

agregué un setTimeout de cinco segundos al componente web en la siguiente demostración. Así lo puedes ver <zombie-profile> los elementos no se muestran hasta que no están definidos <h1> y en <div> que aguanta <zombie-profile> los componentes todavía están allí. Eso es todo <zombie-profile> componente web que recibe display: none ya que aún no han sido definidos.

EN :host pseudo-clase

Supongamos que desea realizar cambios en el estilo del elemento personalizado. Si bien puedes hacer esto desde fuera de el elemento personalizado (como ajustar este N95), el resultado no se encapsulará y será necesario transferir CSS adicional dondequiera que se coloque este elemento personalizado.

Entonces sería muy conveniente tener una pseudo-clase que pueda alcanzar fuera de shadow DOM y seleccione la raíz de la sombra. Esta pseudoclase CSS es :host.

En los ejemplos anteriores de esta serie pregunté <zombie-profile> Ancho CSS de la página principal de la siguiente manera:

zombie-profile {
  width: calc(50% - 1em);
}

S :hostsin embargo, puedo establecer este ancho desde en el interior el componente web de la siguiente manera:

:host {
  width: calc(50% - 1em);
}

De hecho, había un div con una clase de .profile-wrapper en mis ejemplos, que ahora puedo eliminar porque puedo usar la raíz de la sombra como mi shell :hostEsta es una buena manera de reducir el marcado.

Puedes hacer selectores de descendientes desde :hostpero solo se puede acceder a los descendientes dentro del shadow DOM, nada que se haya incrustado en su componente web (sin usar ::slotted).

dijo eso :host no un zombi con un truco. También puede tomar un parámetro, como un selector de clase, y solo aplicará un estilo si la clase está presente.

:host(.high) {
  border: 2px solid blue;
}

Esto le permite realizar cambios si se agregan ciertas clases al elemento personalizado.

También puede pasar pseudoclases allí, como :host(:last-child) y :host(:hover).

EN :host-context pseudo-clase

Ahora hablemos de :host-context.Es como nuestro amigo :host()pero con esteroides :host obtiene una raíz sombría, no le dirá nada sobre el contexto en el que vive el elemento personalizado o su padre y predecesores.

:host-contextpor otro lado, lanza las restricciones de viento, lo que te permite seguir el árbol DOM por el arco iris hasta el duende en el leotardo. Solo tenga en cuenta que mientras escribo esto, :host-context no es compatible con Firefox o Safari. Así que utilízalo para una mejora progresiva.

Así es como funciona. Dividiremos nuestra lista de perfiles de zombis en dos divs. El primer div tendrá todos los partidos con un alto nivel de zombis. .bestmatch clase. El segundo div contendrá todas las coincidencias de amor medias y bajas con un .worstmatch clase.

<div class="profiles bestmatch">
  <zombie-profile class="high">
    <!-- etc. -->
  </zombie-profile>
  <!-- more profiles -->
</div>

<div class="profiles worstmatch">
  <zombie-profile class="medium">
    <!-- etc. -->
  </zombie-profile>
  <zombie-profile class="low">
    <!-- etc. -->
  </zombie-profile>
  <!-- more profiles -->
</div>

Digamos que queremos aplicar diferentes colores de fondo a .bestmatch y .worstmatch clases No podemos hacer esto solos :host:

:host(.bestmatch) {
  background-color: #eef;
}
:host(.worstmatch) {
  background-color: #ddd;
}

Esto se debe a que nuestras mejores y peores clases coincidentes no están en nuestros artículos personalizados. Lo que queremos es poder elegir los elementos principales de los perfiles DOM sombreados. :host-context pasa el elemento de usuario a coincide las clases para los partidos que queremos diseñar.

:host-context(.bestmatch) {
  background-color: #eef;
}
:host-context(.worstmatch) {
  background-color: #ddd;
}


Bueno, gracias por pasar el rato a pesar del mal aliento. (Sé que no se puede decir, pero arriba cuando hablé de Tuya un respiro del que hablé en secreto Mia respiración.)

¿Cómo usarías ::part, ::slotted, :defined, :hosty :host-context en su componente web? Dime en los comentarios. (O si tiene medicamentos para la halitosis crónica, mi esposa estará mucho Me interesa saber más.)

Deja una respuesta

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

Botón volver arriba