Quand il s'agit de rendre sur le DOM de quelqu'un d'autre, vous ne pouvez pas écrire naïvement HTML et CSS comme vous le feriez pour votre propre application web autonome. Vous devez bien réfléchir à la manière dont le code CSS et JavaScript préexistant peut affecter votre application.

Avant de commencer à écrire du code HTML ou CSS, vous devrez prendre une décision importante concernant l'apparence de votre application. Voulez-vous que votre application soit la même partout? Ou souhaitez-vous que l'application hérite de l'aspect natif de la page sur laquelle elle est hébergée? Votre réponse aura un impact profond sur votre stratégie de rendu de votre application.

Une chose est constante: à un certain niveau, vous pratiquerez ce que nous appelons un rendu défensif. Par défensif, nous entendons prendre des mesures pour générer du code HTML et CSS afin de minimiser l’impact de la page parente sur votre application. Plus vous voulez que votre widget soit affecté par la page parente, plus vous devrez effectuer de démarches. Ces étapes peuvent être aussi réduites que les noms de fichiers HTML et CSS pour réduire les conflits de noms ou sur-spécifier vos règles CSS pour qu'elles soient prioritaires par rapport aux règles de la page parente. Pour les widgets qui veulent une immunité complète de la page parente, cela peut également signifier servir votre widget sur un DOM complètement séparé, incorporé dans un iframe.

Nous allons nous concentrer sur le rendu HTML et CSS qui vivent sur le même DOM que la page de l'éditeur. Pour les widgets qui visent à offrir un certain niveau de personnalisation, cela peut être la solution la plus flexible pour les éditeurs, puisque l'éditeur peut facilement cibler vos éléments et les personnaliser selon leurs préférences.

Malheureusement, c'est aussi l'inconvénient. L'éditeur peut à son insu disposer de règles CSS et / ou de code JavaScript qui ciblent par inadvertance votre widget et causent des ravages.

Nous examinerons plusieurs façons de protéger le code HTML et CSS de votre application du code de l'éditeur. Tout d'abord, vous apprendrez les espaces de noms HTML et CSS. Ensuite, vous apprendrez à connaître la spécificité CSS et comment les styles de la page parente peuvent remplacer les vôtres.

Enfin, vous apprendrez des techniques pour remplacer les styles parent de la page, en sur-spécifiant votre CSS et en abusant du mot-clé! Important. Tout d'abord, les espaces de noms.

Espaces de noms

Tous les ID DOM, classes, attributs data * et les sélecteurs CSS correspondants ont été préfixés par stork-. Le but? Réduire la probabilité que ces attributs entrent en conflit avec la page parente.

Considérez la situation suivante. Votre widget a un niveau supérieur

élément qui agit comme un conteneur. Cela se fait en définissant une largeur et une hauteur explicites, délimitant efficacement la zone occupée par votre widget. Vous avez donné ceci
un nom de classe simple, conteneur, qui correspond à une règle de style dans votre CSS d'accompagnement:

...

Cela peut être parfaitement approprié pour une application régulière de rester à la maison, mais pour une application tierce, c'est un non-complet complet. La raison? Un tel nom de classe générique a de bonnes chances d'être déjà utilisé par la page parente. Si vous introduisez cette règle de style, vous pouvez remplacer une règle de style existante mise en place par l'éditeur et détruire la mise en page du site. Ou, à l'inverse, leur règle peut remplacer la vôtre et redimensionner votre widget par inadvertance.

La solution? Préfixer tous vos noms de classe (et autres attributs) avec un identifiant unique à votre application, un espace de noms. Dans le cas du widget Stork, le balisage précédent doit être modifié pour ressembler à ceci:

...

L'idée est que vous nommez votre code JavaScript afin de ne pas déclarer les objets globaux en conflit avec le code exécuté sur la page parente. Il s'étend à chaque élément HTML que vous insérez dans la page: identifiants, classes, attributs data- *, noms de formulaire, etc.

Le placement de noms HTML et CSS est indispensable pour toute application tierce qui rend directement la page de l'éditeur. Ce n'est pas seulement nécessaire pour empêcher les règles CSS contradictoires; Il est également concevable que la page parente ait JavaScript qui interroge le DOM pour les éléments dont les propriétés d'identification peuvent correspondre aux vôtres. Soyez rigoureux en nommant tout ce que vous mettez sur le DOM.

Spécificité CSS

Il est important de noter que, bien qu'utile, le placement de votre code HTML et CSS empêche uniquement les éditeurs d'utiliser des styles ou des requêtes faisant référence à des attributs portant le même nom que le vôtre. Malheureusement, votre widget peut toujours entrer en conflit avec les styles définis par la page parent, même si leur CSS utilise des ID, des noms de classe et des attributs qui ne font pas directement référence à vos éléments. Cela est dû au fait que certaines règles CSS sont pesées plus lourdement par le navigateur et peuvent avoir préséance sur des règles apparemment sans rapport que vous pourriez définir. Ce phénomène est appelé spécificité CSS et vous devez le comprendre avant de pouvoir rendre des éléments en toute sécurité sur la page de l'éditeur.

Revenons à l'exemple de conteneur de la section précédente sur les espaces de noms. Supposons que le code HTML de l'éditeur ait une DIV de niveau supérieur qui englobe tout son contenu, avec un ID de page:

...
...

En outre, supposons que la page comporte le code CSS suivant, où la première règle est définie par l'éditeur et la deuxième règle, ciblant stork-container, est ajoutée par votre script tiers:

/* Publisher */#page div {background-color: green;}/* Camera Stork */.stork-container {background-color: blue;}

Maintenant, quelle couleur aura .stork-container? La réponse pourrait vous choquer: vert. Dans cet exemple simple, la règle de l'éditeur (#page div) a priorité sur la règle de classe de votre application tierce (.stork-container). Cela se produit car le navigateur pèse les règles contenant des identifiants supérieurs à ceux qui ciblent les classes ou les attributs.

Priorités des règles CSS

La spécification CSS du W3C décrit comment les navigateurs sont censés hiérarchiser différents types de règles. Voici une liste de ces types de règles, classés de la plus haute priorité à la plus basse:

  1. Styles en ligne (style = "...")
  2. Les identifiants
  3. Classes, attributs et pseudo-classes (: focus,: survol)
  4. Eléments (div, span, etc.) et pseudo-éléments (: before,: after)

Selon ce tableau, les styles en ligne sont pesés au-dessus de tous les types de règles suivants: ID, classes et éléments. Cela continue logiquement dans la liste, avec des identifiants supérieurs aux classes et aux éléments, etc. Il y a une exception à cette liste: les propriétés marquées avec le mot clé! Important ont la plus haute priorité. Mais notez que le mot-clé! Important affecte une propriété unique dans une règle, pas la règle entière.

Que se passe-t-il lorsque vous avez plusieurs règles CSS de même poids, chacune pouvant affecter le même élément? Regardons un exemple:

Eat your vegetables!

D'après vous, quelle est la couleur de la travée? La réponse pourrait être surprenante: jaune. Même si ces règles sont toutes principalement basées sur des classes, la seconde règle (.storkcontainer span) est considérée comme plus spécifique que la première et la troisième (.stork-container .stork-msg) plus spécifique que la seconde. Comment cela marche-t-il?

Les styles en ligne sont roi

En termes de spécificité CSS, c'est. Si vous vous souvenez de plus tôt dans ce chapitre, nous avons mentionné que les styles en ligne ont l'avantage de ne pas être en conflit avec la page parente. Maintenant, il est clair pourquoi: ils sont prioritaires par rapport à tous les autres types de règles CSS standard (à l'exclusion de ceux avec le mot-clé! Important). Si vous écrivez un widget particulièrement simple, ce n'est peut-être pas une mauvaise idée d'utiliser des styles en ligne. vous éviterez la plupart des conflits de spécificité CSS.

Le navigateur utilise un système de notation simple pour déterminer quelle règle est prioritaire. Pour une règle donnée, chaque sélecteur composant cette règle vaut une certaine valeur. Ces valeurs sont additionnées pour créer un score de spécificité. Lorsque plusieurs règles affectent le même élément, le navigateur compare le score de spécificité de chaque règle et la règle ayant le score le plus élevé est prioritaire. En cas d'égalité, la règle définie a été gagnée. Attributs de style en ligne: 1000; ID: 100; classes, pseudo-classes et attributs: 10, éléments et pseudo-éléments: 1.

Ainsi, en revenant à notre exemple précédent, les règles suivantes auraient été attribuées à ces règles CSS, la priorité étant donnée par le navigateur: vous remarquerez rapidement qu’il ne s’agit pas de nombres ordinaires. Un score de spécificité est en fait un tuple de la forme (a, b, c, d), un être ayant plus de valeur que b, b étant plus précieux que c, et ainsi de suite. Cela signifie qu'un style provoqué par un seul attribut de style inline (1, 0, 0, 0) a une spécificité supérieure à celle d'une règle avec cent sélecteurs d'ID (0, 100, 0, 0).

  • .stork-container (sélecteur de classe 0,0,1,0-one)
  • .stork-container span (sélecteur de classe 0,0,1,1-one, sélecteur d'élément)
  • .stork-container .stork-msg (sélecteurs de classes 0,0,2,0)

À ce stade, vous devriez avoir une bonne idée du fonctionnement de la spécificité CSS et de la raison pour laquelle le navigateur hiérarchise certaines règles plutôt que d’autres. Vous mettrez ensuite ces connaissances à profit, alors que nous explorerons certaines méthodes d’écriture de CSS qui font face à des styles de publication contradictoires.

Sur-spécification des CSS

L'approche la plus simple et la plus simple pour écrire des CSS qui n'entre pas en conflit avec la page de l'éditeur consiste à sur-spécifier vos règles. Cela signifie que vous devez déclarer des sélecteurs supplémentaires pour améliorer la spécificité de vos règles, de sorte que lorsque le navigateur compare vos règles avec celles de la page parente, il est probable que ces dernières obtiennent un score plus élevé et une priorité.

Voyons cela en pratique. Considérez cet exemple révisé du conteneur de widgets Stork, maintenant doté de deux éléments de conteneur, chacun avec un identifiant unique:

Mikon E90 Digital SLR

"/>

599 $

4.3 / 5.0 • 176 avis

Le CSS associé à ce HTML pourrait alors ressembler à ceci:

#stork-main #stork-container { ... }#stork-main #stork-container .stork-product { ... }#stork-main #stork-container .stork-price { ... }

En spécifiant de manière redondante les deux ID de conteneur en tant que sélecteurs parents de toutes vos règles CSS, vous attribuez à chacune de vos règles CSS un score de spécificité minimum de (0,2,0,0). Par la suite, la règle #page générique de l'éditeur ne sera plus en conflit avec votre widget, car il n'utilise qu'un seul identifiant. Les règles purement basées sur les classes ou les éléments ne sont pas non plus en conflit, car il s’agit d’une classe de pondération CSS au-dessous des ID. Même si, à des fins de sélection, il n'est absolument pas nécessaire de spécifier un deuxième identifiant pour vos règles, cela fonctionne ici comme un dispositif efficace pour améliorer la spécificité.

Préservez votre santé mentale avec un préprocesseur CSS

L'écriture de CSS sur-spécifiés peut être un véritable frein: vous devez constamment réécrire les mêmes identifiants pour chacune de vos règles CSS. Vous pouvez remédier à cela en utilisant un préprocesseur CSS, qui étend le langage CSS avec des fonctionnalités supplémentaires telles que la possibilité de déclarer des hiérarchies de règles imbriquées. Par exemple, en utilisant le préprocesseur CSS LESS, vous pouvez écrire l'exemple précédent comme ceci:

#stork-main {#stork-container {.stork-product { ... }.stork-price { ... }}}

Un certain nombre de préprocesseurs CSS populaires sont disponibles aujourd’hui, tous ayant des ensembles de fonctionnalités différents. Parmi les plus populaires sont MOINS,Toupet, et Style.

D'un autre côté, cet exemple nécessite que votre widget utilise des conteneurs de niveau supérieur avec des ID, ce qui ne sera pas pratique pour les widgets pouvant être rendus plusieurs fois sur la même page. En outre, il n’est toujours pas à toute épreuve: un éditeur peut suivre votre exemple et sur-spécifier ses propres règles CSS, ce qui entraîne le même problème que vous.

Mais c'est un scénario peu probable, d'autant plus que vous avez spécifié de manière redondante deux identifiants dans chacune des règles. Vous pouvez également en utiliser un, mais cela sera bien sûr plus vulnérable. La réalité est que la plupart des éditeurs utilisent des règles CSS saines et que la sur-spécification de vos règles comme celle-ci sera compatible avec la plupart d'entre elles.

La sur-spécification des CSS ne se mélange pas avec les outils de qualité du code

Si vous décidez de sur-spécifier votre CSS comme celui-ci, vous pourriez trouver un ennemi improbable: des outils qui évaluent la qualité de votre code CSS, tels que CSS Lint, Google Page Speed ​​et Yahoo YSlow. Ces outils indiquent que vous faites des sélecteurs CSS redondants et ils vous conseillent de supprimer ces sélecteurs pour réduire la taille des fichiers et améliorer les performances CSS des navigateurs. Malheureusement, ces outils ne sont pas programmés en gardant à l'esprit des scripts tiers et n'évaluent pas équitablement l'utilité de la sur-spécification des CSS. Les avantages de la sur-spécification pour les applications tierces l'emporteront sur la taille de fichier supplémentaire et les performances minuscules.

Abusant! Important

Si vous pensez que la sur-spécification de votre CSS avec des sélecteurs d’ID ou de classe supplémentaires ne va pas assez loin, vous pouvez sortir de l’option nucléaire: le mot-clé! Les propriétés d'une règle CSS portant le mot-clé! Important ont la priorité la plus élevée, même au-dessus des styles en ligne. En effet, le mot clé! Important a été conçu pour donner aux utilisateurs du navigateur un moyen sûr de remplacer les styles "auteur" (éditeur), dans le cas de plug-ins de navigateur ou de styles spécifiques à un site. Vous pouvez en abuser en l'utilisant sur toutes vos propriétés CSS, en les hiérarchisant efficacement par rapport à toutes les autres règles.

Voici comment utiliser le mot clé! Important sur une seule règle CSS:

.stork-price {font-size: 11px !important;color: #888 !important;text-decoration: none !important;display: block !important;}

Comme il s'agit d'une propriété, le mot-clé! Important doit être répété comme cela, ce qui peut entraîner un glissement sur une feuille de style longue et complexe. Mais en échange, vous obtenez un ensemble de feuilles de style solides qui ne seront probablement pas réinitialisées par la page de l'éditeur.

Il est encore concevable que l'éditeur puisse à son tour utiliser! Important de cibler vos éléments et de définir leurs propres styles, à quel point ils ciblent volontairement vos éléments pour les personnaliser. D'une part, cela peut être frustrant si vous essayez de maintenir une apparence cohérente. Mais si vous avez décidé d’autoriser les éditeurs à personnaliser votre widget, c’est probablement le comportement souhaité.

Une chose devrait être claire: le partage du DOM avec l'éditeur peut rendre particulièrement difficile le rendu d'un widget de style cohérent. Bien que vous puissiez prendre des mesures pour sur-spécifier vos règles CSS afin de réduire le risque de conflits, l'éditeur peut toujours cibler vos éléments avec leurs règles, de manière accidentelle ou délibérée.

Mais si partager le DOM avec l'éditeur est ce qui cause tant de chagrin, est-il possible de rendre votre widget hors du DOM? Pourquoi oui, oui, vous pouvez.

Résumé

Pour une application JavaScript tierce, l'injection de HTML et de CSS dans la page de l'éditeur nécessite plus de soin que si vous ajoutiez un balisage à un environnement "sécurisé". Vous devez vous assurer que lors de la sortie HTML vers la page, vous ne ralentissez pas la page avec une opération de blocage. Vous devez également tenir compte du fait que votre script peut être inclus plusieurs fois sur la même page, et qu'il doit rendre plusieurs instances avec élégance. En outre, vous devriez choisir une méthode optimale pour injecter des CSS dans la page de l'éditeur, soit en insérant tous vos styles, en ajoutant des éléments de lien ou en incorporant des règles CSS dans votre code JavaScript.

Mais il ne suffit pas d’obtenir HTML et CSS sur la page. Vous devez reconnaître que les éléments que vous introduisez dans le DOM peuvent entrer en conflit avec la page parente. Vous devez également tenir compte de la manière dont vos styles peuvent entrer en conflit avec les styles existants définis par l'éditeur. Vous pouvez utiliser un certain nombre de techniques pour réduire l'impact des styles parents sur votre widget: en sur-spécifiant vos règles CSS ou en présentant votre contenu derrière un iframe, qu'il s'agisse d'un iframe sans src ou d'un document HTML externe.

Quelles techniques utilisez-vous pour produire des fichiers CSS et HTML pour des tiers? Vous êtes-vous déjà replié sur! Important? Faites le nous savoir dans les commentaires.

Image / vignette en vedette, image de défense via Shutterstock.