Comment réinitialiser l'échelle / le zoom d'une application Web lors d'un changement d'orientation sur l'iPhone?


96

Lorsque je lance mon application en mode portrait, cela fonctionne correctement. Ensuite, je tourne en paysage et il est agrandi. Pour le mettre à l'échelle correctement pour le mode paysage, je dois taper deux fois sur quelque chose deux fois, d'abord pour zoomer complètement (le comportement normal de double tap) et encore pour zoomer complètement (encore une fois, le comportement normal de double tap) . Lorsqu'il effectue un zoom arrière, il effectue un zoom arrière à la NOUVELLE échelle correcte pour le mode paysage.

Le retour au portrait semble fonctionner de manière plus cohérente; c'est-à-dire qu'il gère le zoom afin que l'échelle soit correcte lorsque l'orientation revient au portrait.

J'essaye de savoir s'il s'agit d'un bug? ou si c'est quelque chose qui peut être corrigé avec JavaScript?

Avec le méta-contenu de la fenêtre d'affichage, je mets l'échelle initiale à 1,0 et je ne mets PAS d'échelle minimale ou maximale (et je ne veux pas). Je règle la largeur sur la largeur de l'appareil.

Des idées? Je sais que beaucoup de gens seraient reconnaissants d'avoir une solution car cela semble être un problème persistant.


1
Une solution parfaite: pas de javascript! stackoverflow.com/a/8727440/805787
Steeven

Réponses:


89

Jeremy Keith ( @adactio ) a une bonne solution pour cela sur son blog Orientation et échelle

Gardez le balisage évolutif en ne définissant pas d'échelle maximale dans le balisage.

<meta name="viewport" content="width=device-width, initial-scale=1">

Désactivez ensuite l'évolutivité avec javascript au chargement jusqu'au démarrage du geste lorsque vous autorisez à nouveau l'évolutivité avec ce script:

if (navigator.userAgent.match(/iPhone/i) || navigator.userAgent.match(/iPad/i)) {
    var viewportmeta = document.querySelector('meta[name="viewport"]');
    if (viewportmeta) {
        viewportmeta.content = 'width=device-width, minimum-scale=1.0, maximum-scale=1.0, initial-scale=1.0';
        document.body.addEventListener('gesturestart', function () {
            viewportmeta.content = 'width=device-width, minimum-scale=0.25, maximum-scale=1.6';
        }, false);
    }
}

Mise à jour 22-12-2014:
Sur un iPad 1, cela ne fonctionne pas, cela échoue sur l'écouteur d'événements. J'ai constaté que la suppression des .bodycorrectifs qui:

document.addEventListener('gesturestart', function() { /* */ });

4
C'est sûrement mieux que de désactiver le zoom?! La meilleure solution que j'ai trouvée
jusqu'à

Hmm, cela désactive toujours la possibilité de zoomer. Quelqu'un a-t-il une solution simple qui ne fait pas cela?
Brad Swerdfeger

Cela fonctionne, mais j'ai observé que le problème recommence si j'utilise le geste de pincement et de zoom, puis que je fais pivoter l'écran. Je ne suis pas sûre de pouvoir régler ça.
Nilesh

3
Ça marche. Cependant, j'ai remarqué que l'utilisateur doit pincer deux fois pour zoomer. Je suppose que c'est parce que le maximum-scale=1.0reste en vigueur après le début du geste. Est-ce qu'il y a un moyen de réparer ceci?
LandonSchropp

3
Cela ne fonctionne pas pour 2 raisons: 1) cela désactive le démarrage gestuel numéro 1, obligeant l'utilisateur à faire deux gestes. 2) il se casse après que l'utilisateur double le premier geste, donc cela ne fonctionne vraiment que si l'utilisateur ne fait jamais de geste du tout. - tout le monde devrait regarder la solution d'Andrew Ashbacher ci-dessous. Ça marche vraiment.
tmsimont

18

Scott Jehl a proposé une solution fantastique qui utilise l'accéléromètre pour anticiper les changements d'orientation. Cette solution est très réactive et n'interfère pas avec les gestes de zoom.

https://github.com/scottjehl/iOS-Orientationchange-Fix

Fonctionnement: ce correctif fonctionne en écoutant l'accéléromètre de l'appareil pour prédire quand un changement d'orientation est sur le point de se produire. Lorsqu'il juge un changement d'orientation imminent, le script désactive le zoom de l'utilisateur, ce qui permet au changement d'orientation de se produire correctement, avec le zoom désactivé. Le script restaure le zoom une fois que l'appareil est soit orienté près de la verticale, soit après que son orientation a changé. De cette façon, le zoom de l'utilisateur n'est jamais désactivé lorsque la page est en cours d'utilisation.

Source minifiée:

/*! A fix for the iOS orientationchange zoom bug. Script by @scottjehl, rebound by @wilto.MIT License.*/(function(m){if(!(/iPhone|iPad|iPod/.test(navigator.platform)&&navigator.userAgent.indexOf("AppleWebKit")>-1)){return}var l=m.document;if(!l.querySelector){return}var n=l.querySelector("meta[name=viewport]"),a=n&&n.getAttribute("content"),k=a+",maximum-scale=1",d=a+",maximum-scale=10",g=true,j,i,h,c;if(!n){return}function f(){n.setAttribute("content",d);g=true}function b(){n.setAttribute("content",k);g=false}function e(o){c=o.accelerationIncludingGravity;j=Math.abs(c.x);i=Math.abs(c.y);h=Math.abs(c.z);if(!m.orientation&&(j>7||((h>6&&i<8||h<8&&i>6)&&j>5))){if(g){b()}}else{if(!g){f()}}}m.addEventListener("orientationchange",f,false);m.addEventListener("devicemotion",e,false)})(this);

Agréable! On dirait une solution élégante.
Elisabeth

1
cela devrait être la réponse acceptée !!!! J'aurais aimé voir cela avant de perdre une heure sur les solutions ci-dessus :)
tmsimont

1
après des tests supplémentaires, c'est une sorte de solution peu fiable: (c'est incohérent, et après avoir parcouru le code, je peux voir pourquoi ... le "seuil" de mouvement défini n'est pas toujours atteint, surtout si vous tenez l'ipad sur un angle pendant la rotation
tmsimont

Pourrait avoir des conséquences désagréables pour quiconque utilise le verrouillage de rotation ... ils pourraient tenir le téléphone à un certain angle et perdre la capacité de zoomer - l'utilisateur n'aurait aucune idée pourquoi
1owk3y

14

J'ai eu le même problème et la définition de l'échelle maximale = 1.0 a fonctionné pour moi.

Modifier: comme mentionné dans les commentaires, cela désactive le zoom utilisateur, sauf lorsque le contenu dépasse la résolution de largeur. Comme mentionné, cela pourrait ne pas être sage. Cela peut également être souhaité dans certains cas.

Le code de la fenêtre:

    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0;">

Belle solution. Fait un bon travail en gardant la page à un niveau de zoom constant (par rapport à la largeur de l'appareil) grâce aux changements d'orientation. Merci de le partager!
Luke Stevenson

17
l'inconvénient est que les utilisateurs handicapés ne peuvent pas zoomer sur votre site!
Jess Jacobs

J'ai remarqué que toutes ces méthodes semblent empêcher le CSS basé sur les requêtes multimédias d'enregistrer correctement la nouvelle largeur de l'appareil (ex: @media all et (max-width: 479px)
mheavers

2
tuer le zoom de l'utilisateur est une très mauvaise idée. voir la solution d'Andrew Ashbacher ci
tmsimont

Pas sûr pour l'iPhone, mais sur iPad, cela ne résout pas le problème, cela empêche simplement l'utilisateur de pouvoir effectuer un zoom arrière manuellement lorsque le navigateur effectue un zoom avant sur le changement d'orientation.
Alejo

3

Si vous avez défini la largeur dans la fenêtre:

<meta name = "viewport" content = "width=device-width; initial-scale=1.0;
 maximum-scale=1.0;" />

Et puis changez l'orientation, il fera parfois un zoom avant aléatoire (surtout si vous faites glisser sur l'écran) pour résoudre ce problème, ne définissez pas une largeur ici que j'ai utilisée:

<meta id="viewport" name="viewport" content="initial-scale=1.0; user-scalable=0;
minimum-scale=1.0; maximum-scale=1.0" />

Cela corrige le zoom quoi qu'il arrive, vous pouvez utiliser soit l'événement window.onorientationchange, soit si vous voulez qu'il soit indépendant de la plate-forme (pratique pour tester) la méthode window.innerWidth .


1

MobileSafari prend en charge l' orientationchangeévénement sur l' windowobjet. Malheureusement, il ne semble pas y avoir de moyen de contrôler directement le zoom via JavaScript. Vous pourriez peut-être écrire / modifier dynamiquement la metabalise qui contrôle la fenêtre - mais je doute que cela fonctionne, cela n'affecte que l'état initial de la page. Vous pourriez peut-être utiliser cet événement pour redimensionner votre contenu à l'aide de CSS. Bonne chance!


3
Merci! Oui, j'ai essayé de modifier dynamiquement les valeurs de la fenêtre de la balise Meta et cela n'a rien fait. Il me semble que si vous faites pivoter en Paysage, vous voulez qu'il zoome correctement pour conserver l'échelle afin que la page rentre dans la fenêtre Safari. Il me semble très étrange que ce ne soit pas le comportement par défaut!
Elisabeth


1

J'utilise cette fonction dans mon projet.

function changeViewPort(key, val) {
    var reg = new RegExp(key, "i"), oldval = document.querySelector('meta[name="viewport"]').content;
    var newval = reg.test(oldval) ? oldval.split(/,\s*/).map(function(v){ return reg.test(v) ? key+"="+val : v; }).join(", ") : oldval+= ", "+key+"="+val ;
    document.querySelector('meta[name="viewport"]').content = newval;
}

donc juste addEventListener:

if( /iPad|iPhone|iPod|Android/i.test(navigator.userAgent) ){
    window.addEventListener("orientationchange", function() { 
        changeViewPort("maximum-scale", 1);
        changeViewPort("maximum-scale", 10);
    }
}

0

J'ai trouvé une nouvelle solution de contournement, différente de toutes les autres que j'ai vues, en désactivant le zoom iOS natif et en implémentant à la place la fonctionnalité de zoom dans JavaScript.

Sérgio Lopes fournit une excellente base sur les diverses autres solutions au problème de zoom / orientation: une correction du célèbre bug de zoom iOS sur le changement d'orientation en portrait .

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta name="viewport" id="viewport" content="user-scalable=no,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0" />
    <title>Robocat mobile Safari zoom fix</title>
    <style>
        body {
            padding: 0;
            margin: 0;
        }
        #container {
            -webkit-transform-origin: 0px 0px;
            -webkit-transform: scale3d(1,1,1);
            /* shrink-to-fit needed so can measure width of container http://stackoverflow.com/questions/450903/make-css-div-width-equal-to-contents */
            display: inline-block;
            *display: inline;
            *zoom: 1;
        }
        #zoomfix {
            opacity: 0;
            position: absolute;
            z-index: -1;
            top: 0;
            left: 0;
        }
    </style>
</head>

<body>
    <input id="zoomfix" disabled="1" tabIndex="-1">
    <div id="container">
        <style>
            table {
                counter-reset: row cell;
                background-image: url(http://upload.wikimedia.org/wikipedia/commons/3/38/JPEG_example_JPG_RIP_010.jpg);
            }
            tr {
                counter-increment: row;
            }
            td:before {
                counter-increment: cell;
                color: white;
                font-weight: bold;
                content: "row" counter(row) ".cell" counter(cell);
            }
        </style>
        <table cellspacing="10">
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
        </table>
    </div>

    <script>
    (function() {
        var viewportScale = 1;
        var container = document.getElementById('container');
        var scale, originX, originY, relativeOriginX, relativeOriginY, windowW, windowH, containerW, containerH, resizeTimer, activeElement;
        document.addEventListener('gesturestart', function(event) {
            scale = null;
            originX = event.pageX;
            originY = event.pageY;
            relativeOriginX = (originX - window.pageXOffset) / window.innerWidth;
            relativeOriginY = (originY - window.pageYOffset) / window.innerHeight;
            windowW = window.innerWidth;
            windowH = window.innerHeight;
            containerW = container.offsetWidth;
            containerH = container.offsetHeight;
        });
        document.addEventListener('gesturechange', function(event) {
            event.preventDefault();
            if (originX && originY && event.scale && event.pageX && event.pageY) {
                scale = event.scale;
                var newWindowW = windowW / scale;
                if (newWindowW > containerW) {
                    scale = windowW / containerW;
                }
                var newWindowH = windowH / scale;
                if (newWindowH > containerH) {
                    scale = windowH / containerH;
                }
                if (viewportScale * scale < 0.1) {
                    scale = 0.1/viewportScale;
                }
                if (viewportScale * scale > 10) {
                    scale = 10/viewportScale;
                }
                container.style.WebkitTransformOrigin = originX + 'px ' + originY + 'px';
                container.style.WebkitTransform = 'scale3d(' + scale + ',' + scale + ',1)';
            }
        });
        document.addEventListener('gestureend', function() {
            if (scale && (scale < 0.95 || scale > 1.05)) {
                viewportScale *= scale;
                scale = null;
                container.style.WebkitTransform = '';
                container.style.WebkitTransformOrigin = '';
                document.getElementById('viewport').setAttribute('content', 'user-scalable=no,initial-scale=' + viewportScale + ',minimum-scale=' + viewportScale + ',maximum-scale=' + viewportScale);
                document.body.style.WebkitTransform = 'scale3d(1,1,1)';
                // Without zoomfix focus, after changing orientation and zoom a few times, the iOS viewport scale functionality sometimes locks up (and completely stops working).
                // The reason I thought this hack would work is because showing the keyboard is the only way to affect the viewport sizing, which forces the viewport to resize (even though the keyboard doesn't actually get time to open!).
                // Also discovered another amazing side effect: if you have no meta viewport element, and focus()/blur() in gestureend, zoom is disabled!! Wow!
                var zoomfix = document.getElementById('zoomfix');
                zoomfix.disabled = false;
                zoomfix.focus();
                zoomfix.blur();
                setTimeout(function() {
                    zoomfix.disabled = true;
                    window.scrollTo(originX - relativeOriginX * window.innerWidth, originY - relativeOriginY * window.innerHeight);
                    // This forces a repaint. repaint *intermittently* fails to redraw correctly, and this fixes the problem.
                    document.body.style.WebkitTransform = '';
                }, 0);
            }
        });
    })();
    </script>
</body>
</html>

Il pourrait être amélioré, mais pour mes besoins, il évite les inconvénients majeurs qui se produisent avec toutes les autres solutions que j'ai vues. Jusqu'à présent, je ne l'ai testé qu'en utilisant Safari mobile sur un iPad 2 avec iOS4.

La mise au point () / flou () est une solution de contournement pour éviter le blocage occasionnel de la fonctionnalité de zoom qui peut se produire après avoir changé d'orientation et zoomé plusieurs fois.

La définition du document.body.style oblige à repeindre en plein écran, ce qui évite des problèmes intermittents occasionnels où le repeinture échoue gravement après le zoom.


0

Elisabeth, vous pouvez modifier le contenu de la fenêtre de manière dynamique en ajoutant la propriété "id" au méta-étiquette:

<meta name="viewport" id="view" content="user-scalable=yes, width=device-width minimum-scale=1, maximum-scale=1" />

Ensuite, vous pouvez simplement appeler par javascript:

document.getElementById("view").setAttribute('content','user-scalable=yes, width=device-width, minimum-scale=1, maximum-scale=10');

@bridgestew si vous souhaitez modifier le zoom ou la fenêtre de façon dynamique, utilisez la vue de défilement de sous-vue contenue dans uiwebview. J'ai ajouté un extrait d'exemple sur un autre fil: lien
M Penades

4
@Elisabeth ça marche pour toi? Cela ne réinitialise pas le zoom lors du passage en mode paysage pour moi.
instanceof me

0

Voici une autre façon de le faire, qui semble bien fonctionner.

  1. Définissez la balise Meta pour restreindre la fenêtre à scale = 1, ce qui empêche le zoom:

    <meta name = "viewport" content = "width = device-width, initial-scale = 1, minimum-scale = 1, maximum-scale = 1">

  2. Avec javascript, modifiez la balise meta 1/2 seconde plus tard pour autoriser le zoom:

    setTimeout (function () {document.querySelector ("meta [name = viewport]"). setAttribute ('content', 'width = device-width, initial-scale = 1');}, 500);

  3. Encore une fois avec javascript, lors du changement d'orientation, rechargez la page:

    window.onorientationchange = function () {window.location.reload ();};

Chaque fois que vous réorientez l'appareil, la page se recharge, initialement sans zoom. Mais 1/2 seconde plus tard, la possibilité de zoomer est rétablie.


6
Répondre à une question 5 ans après qu'elle a été posée est quelque chose. Malheureusement, ce n'est pas ainsi que le Web fonctionne en 2015. Vous NE rechargez PAS la page lorsque l'utilisateur fait pivoter son appareil.
Pierre

0

J'ai trouvé un correctif très facile à mettre en œuvre. Définissez le focus sur un élément de texte qui a une taille de police de 50 px à la fin du formulaire. Cela ne semble pas fonctionner si l'élément de texte est masqué, mais le masquage de cet élément se fait facilement en définissant les propriétés de couleur des éléments pour ne pas avoir d'opacité.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.