css transform, bords dentelés en chrome


193

J'ai utilisé la transformation CSS3 pour faire pivoter des images et des zones de texte avec des bordures dans mon site Web.

Le problème est que la bordure est dentelée dans Chrome, comme un jeu (basse résolution) sans anti-crénelage. Dans IE, Opera et FF, cela semble beaucoup mieux car AA est utilisé (ce qui est toujours clairement visible mais pas si mal). Je ne peux pas tester Safari car je ne possède pas de Mac.

La photo pivotée et le texte lui-même ont l'air bien, seule la bordure est dentelée.

Le CSS que j'utilise est le suivant:

.rotate2deg {
    transform: rotate(2deg);
    -ms-transform: rotate(2deg); /* IE 9 */
    -webkit-transform: rotate(2deg); /* Safari and Chrome */
    -o-transform: rotate(2deg); /* Opera */
    -moz-transform: rotate(2deg); /* Firefox */
}

Existe-t-il un moyen de résoudre ce problème, par exemple en forçant Chrome à utiliser AA?

Exemple ci-dessous:

Exemple de bords dentelés


Pour ceux qui le liront plus tard: il devrait être corrigé dans Chrome à partir de la version 15 (novembre 2011), mais Safari a introduit exactement le même problème dans 5.1 pour Mac qui n'est pas encore résolu pour le moment
dtech

Et ils l'ont si bien réparé, qu'il est impossible de revenir en arrière. Nous avons des cas où l'anticrénelage est la dernière chose que nous voulons, mais maintenant Chrome / Chromium / Safari n'a pas de méthode pour désactiver l'anticrénelage dans les images transformées, bien qu'il s'agisse d'images 1 bit (par exemple, b / w gif). Le flou est tellement cool, tellement cool, plus de flou est plus cool, disent-ils! Le seul moyen de garantir des bords nets est de tout convertir en chemins ou objets svg et d'ajouter l'attribut shape-render = "crispEdges".
Timo Kähkönen

Pour moi, le problème est avec les bordures transparentes utilisées pour créer une flèche. C'est dans Chrome 40 sur win et mac. Aucune des options ici ne résout le problème.
Gurnard

Réponses:


389

Au cas où quelqu'un chercherait cela plus tard, une bonne astuce pour se débarrasser de ces bords irréguliers sur les transformations CSS dans Chrome est d'ajouter la propriété CSS -webkit-backface-visibilityavec une valeur de hidden. Dans mes propres tests, cela les a complètement lissés. J'espère que cela pourra aider.

-webkit-backface-visibility: hidden;

7
Lifesaver - cette astuce nous a permis de réactiver -webkit-transform sur un certain nombre de sites que nous étions auparavant obligés de désactiver les transformations en raison de problèmes d'anti-aliasing. Merci!
Darren


5
Cela fonctionne dans Chrome, mais cela les rend à nouveau irréguliers dans iOS 6!
lezd

11
@lazd pour le corriger dans iOS ajouterpadding: 1px; -webkit-background-clip: content-box;
Rob Fletcher

2
@RobFletcher a ajouté un rembourrage et un clip d'arrière-plan qui semblent, par ce fil, essentiels à une solution cross-browser et cross-os. Cela corrige également mon problème OSX / Chrome ... Je pense qu'une solution complète serait quelque chose comme:padding: 1px;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-background-clip:content-box;background-clip:content-box;
Benjamin Luoma

120

Si vous utilisez transitionau lieu de transform, -webkit-backface-visibility: hidden;ne fonctionne pas. Un bord dentelé apparaît pendant l'animation pour un fichier png transparent.

Pour le résoudre, j'ai utilisé: outline: 1px solid transparent;


4
cela semble aider dans les situations où la propriété web-kit-backface-visibilité n'a pas été détectée.
dgibbs

2
Fonctionne pour moi quand aucun des autres ne l'a fait. Avant d'ajouter cette propriété, Chrome Android avait des problèmes. Maintenant, tous les navigateurs semblent fonctionner correctement.
Bernie Sumption

Fonctionne pour moi dans Safari sur iOS 8.
Moritz Friedrich

Solution parfaite. Les autres n'ont pas fonctionné. J'ai failli abandonner et je doutais que cela fonctionnerait. Mais c'est le cas!
Garconis

1
Fonctionne parfaitement pour mes besoins. J'utilise en effet la transition, et les autres réponses provoquaient la pixellisation de mon PNG à son état par défaut. Votre réponse a aidé à supprimer toute pixelisation - à la fois sur l'état par défaut et pendant la transition. Parfait!
Garconis

24

L'ajout d'une bordure transparente 1px déclenchera l'anti-aliasing

outline: 1px solid transparent;

Alternativement, ajoutez une ombre transparente transparente de 1px.

box-shadow: 0 0 1px rgba(255,255,255,0);

rgba (255, 255, 255, 0) est probablement mieux
mmm

4
L'ajout de la section supérieure de CSS dans votre réponse et cela outline: 1px solid transparent;a bien fonctionné pour moi. Les autres solutions ci-dessus ne fonctionnaient pas assez bien.
Timothy Zorn

outline: 1px solid transparent;déclencher l'anti-aliasing également dans Firefox 52 (qui a les mêmes problèmes que Chrome)
Luca Detomi

18

Essayez la transformation 3D. Ça fonctionne super bien!

/* Due to a bug in the anti-liasing*/
-webkit-transform-style: preserve-3d; 
-webkit-transform: rotateZ(2deg);

1
en essayant cela dans Chrome maintenant (août 2013 sur Mac), la solution acceptée ne fonctionne pas, mais son utilisation (en particulier preserve-3d; rotatepeut toujours être utilisée sans passer à rotateZ) le fait.
Dave

Super hacky, mais a fonctionné pour moi. Essayez même un degré plus petit comme 0,05 pour éviter un mauvais alignement visible.
cpursley

préserv-3d m'a sauvé la vie.
Hannes Schneidermayer

8

La réponse choisie (ni aucune des autres réponses) n'a pas fonctionné pour moi, mais cela a:

img {outline:1px solid transparent;}


2

J'ai eu un problème avec un gradient CSS3 avec -45deg. Le backgroundslanted, était mal dentelé similaire mais pire que le poste d'origine. J'ai donc commencé à jouer avec les deux background-size. Cela étirerait la déchirure, mais elle était toujours là. Ensuite, en plus, j'ai lu que d'autres personnes avaient également des problèmes à des incréments de 45 degrés, j'ai donc ajusté de -45degà -45.0001deget mon problème a été résolu.

Dans mon CSS ci-dessous, background-sizeétait initialement 30pxet le degdégradé d'arrière-plan était exactement -45deg, et toutes les images clés l'étaient 30px 0.

    @-webkit-keyframes progressStripeLTR {
        to {
            background-position: 60px 0;
        };
    }

    @-moz-keyframes progressStripeLTR {
        to {
            background-position: 60px 0;
        };
    }

    @-ms-keyframes progressStripeLTR {
        to {
            background-position: 60px 0;
        };
    }

    @-o-keyframes progressStripeLTR {
        to {
            background-position: 60px 0;
        };
    }

    @keyframes progressStripeLTR {
        to {
            background-position: 60px 0;
        };
    }

    @-webkit-keyframes progressStripeRTL {
        to {
            background-position: -60px 0;
        };
    }

    @-moz-keyframes progressStripeRTL {
        to {
            background-position: -60px 0;
        };
    }

    @-ms-keyframes progressStripeRTL {
        to {
            background-position: -60px 0;
        };
    }

    @-o-keyframes progressStripeRTL {
        to {
            background-position: -60px 0;
        };
    }

    @keyframes progressStripeRTL {
        to {
            background-position: -60px 0;
        };
    }

    .pro-bar-candy {
        width: 100%;
        height: 15px;

        -webkit-border-radius:  3px;
        -moz-border-radius:     3px;
        border-radius:          3px;

        background: rgb(187, 187, 187);
        background: -moz-linear-gradient(
                        -45.0001deg,
                        rgba(187, 187, 187, 1.00) 25%,
                        transparent 25%,
                        transparent 50%,
                        rgba(187, 187, 187, 1.00) 50%,
                        rgba(187, 187, 187, 1.00) 75%,
                        transparent 75%,
                        transparent
                    );
        background: -webkit-linear-gradient(
                        -45.0001deg,
                        rgba(187, 187, 187, 1.00) 25%,
                        transparent 25%,
                        transparent 50%,
                        rgba(187, 187, 187, 1.00) 50%,
                        rgba(187, 187, 187, 1.00) 75%,
                        transparent 75%,
                        transparent
                    );
        background: -o-linear-gradient(
                        -45.0001deg,
                        rgba(187, 187, 187, 1.00) 25%,
                        transparent 25%,
                        transparent 50%,
                        rgba(187, 187, 187, 1.00) 50%,
                        rgba(187, 187, 187, 1.00) 75%,
                        transparent 75%,
                        transparent
                    );
        background: -ms-linear-gradient(
                        -45.0001deg,
                        rgba(187, 187, 187, 1.00) 25%,
                        transparent 25%,
                        transparent 50%,
                        rgba(187, 187, 187, 1.00) 50%,
                        rgba(187, 187, 187, 1.00) 75%,
                        transparent 75%,
                        transparent
                    );
        background: linear-gradient(
                        -45.0001deg,
                        rgba(187, 187, 187, 1.00) 25%,
                        transparent 25%,
                        transparent 50%,
                        rgba(187, 187, 187, 1.00) 50%,
                        rgba(187, 187, 187, 1.00) 75%,
                        transparent 75%,
                        transparent
                    );
        background: -webkit-gradient(
                        linear,
                        right bottom,
                        right top,
                        color-stop(
                            25%,
                            rgba(187, 187, 187, 1.00)
                        ),
                        color-stop(
                            25%,
                            rgba(0, 0, 0, 0.00)
                        ),
                        color-stop(
                            50%,
                            rgba(0, 0, 0, 0.00)
                        ),
                        color-stop(
                            50%,
                            rgba(187, 187, 187, 1.00)
                        ),
                        color-stop(
                            75%,
                            rgba(187, 187, 187, 1.00)
                        ),
                        color-stop(
                            75%,
                            rgba(0, 0, 0, 0.00)
                        ),
                        color-stop(
                            rgba(0, 0, 0, 0.00)
                        )
                    );

        background-repeat: repeat-x;
        -webkit-background-size:    60px 60px;
        -moz-background-size:       60px 60px;
        -o-background-size:         60px 60px;
        background-size:            60px 60px;
        }

    .pro-bar-candy.candy-ltr {
        -webkit-animation:  progressStripeLTR .6s linear infinite;
        -moz-animation:     progressStripeLTR .6s linear infinite;
        -ms-animation:      progressStripeLTR .6s linear infinite;
        -o-animation:       progressStripeLTR .6s linear infinite;
        animation:          progressStripeLTR .6s linear infinite;
        }

    .pro-bar-candy.candy-rtl {
        -webkit-animation:  progressStripeRTL .6s linear infinite;
        -moz-animation:     progressStripeRTL .6s linear infinite;
        -ms-animation:      progressStripeRTL .6s linear infinite;
        -o-animation:       progressStripeRTL .6s linear infinite;
        animation:          progressStripeRTL .6s linear infinite;
        }

1

Vous pourrez peut-être masquer les irrégularités en utilisant des ombres de boîte floues . L'utilisation de -webkit-box-shadow au lieu de box-shadow garantira que cela n'affectera pas les navigateurs non-webkit. Vous voudrez peut-être vérifier Safari et les navigateurs Webkit mobiles.

Le résultat est un peu meilleur, mais toujours beaucoup moins bon qu'avec les autres navigateurs:

avec ombre de boîte (dessous)


1

Je pensais juste que nous jetterions aussi notre solution car nous avions exactement le même problème sur Chrome / Windows.

Nous avons essayé la solution de @stevenWatkins ci-dessus, mais nous avons toujours eu le "stepping".

Au lieu de

-webkit-backface-visibility: hidden;

Nous avons utilisé:

-webkit-backface-visibility: initial;

Pour nous, cela a fait l'affaire 🎉


1

L'ajout de ce qui suit sur le div entourant l'élément en question a corrigé cela pour moi.

-webkit-transform-style: preserve-3d;

Les bords dentelés apparaissaient autour de la fenêtre vidéo dans mon cas.


0

Pour moi, c'est la propriété CSS en perspective qui a fait l'affaire:

-webkit-perspective: 1000;

Complètement illogique dans mon cas car je n'utilise pas de transitions 3D, mais fonctionne quand même.


0

Pour canvas en Chrome (Version 52)

Toutes les réponses répertoriées concernent les images. Mais mon problème concerne le canevas en chrome (v.52) avec transformation rotation. Ils sont devenus irréguliers et toutes ces méthodes ne peuvent pas aider.

Solution qui fonctionne pour moi:

  1. Agrandir la toile sur 1 px pour chaque côté => +2 px pour la largeur et la hauteur;
  2. Dessinez une image avec un décalage + 1px (en position 1,1 au lieu de 0,0) et une taille fixe (la taille de l'image doit être 2px inférieure à la taille du canevas)
  3. Appliquer la rotation requise

Blocs de code si importants:

// Unfixed version
ctx.drawImage(img, 0, 0, 335, 218);
// Fixed version
ctx.drawImage(img, 1, 1, 335, 218);
/* This style should be applied for fixed version */
canvas {
  margin-left: -1px;
  margin-top:-1px;
}        
<!--Unfixed version-->
<canvas width="335" height="218"></canvas>
<!--Fixed version-->
<canvas width="337" height="220"></canvas>

Exemple: https://jsfiddle.net/tLbxgusx/1/

Remarque: il y a beaucoup de divs imbriqués car c'est une version simplifiée de mon projet.


Ce problème est également reproduit pour Firefox pour moi. Il n'y a pas un tel problème sur Safari et FF avec rétine.

Et une autre solution fondée consiste à placer le canevas dans un div de même taille et à appliquer le CSS suivant à ce div:

overflow: hidden;
box-shadow: 0 0 1px rgba(255,255,255,0);
// Or
//outline:1px solid transparent;

Et la rotation doit être appliquée à cette div enveloppante. La solution listée est donc travaillée mais avec de petites modifications.

Et l'exemple modifié d'une telle solution est: https://jsfiddle.net/tLbxgusx/2/

Remarque: Voir le style de div avec la classe «troisième».

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.