Créez une fenêtre modale avec CSS et jQuery

| Soh Tanaka | Didier Mouronval (mise à jour) |

Traducteur

Didier Mouronval

Cet article est la traduction de l'article : inline Modal Window w/ CSS and jQuery. Retrouvez toutes les traductions de Soh Tanaka disponibles sur https://sohtanaka.developpez.com/.

Tout au long de cet article, l'auteur vous présente une méthode permettant de créer une popup CSS du même style que celles utilisées par la bibliothèque Lightview.
Commentez ♪

- Titre : Créez une fenêtre modale avec CSS et jQuery

- Auteurs : Soh Tanaka, Didier Mouronval (mise à jour)

- Traducteur : Didier Mouronval

- Parution : 4 mars 2011

- Mise à jour : 10 février 2013

- Licence : Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright ® 2011 Soh Tanaka. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- Présentation

- La structure HTML

- La mise en forme avec le CSS

- Mise en place de jQuery

- La touche finale : le code jQuery

- Démo et conclusion

- Mise à jour février 2013

- La structure HTML

- Le code jQuery

- Remerciements

Présentation

Il existe de nombreux scripts de fenêtres modales (de type pop-up) simples à implémenter et élégantes. Mais la plupart du temps, ces scripts peuvent rentrer en conflit avec la logique propre de la page.
J'ai été récemment confronté à un cas où il m'était impossible d'utiliser les scripts comme fancybox ou prettyPhoto. J'ai donc dû développer ma propre fenêtre modale pour y insérer du code (X)HTML.
Je vais vous expliquer comment j'ai procédé.

Voir une démo en ligne

Voir la démo en ligne

La structure HTML

Commençons par ajouter une balise <a> avec les attributs suivants :

- href - #?w=500 : spécifie la largeur de la fenêtre ;

- rel : définit la relation avec la pop-up à ouvrir ;

- class="poplight" : classe CSS pour gérer les pop-up.

<a href="#?w=500" rel="popup_name" class="poplight">En savoir plus</a>

Ensuite, nous ajoutons le code (X)HTML des fenêtres.
Vous pouvez les placer où vous voulez dans la page, pour ma part, j'ai opté pour les mettre en fin de code.
Notez bien que l'attribut id correspond à l'attribut rel de la balise <a>. Cela permet d'établir la relation entre le lien et la fenêtre correspondante.

<div id="popup_name" class="popup_block">
<h2>Developpez.com</h2>
<p>Soh Tanaka est traduit sur developpez.com.</p>
</div>

La mise en forme avec le CSS

Le code CSS est commenté afin de vous expliquer comment il fonctionne.
Notez que nous ne précisons pas le margin pour la classe .popup_block : comme la taille de la fenêtre peut varier, c'est jQuery qui le calculera à l'étape suivante.

#fade { /*--Masque opaque noir de fond--*/
display: none; /*--masqué par défaut--*/
background: #000;
position: fixed; left: 0; top: 0;
width: 100%; height: 100%;
opacity: .80;
z-index: 9999;
}
.popup_block{
display: none; /*--masqué par défaut--*/
background: #fff;
padding: 20px;
border: 20px solid #ddd;
float: left;
font-size: 1.2em;
position: fixed;
top: 50%; left: 50%;
z-index: 99999;
/*--Les différentes définitions de Box Shadow en CSS3--*/
-webkit-box-shadow: 0px 0px 20px #000;
-moz-box-shadow: 0px 0px 20px #000;
box-shadow: 0px 0px 20px #000;
/*--Coins arrondis en CSS3--*/
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
}
img.btn_close {
float: right;
margin: -55px -55px 0 0;
}
/*--Gérer la position fixed pour IE6--*/
*html #fade {
position: absolute;
}
*html .popup_block {
position: absolute;
}

Mise en place de jQuery

Pour ceux qui ne sont pas familiers avec jQuery, je vous invite à mieux connaitre cette librairie sur leur site pour comprendre comment elle fonctionne.

Vous pouvez choisir de télécharger ou de le charger depuis le site Google.

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js"></script>

Après avoir chargé jQuery, vous pouvez ouvrir une nouvelle balise <script> et commencer votre code avec l'événement $(document).ready, ce qui permet au code jQuery d'être exécuté dès que le DOM est disponible.
Le reste du code nécessaire au script s'y trouvera.

$(document).ready(function() {
//Le code ici
});

La touche finale : le code jQuery

Le code suivant est commenté pour vous permettre de comprendre le fonctionnement du script.

//Lorsque vous cliquez sur un lien de la classe poplight et que le href commence par #
$('a.poplight[href^=#]').click(function() {
var popID = $(this).attr('rel'); //Trouver la pop-up correspondante
var popURL = $(this).attr('href'); //Retrouver la largeur dans le href

//Récupérer les variables depuis le lien
var query= popURL.split('?');
var dim= query[1].split('&amp;');
var popWidth = dim[0].split('=')[1]; //La première valeur du lien

//Faire apparaitre la pop-up et ajouter le bouton de fermeture
$('#' + popID).fadeIn().css({
'width': Number(popWidth)
})
.prepend('<a href="#" class="close"><img src="close_pop.png" class="btn_close" title="Fermer" alt="Fermer" /></a>');

//Récupération du margin, qui permettra de centrer la fenêtre - on ajuste de 80px en conformité avec le CSS
var popMargTop = ($('#' + popID).height() + 80) / 2;
var popMargLeft = ($('#' + popID).width() + 80) / 2;

//On affecte le margin
$('#' + popID).css({
'margin-top' : -popMargTop,
'margin-left' : -popMargLeft
});

//Effet fade-in du fond opaque
$('body').append('<div id="fade"></div>'); //Ajout du fond opaque noir
//Apparition du fond - .css({'filter' : 'alpha(opacity=80)'}) pour corriger les bogues de IE
$('#fade').css({'filter' : 'alpha(opacity=80)'}).fadeIn();

return false;
});

//Fermeture de la pop-up et du fond
$('a.close, #fade').live('click', function() { //Au clic sur le bouton ou sur le calque...
$('#fade , .popup_block').fadeOut(function() {
$('#fade, a.close').remove();  //...ils disparaissent ensemble
});
return false;
});

Démo et conclusion

Voir la démo en ligne

Voir la démo en ligne

Si vous êtes à l'aise avec jQuery et que vous voyez des améliorations à apporter au code, n'hésitez pas à les proposer.
À l'inverse, si vous êtes débutant et que des points ne vous semblent pas clairs, faites la demande sur le forum.
Commentez

Mise à jour février 2013

Depuis la première publication de cet article très populaire, jQuery a beaucoup évolué et le code de la démonstration est devenu incompatible avec les versions les plus récentes de la bibliothèque.
Il nous a donc paru utile de le mettre à jour. Cependant, nous avons souhaité respecter au maximum le script initial tout en rendant la page compatible avec les standards actuels.

La structure HTML

Nous avons passé le code HTML en HTML5.
Peu de choses ont évolué si ce n'est le doctype et la déclaration de charset.
Cependant, la modification la plus importante va permettre d'avoir un code jQuery plus concis : nous avons décidé de ne plus utiliser l'attribut rel ni l'attribut href pour déterminer quelle popup devra être ouverte ainsi que ses dimensions, en effet, ces attributs ne sont pas destinés à ce genre d'information et rendent la page sémantiquement fausse.
À la place, nous utiliserons les attributs data-* de HTML5. data-width correspondra aux dimensions voulues, data-rel à l'identifiant de la popup à afficher.

Voici comment se présentent désormais les liens :

<a href="#" data-width="500" data-rel="popup1" class="poplight">Voir la pop-up - Width = 500px</a>

Le code jQuery

Le code jQuery correspond à la version 1.9.1 qui est la dernière disponible au moment de cette mise à jour, elle est chargée depuis le CDN de jQuery :

<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>

La modification majeure consiste à remplacer les affectations d'événements (.click() et surtout .live()) par la méthode recommandée .on().

Le code jQuery complet est le suivant :

jQuery(function($){

//Lorsque vous cliquez sur un lien de la classe poplight
$('a.poplight').on('click', function() {
var popID = $(this).data('rel'); //Trouver la pop-up correspondante
var popWidth = $(this).data('width'); //Trouver la largeur

//Faire apparaitre la pop-up et ajouter le bouton de fermeture
$('#' + popID).fadeIn().css({ 'width': popWidth}).prepend('<a href="#" class="close"><img src="close_pop.png" class="btn_close" title="Close Window" alt="Close" /></a>');

//Récupération du margin, qui permettra de centrer la fenêtre - on ajuste de 80px en conformité avec le CSS
var popMargTop = ($('#' + popID).height() + 80) / 2;
var popMargLeft = ($('#' + popID).width() + 80) / 2;

//Apply Margin to Popup
$('#' + popID).css({
'margin-top' : -popMargTop,
'margin-left' : -popMargLeft
});

//Apparition du fond - .css({'filter' : 'alpha(opacity=80)'}) pour corriger les bogues d'anciennes versions de IE
$('body').append('<div id="fade"></div>');
$('#fade').css({'filter' : 'alpha(opacity=80)'}).fadeIn();

return false;
});

//Close Popups and Fade Layer
$('body').on('click', 'a.close, #fade', function() { //Au clic sur le body...
$('#fade , .popup_block').fadeOut(function() {
$('#fade, a.close').remove();
}); //...ils disparaissent ensemble

return false;
});

});

Vous noterez que le script est initié avec jQuery(function($){...});. Cette notation correspond à $(document).ready(function(){});, la différence est que jQuery permet d'éviter tout conflit de nommage pour la fonction $() utilisée par de nombreux scripts et bibliothèques. La fonction de rappel anonyme appelée par l'événement .ready() prend en paramètre l'objet jQuery, vous pouvez dons le nommer ($) afin de pouvoir l'utiliser à l'intérieur de la fermeture (closure).

La méthode .on() prend au minimum deux paramètres : le type d'événement à écouter et le code à exécuter lorsque l'événement est déclenché.
Dans la seconde version, un troisième paramètre vient s'intercaler entre les deux précédents. Si cet argument correspond à un sélecteur, alors c'est sur les éléments correspondant à ce sélecteur que sera affecté l'événement, même s'ils ne sont pas présents dans le DOM au moment de la déclaration. Il s'agit de la délégation d'événements.

Le second événement est affecté à la balise <body>, en effet, nous souhaitons que lors du clic sur le masque opaque, la popup disparaisse, or ce masque opaque est ajouté directement dans le body, c'est donc la balise la plus proche contenant tous les éléments sur lesquels nous souhaitons déléguer des événements.

Si nous avions souhaité que seuls les clics sur les croix ferment les popups, alors nous aurions pu les encapsuler dans un élément commun et affecter la délégation sur cet élément.

Voir la démonstration pour cette version : exemple modifié

Remerciements

Ce tutoriel a été traduit avec l'aimable autorisation de Soh Tanaka.

Merci à ClaudeLELOUP pour sa relecture attentive et efficace.