Sélection d'éléments parents avec CSS et jQuery

Il y a eu des occasions où j'ai souhaité pouvoir sélectionner un élément parent avec CSS - et je ne suis pas seul à ce sujet. Cependant, il n’existe pas de Sélecteur de parents en CSS, donc ce n'est tout simplement pas possible pour le moment.

Dans ce didacticiel, nous allons passer en revue quelques cas où un sélecteur de parents CSS pourrait s'avérer utile, ainsi que des solutions de contournement possibles. Commençons!

Attendez, c'est quoi un sélecteur de parents?

Les sélecteurs CSS nous permettent de cibler des éléments, en descendant et à travers l’arborescence DOM, en devenant plus spécifiques. Voici un exemple du type de sélecteur que vous pouvez trouver dans Bootstrap. Il parcourt l’arborescence DOM à partir du nav.navbar-dark élément, à la ul, la li, puis finalement le a.nav-link.

.navbar-dark .navbar-nav .nav-item .nav-link 

 Un sélecteur de parents nous permettrait de revenir en haut le DOM, ciblant les éléments parents de certaines choses. Par exemple, nous pourrions cibler le parent de .nav-link éléments en utilisant:

.nav-link :: parent 

Remarque: Cet exemple est du pseudo-code pur, il n’existe ni ne suggère la meilleure syntaxe possible!

Cas 1: style du contenu hérité

Le style du contenu hérité, avec la structure et le balisage datés, est un défi classique lors de la refonte d'un site Web. Avant HTML5, par exemple, une image pouvait généralement être encapsulée avec un p, div, ou parfois avec un envergure avec un imbriqué p utilisé pour envelopper la légende de l'image. Il n'y avait pas de moyen standard pour envelopper une image et une légende. Plus tard, nous avons adopté le figure et figcaption éléments, rendant notre structure de document plus sémantique.

Nous voulons que les images du contenu hérité apparaissent comme ci-dessus. Mais comme il peut y avoir plus div balises dans notre document, celles qui ne contiennent pas d'images du tout, les déclarations de style suivantes seraient complètement impraticables.

.page-content div padding: 15px; couleur de fond: # f3f3f3; marge: 10px 0 20px;  .page-content div img marging: 0 0 10px;  .page-content div .img-caption color: # 999; taille de police: 12px; text-align: center; Wisplay: bloquer; 

Il appliquerait la couleur d'arrière-plan, le remplissage et les marges à tous les éléments div du contenu. Nous voulons réellement appliquer ces styles exclusivement à div éléments qui enveloppent une image et une légende.

Cas 2: Maintien du ratio vidéo

Un autre exemple concerne le maintien du ratio de vidéo intégrée (comme de Youtube ou de Vimeo), ainsi que la fluidification de la vidéo. Ces jours-ci, en grande partie grâce au travail d'enquête de Dave Rupert et de ses amis, il est largement admis que la meilleure approche consiste à appliquer rembourrage ou rembourrage en bas à l'élément parent.

Extrait de code tiré de CSS-Tricks: vidéo de largeur fluide

Dans un monde réel, cependant, nous ne saurions peut-être pas quel élément contient la vidéo. Il se peut que nous trouvions de la vidéo intégrée dans un div ou un p sans nom de classe identifiable, ce qui rend difficile la sélection du bon élément sur lequel appliquer les styles. 

Par conséquent, déclarer les styles comme suit n’est pas pratique dans la mesure où cela aura un impact sur tous les div du .Contenu de la page y compris ceux qui ne contiennent pas de vidéo intégrée.

.contenu de la page width: 560px; marge droite: auto; marge gauche: auto; marge supérieure: 30px;  .page-content div position: relative; rembourrage en bas: 56,25%;  .page-content div iframe position: absolute; en haut: 0; largeur: 100%; hauteur: 100%; 

Comme il serait merveilleux de sélectionner directement l'élément parent de la vidéo!

Cas 3: Répondre à la saisie du formulaire

Dans cet exemple, nous avons un formulaire avec plusieurs entrées. Lorsque nous nous concentrons sur l'une des entrées, une couleur de bordure plus prononcée lui est attribuée, soulignant la position de l'utilisateur dans le formulaire..

Parfois, vous pouvez également rencontrer la situation où non seulement la couleur de la bordure, mais aussi l'élément enveloppant l'entrée sont mis en surbrillance, ce qui la rend encore plus visible:

Focus formulaire de saisie.

L'élément parent pourrait être un div ou un p. Alors, comment pouvons-nous correctement sélectionner l'élément parent en fonction de certains états de ses descendants?

Solutions de contournement possibles

Comme nous l’avons vu, il n’existe pas de sélecteur de parents, donc choisir un parent n'est pas possible. Nous pourrions être tentés de contourner le problème en reconsidérant complètement la conception afin d'éviter de sélectionner le parent. Mais si cela n’est pas possible, voici quelques approches potentielles..

Utiliser CSS :a() Sélecteur 

le :a Le sélecteur est officiellement désigné sous le nom de pseudo-classe relationnelle. Il fait correspondre les éléments en fonction de leurs descendants, qui sont définis entre les parenthèses. 

Dans l'exemple suivant, il applique une Couleur de fond à tout div contenant une légende d'image. Cela semble concerner le cas 1.

.page-content div: has (.img-caption) padding: 15px; couleur de fond: #ccc; 

Ou, si nous voulons être plus précis, nous pouvons le réécrire pour correspondre à tout div tag avec le .img-caption comme le direct descendant.

.page-content div: has (> .img-caption) padding: 15px; couleur de fond: #ccc; 

Ce sélecteur est rédigé pour CSS Selector Level 4 bien qu'aucun navigateur ne l'implémente pour le moment. Nous devrons attendre un peu plus longtemps avant que ce sélecteur n'apparaisse. En attendant, jetez un coup d'œil au cours vidéo suivant intitulé CSS of the Future pour découvrir comment fonctionne le sélecteur:

  • Le: a pseudo-classe
  • Combinant: a et: non

Utilisation du sélecteur de parent jQuery

Aucune solution CSS unique ne peut résoudre nos problèmes ici, voyons donc ce que JavaScript peut faire pour nous à la place. Dans cet exemple, nous allons utiliser jQuery pour ses API robustes, sa commodité et sa compatibilité avec les navigateurs. Au moment de l'écriture, jQuery fournit trois méthodes pour sélectionner les éléments parents.

parent(); cette méthode sélectionne le parent immédiat de l'élément ciblé. Nous pouvons utiliser cette méthode pour traiter tous les cas d'utilisation mentionnés plus haut dans le didacticiel..

Structure d'image dans le contenu hérité.

Par exemple, nous pouvons utiliser parent() ajouter une classe spéciale à l'élément d'habillage des images dans le contenu.

$ (".img-caption") .parent () .addClass ("has-img-caption"); 

Le code ci-dessus sélectionnera l’élément immédiat qui enveloppe l’image, quel que soit le type d’élément, en ajoutant le has-img-caption classe pour nous donner plus de contrôle sur la sélection des éléments et les styles, comme suit.

Structure d'image dans le contenu hérité avec une classe supplémentaire.

Parents() remarquez la forme plurielle de cette méthode. Cette méthode nous permet de sélectionner les éléments parents de l’immédiat à la racine du document, à moins qu’un sélecteur est spécifié comme argument.

$ (".img-caption") .parents () .addClass ("has-img-caption"); 

Compte tenu de l'exemple ci-dessus, le Parents() méthode sélectionne tout le chemin de la div balise qui enveloppe immédiatement l'image, la prochaine div, et enfin le html, en ajoutant le has-img-caption classe à tous les éléments.

La classe has-img-caption appliquée avec la méthode parents ().

Cet excès est redondant. Le seul élément qui nécessitera probablement l’ajout de la classe, dans ce cas, est l’immédiat div élément. Par conséquent, nous le passons dans l'argument de la méthode.

$ (".img-caption") .parents ("div") .addClass ("has-img-caption"); 

Ici le Parents() Cette méthode parcourt l’arbre des ancêtres de l’image en sélectionnant div trouvé et en lui donnant la has-image-caption classe.

Si cela reste envahissant, vous pouvez réduire la sélection à un seul élément en spécifiant l'index. Dans l'exemple suivant, nous appliquons la classe uniquement à la première div.

var $ parents = $ (".caption") .parents ("div"); $ parents [0] .addClass ("has-img-caption"); // sélectionne la première division add ajoute la classe. 

parentsJusqu'à (); cette méthode sélectionne les éléments parents jusqu'à mais non compris l'élément spécifié entre parenthèses.

$ (".caption") .parentsUntil (".page-content") .addClass ("has-img-caption"); 

Compte tenu du code ci-dessus, il appliquera le has-img-caption classe à tous les éléments parents sauf l'élément avec .Contenu de la page.

Dans certains cas, lorsque vous avez des milliards d'éléments imbriqués, utilisez le parentsJusqu'à () méthode est préférable. Il est comparativement plus rapide que le Parents() Cette méthode évite d’utiliser le moteur de sélection jQuery (Sizzle) pour parcourir l’arborescence DOM complète jusqu’à la racine du document..

Emballer

Sommes-nous susceptibles d'avoir un sélecteur de parent CSS à un moment donné dans l'avenir?

Probablement pas. Le type de sélecteur de parents dont nous avons parlé ci-dessus a été proposé à de nombreuses reprises, mais il n’a jamais dépassé le stade de rédaction du W3C pour plusieurs raisons. Ces raisons se concentrent principalement sur les performances du navigateur, en raison de la manière dont les navigateurs évaluent et rendent les pages. La chose la plus proche que nous aurons à l'avenir est le sélecteur relationnel, :a().

Cependant, depuis le :a() n'est pas encore applicable, JavaScript et jQuery sont actuellement l'approche la plus fiable. Gardez à l'esprit que DOM Traversal est une opération coûteuse qui peut affecter gravement les performances de rendu de votre site. Évitez d'utiliser Parents() ou parentsJusqu'à () avec d'autres opérations lourdes comme animer(), fadeIn () ou disparaître()

Mieux encore, examinez la structure HTML chaque fois que possible pour voir si la sélection de l'élément parent peut être totalement évitée.!

Ressources supplémentaires

  • Sélecteurs CSS de niveau 4 à surveiller
  • Sélecteur CSS pour: ciblage des parents (s'il vous plaît)
  • Pourquoi nous n'avons pas de sélecteur de parents