J'essaye d'utiliser l'élément dialog
.
Lorsque la boîte de dialogue / modale est fermée, le corps doit pouvoir faire défiler.
Lorsque la boîte de dialogue / modale est ouverte, si son contenu est volumineux, la boîte de dialogue / modal doit pouvoir faire défiler.
Cependant, lorsque le dialogue / modal est ouvert, je ne veux pas que le scroll s'applique à la fois au dialogue / modal et l'arrière-plan du corps, ce qu'il semble faire par défaut.
/ p>
Exemple: https://output.jsbin.com/mutudop/3 . < / p>
Comment puis-je faire en sorte que le défilement s'applique uniquement au contenu de la boîte de dialogue / modal, lorsque la boîte de dialogue / modale est ouverte?
Remarque: je ne suis intéressé que par les solutions utilisant l'élément natif dialog
.
3 Réponses :
J'ai créé un autre exemple où votre contenu principal ne fait pas défiler avec votre modal s'il est plus grand que votre contenu principal. Vous pouvez définir position
sur fixed
sur votre conteneur pour y parvenir.
<div id="container"> <dialog id="my-dialog"> <div id="my-dialog__content"> <form method="dialog"> <menu> <button id="cancel-button" value="cancel">Cancel</button> </menu> </form> </div> </dialog> <menu> <button id="open-dialog">Open Dialog</button> </menu> </div>
#my-dialog { width: 50%; max-height: 50vh; overflow-y: auto; } #my-dialog__content { display: flex; flex-direction: column; height: 150vh; } menu { width: 100%; padding: 0; margin: 0 auto; } #cancel-button { width: 100% }
(function() { var openBtn = document.getElementById('open-dialog'); var myDialog = document.getElementById('my-dialog'); openBtn.addEventListener('click', function() { if (typeof myDialog.showModal === "function") { myDialog.showModal(); } else { alert("Dialog API not supported by browser"); } }); })();
Réponse d'origine
Vous pouvez définir une hauteur max
sur votre boîte de dialogue et styliser le contenu de votre boîte de dialogue en conséquence. Voir l'exemple ci-dessous.
<div id="container"> <dialog id="my-dialog"> <div id="my-dialog__content"> <form method="dialog"> <menu> <button id="cancel-button" value="cancel">Cancel</button> </menu> </form> </div> </dialog> <menu> <button id="open-dialog">Open Dialog</button> </menu> </div>
#container { height: 100vh; width: 100vw; position: fixed; top: 0; left: 0; background: #ccc; } #my-dialog { margin-top: 1rem; margin-bottom: 3rem; top: 3rem; width: 50%; overflow-y: auto; } #my-dialog__content { display: flex; flex-direction: column; height: 200vh; } menu { width: 100%; padding: 0; margin: 0 auto; } #cancel-button { width: 100% }
(function() { var openBtn = document.getElementById('open-dialog'); var myDialog = document.getElementById('my-dialog'); openBtn.addEventListener('click', function() { if (typeof myDialog.showModal === "function") { myDialog.showModal(); } else { alert("Dialog API not supported by browser"); } }); })();
Très intéressant. Que faire si je veux que le défilement fonctionne non pas à l'intérieur du modal mais à l'extérieur, c'est-à-dire faire défiler la superposition? Vous pouvez voir l'effet souhaité en accédant à unsplash.com/photos/bQ-XtB9IWmo?force_page_modal < / a>.
Je vois. Je viens de mettre à jour ma réponse. Faites-moi savoir si c'est ce que vous recherchiez.
Cela fonctionne, mais cela ne préserve pas le défilement de l'arrière-plan du modal lorsque le modal est fermé. Dans mon exemple d'origine, l'arrière-plan modal a une grande quantité de contenu, qui devrait pouvoir faire défiler mais uniquement lorsque le modal est fermé. Désolé, je n'ai pas clarifié cela dans mon message d'origine. Je vais mettre à jour ma question.
Une solution simple est la suivante: une fois que le mnodel est affiché, créez un DIV de plus en superposition qui couvre le plein écran, à cet endroit css {pointer-events: none} et le modèle sera placé dessus. l'utilisateur ne peut pas cliquer sur le contenu du corps autre que les données du modèle.
J'ai créé un exemple: http://jsfiddle.net / z3sgvnox /
(function() { var openBtn = document.getElementById('open-dialog'); var myDialog = document.getElementById('my-dialog'); var bodyData = document.getElementById('content-body'); openBtn.addEventListener('click', function() { if (typeof myDialog.showModal === "function") { myDialog.showModal(); bodyData.classList.add("hideScroll"); } else { alert("Dialog API not supported by browser"); } }); })();
CSS
#container { height: 100vh; width: 100vw; position: fixed; top: 0; left: 0; background: #ccc; } #my-dialog { margin-top: 1rem; margin-bottom: 3rem; width: 50%; overflow-y: auto; max-height: 80%; } .hideScroll{ overflow:hidden; pointer-events:none; } #my-dialog__content { display: flex; flex-direction: column; height: 200vh; } menu { width: 100%; padding: 0; margin: 0 auto; } #cancel-button { width: 100% }
JS:
<body id="content-body"> <div id="container"> <dialog id="my-dialog"> <div id="my-dialog__content"> <form method="dialog"> <menu> <button id="cancel-button" value="cancel">Cancel</button> </menu> </form> </div> </dialog> <menu> <button id="open-dialog">Open Dialog</button> </menu> </div> </body>
Je l'ai donc essayé également et j'ai trouvé ceci:
<div class="wrapper"> <dialog> <div> <form method="dialog"> <button value="cancel">Cancel</button> </form> </div> </dialog> <button id="open">Open Dialog</button> </div>
* { box-sizing: border-box; } .wrapper { height: 10000px; } dialog { width: 100%; height: 100%; padding: 0; margin: 0; border: 0; z-index: 100; background: transparent; overflow-y: auto; } dialog>div { width: 50%; height: 500px; background: white; border: 3px solid black; margin: 0 auto; margin-top: 50px; } .overflow-hidden { overflow: hidden; }
(function() { var openBtn = document.querySelector("button#open"); var myDialog = document.querySelector("dialog"); openBtn.addEventListener('click', function() { if (typeof myDialog.showModal === "function") { myDialog.showModal(); } else { alert("Dialog API not supported by browser"); } }); })();
Vous avez peut-être remarqué que j'ai ajouté deux lignes de JS pour masquer / afficher le débordement
du body
et vous en aurez probablement besoin comme vous pouvez ne ciblez pas le body
avec du CSS pur si vous voulez vérifier si la boîte de dialogue
est ouverte ou non.
Si vous ne le faites pas les voulez, vous pouvez les supprimer et cela fonctionne très bien. Cependant, vous aurez deux barres de défilement sur le côté droit. Voici à quoi cela ressemble sans le JS:
<div class="wrapper"> <dialog> <div> <form method="dialog"> <button onclick='document.body.classList.remove("overflow-hidden");' value="cancel">Cancel</button> </form> </div> </dialog> <button id="open">Open Dialog</button> <h4>You can scroll the body now but not when the dialog is opened.</h4> </div>
* { box-sizing: border-box; } .wrapper { height: 10000px; } dialog { width: 100%; height: 100%; padding: 0; margin: 0; border: 0; z-index: 100; background: transparent; overflow-y: auto; } dialog>div { width: 50%; height: 500px; background: white; border: 3px solid black; margin: 0 auto; margin-top: 50px; } .overflow-hidden { overflow: hidden; }
(function() { var openBtn = document.querySelector("button#open"); var myDialog = document.querySelector("dialog"); openBtn.addEventListener('click', function() { if (typeof myDialog.showModal === "function") { myDialog.showModal(); document.querySelector("body").classList.add("overflow-hidden"); } else { alert("Dialog API not supported by browser"); } }); })();
Si vous avez besoin d'explications, faites-le moi savoir mais je pense que le code devrait être explicite.
N'oubliez pas que les boîtes de dialogue peuvent être fermées avec la touche d'échappement, vous devriez donc probablement avoir un code comme celui-ci: myDialog.addEventListener ("keydown", (e) => {if (e.keyCode === 27 ) {document.body.classList.remove ("overflow-hidden");}});
Hé, je pense que certains commentaires seraient bien. Pour autant que je puisse le voir, vous n'avez pas répondu à 2 réponses jusqu'à présent. Ils ont besoin de savoir si leurs réponses résolvent votre question ou si la réponse / votre question est / n'est plus pertinente.