web-dev-qa-db-fra.com

Sous-pixels calculés et rendus différemment entre les navigateurs

Le but:

Je travaille sur un code similaire à celui-ci pour créer un composant dans lequel un champ d'entrée a un bouton incorporé :

http://codepen.io/anon/pen/pgwbWG?editors=110

Comme vous pouvez le constater, le bouton est positionné de manière absolue avec top et bottom définis sur 0, pour obtenir un élément de hauteur de 100%.

A noter également que la bordure du saisie de texte doit rester visible et aussi envelopper le bouton. Pour y parvenir, j'ai ajouté un margin: 1px au bouton afin qu'il y ait (devrait être) un espace pour afficher le saisie de texte} _ bordure rouge (généralement lorsque le contenu du champ de saisie n'est pas valide).

Le problème:

est-ce que sur Firefox, il est (généralement) rendu correctement, alors que sur Chrome (et apparemment sur le dernier Safari), il y aura un écart 1px au bas du bouton.

CSS semble ok mais il semble y avoir un problème de calcul/arrondi dans le rendu, où la marge inférieure ou supérieure du bouton n’est pas vraiment 1px (on peut le voir inspecter l’élément). Et aussi le remplissage de l'entrée semble influencer en cela.

À différentes vitesses de zoom, il ajoute ou supprime 1px de marge en haut ou en bas du bouton, ce qui donne un écart de 1px ou une bordure couverte .

Lorsque je règle le bouton margin sur 0px, la marge inférieure est fixe mais je perds la marge de 1px en haut pour finir de couvrir le bord rouge du entrée de texte.

Les exemples:

Je ne suis probablement pas assez clair ni trop bavard pour l'expliquer. Voici donc quelques captures d'écran du bogue, issues de différents zooms sur Chrome (notez que le CSS est toujours le même):

 enter image description here  enter image description here  enter image description here  enter image description here

La solution:

Je n’étais pas en mesure de trouver un solution inter-navigateurs . Comment le gérer et obtenir un composant cohérent? (Pas de Javascript s'il vous plaît)

15
Kamafeather

Comme vous le savez déjà, le problème provient d’une approche différente du calcul des sous-pixels entre les navigateurs.

Dans Chrome, par exemple, les bordures peuvent avoir une taille fractionnaire, mais les marges sont gérées différemment (sous forme d'entiers).

Je n'ai pas de documentation à ce sujet de la part de l'équipe Chrome, mais c'est ce que l'on peut voir dans les outils de développement:

 dev tools capture

D'après les informations dont je dispose, il n'y a pas moyen de changer cela.

Au lieu de cela, vous pouvez transférer l'utilisation de la marge du bouton vers une bordure.

Etant donné que vous devez disposer d'espace pour la bordure 1px de l'entrée, procédez de la même manière dans le bouton, définissez une bordure 1px (au lieu d'une marge) et définissez-la transparente.

L'astuce restante consiste à définir la propriété background-clip sur padding box, afin que cette transparence ne soit pas affectée par l'arrière-plan

Il existe un autre bogue dans Chrome, le remplissage exprimé en em n’est pas fiable à ce niveau de précision lorsque le navigateur est zoomé. J'ai changé cela dans l'extrait. 

Puisque nous utilisons le bouton Bordure pour obtenir la cote ok, nous pouvons styliser la bordure en utilisant plutôt une ombre incrustée.

* {
  margin: 0; padding: 0; box-sizing: border-box;
}
button, input, wrapper {
  display: inline-block; border-radius: 3px;
}

.wrapper {
  position: relative;
  
  width: 60%;
  margin: 1em;
  background-color: #ccc;
}

input {
  border: 1px solid red;
  width: 100%;
  
  background-color: limegreen;
  line-height: 3em;
/*  padding: 0.75em; */
  padding: 10px;
}

button {
  position: absolute;
  right: 0;
  top: 0;
  bottom: 0;
  border: 1px solid transparent;
  width: 7em;
  margin: 0px;
  background-clip: padding-box;
  box-shadow:  inset 0px 0px 0px 2px  black;
}
<div class="wrapper">
  <input type="text">
  <button>Test</button>
</div>

Un autre exemple, où le bouton a une bordure. Mais nous avons besoin d’un emballage autour pour obtenir les dimensions correctes.

* {
  margin: 0; padding: 0; box-sizing: border-box;
}
button, input, wrapper {
  display: inline-block; border-radius: 3px;
}

.wrapper {
  position: relative;
  
  width: 60%;
  margin: 1em;
  background-color: #ccc;
}

input {
  border: 1px solid red;
  width: 100%;
  
  background-color: limegreen;
  line-height: 3em;
/*  padding: 0.75em; */
  padding: 10px;
}

.buttonwrap {
  position: absolute;
  right: 0;
  top: 0;
  bottom: 0;
  border: 1px solid transparent;
  width: 7em;
  margin: 0px;
  background-clip: padding-box;
}
button {
  position: absolute;
  right: 0px;
  top: 0;
  bottom: 0;
  width: 100%;
  border: 2px solid blue;
  margin: 0px;
}
<div class="wrapper">
  <input type="text">
  <div class="buttonwrap">
      <button>Test</button>
  </div>
</div>

8
vals

Utilisez http://autoprefixer.github.io/ pour obtenir la prise en charge multi-navigateurs dont vous avez besoin pour l’affichage: flex;

button, input, wrapper {
  display: inline-block; <----- Remove "display: inline-block;"
  border-radius: 3px;
}

.wrapper {
  position: relative;
  display: -webkit-box;<----- Add "display: flex;"
  display: -webkit-flex;<----- Add "display: flex;"
  display: -ms-flexbox;<----- Add "display: flex;"
  display: flex;<----- Add "display: flex;"
  width: 60%;
  margin: 1em;
  background-color: #ccc;
}

Matériel de lecture et d'apprentissage supplémentaire:

https://css-tricks.com/snippets/css/a-guide-to-flexbox/

http://flexbox.io/#/

https://philipwalton.github.io/solved-by-flexbox/demos/holy-grail/

http://www.sketchingwithcss.com/samplechapter/cheatsheet.html

Remarque: pour remplacer une règle de flexion, vous devrez utiliser un raccourci de flex plutôt qu'un dépassement spécifique en raison des insuffisances actuelles du navigateur, par exemple. 

.item {
  flex: 0 0 300px;
}

/* overide for some reason */

.item {
  flex: 1 0 300px;
}

/* NOT */

.item {
  flex-grow: 1;
}

Vous POUVEZ avoir besoin de passer outre pour ie11:

.ie11std .wrapper {
  display:table;
}

.ie11std .item {
  display:table-cell;
}

bien que cela ne soit pas réactif.

0
Carol McKay