Les décimales dans une largeur CSS sont-elles respectées?

225

Quelque chose que je me demandais depuis un moment lors de la conception CSS.

Les décimales dans les largeurs CSS sont-elles respectées? Ou sont-ils arrondis?

.percentage {
  width: 49.5%;
}

ou

.pixel {
  width: 122.5px;
}
Alastair Pitts
la source

Réponses:

186

Si c'est un pourcentage de largeur, alors oui, il est respecté . Comme Martin l'a souligné, les choses se décomposent lorsque vous arrivez à des pixels fractionnaires, mais si vos valeurs de pourcentage donnent une valeur de pixel entière (par exemple, 50,5% de 200 pixels dans l'exemple), vous obtiendrez un comportement raisonnable et attendu.

Modifier: j'ai mis à jour l'exemple pour montrer ce qui arrive aux pixels fractionnaires (dans Chrome, les valeurs sont tronquées, donc 50, 50,5 et 50,6 affichent tous la même largeur).

Skilldrick
la source
7
Vous avez raison sur le fait que les valeurs de pourcentage ne sont pas elles-mêmes arrondies, mais les largeurs de pixels avec des décimales et le résultat final du calcul du pourcentage seront toujours arrondis à des pixels entiers :)
MartinodF
2
@MartinodF Merci pour la clarification. Oui, les pixels sont arrondis, mais il n'est pas défini s'ils arrondissent réellement au plus proche, au sol ou au plafond (c'est ce que j'entendais par «les choses se décomposent»).
Skilldrick
1
@Skilldrick J'ai essayé les pixels fractionnaires de votre démo sur certains navigateurs par curiosité: IE9p7 et FF4b7 arrondissent au pixel le plus proche, tandis qu'Opera 11b, Chrome 9.0.587.0 et Safari 5.0.3 tronquent la valeur. @andras Juste pour clarifier: je ne dis pas que les valeurs internes sont arrondies, seules les valeurs de rendu finales le sont. Si vous effectuez un zoom ou si certains éléments héritent de propriétés, etc., les décimales compteront.
MartinodF
10
Mise à jour moderne: ma version Chrome 24 arrondit en fait les pixels fractionnaires. La visualisation du jsFiddle, 50,5 et 50,6 arrondit à 51 pixels, soit 1 pixel de plus que la div 50 pixels.
Michael Butler
5
Ce qui peut être le plus important à noter, c'est comment les éléments avec des dimensions de pixels fractionnaires s'empilent les uns à côté des autres. Alors qu'ils font autour visuellement par eux - mêmes, ils ne prennent pas de place supplémentaire lors de mettre à côté d'autres éléments très légèrement dimensionnées: cssdesk.com/8R2rB
Sandy Gifford
53

Même lorsque le nombre est arrondi lorsque la page est peinte, la valeur complète est conservée en mémoire et utilisée pour le calcul enfant suivant. Par exemple, si votre boîte de 100,4999px peint à 100px, son enfant avec une largeur de 50% sera calculé comme 0,5 * 100,4999 au lieu de 0,5 * 100. Et ainsi de suite à des niveaux plus profonds.

J'ai créé des systèmes de disposition de grille profondément imbriqués où les largeurs des parents sont des ems et les enfants sont des pourcentages, et inclure jusqu'à quatre décimales en amont a eu un impact notable.

Affaire Edge, bien sûr, mais quelque chose à garder à l'esprit.

natekoechley
la source
2
La réponse acceptée est plus complète que celle-ci, mais l'anecdote dans celle-ci me donne une meilleure idée de la façon dont les implications techniques se feront sentir. Merci de l'avoir posté.
Tom
23

Bien que les pixels fractionnaires puissent sembler arrondir les éléments individuels (comme le démontre très bien @SkillDrick ), il est important de savoir que les pixels fractionnaires sont réellement respectés dans le modèle de boîte réel .

Cela se voit mieux lorsque les éléments sont empilés les uns à côté des autres (ou les uns au-dessus des autres); en d'autres termes, si je plaçais 400 divs de 0,5 pixel côte à côte, ils auraient la même largeur qu'un seul div de 200 pixels. S'ils ont tous fait raflés à 1px (en regardant des éléments individuels impliquerait) , nous nous attendons à la div 200px soit la moitié du temps.

Cela peut être vu dans cet extrait de code exécutable:

body {
  color:            white;
  font-family:      sans-serif;
  font-weight:      bold;
  background-color: #334;
}

.div_house div {
  height:           10px;
  background-color: orange;
  display:          inline-block;
}

div#small_divs div {
  width:            0.5px;
}

div#large_div div {
  width:            200px;
}
<div class="div_house" id="small_divs">
  <p>0.5px div x 400</p>
  <div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div>
</div>
<br>
<div class="div_house" id="large_div">
  <p>200px div x 1</p>
  <div></div>
</div>

Sandy Gifford
la source
11
En ce qui concerne le rendu: dans votre exemple, vous avez deux divisions en compétition pour chaque pixel. Dans ces cas, votre navigateur en choisira un pour rendre le pixel entier - pour éviter le flou et autres artefacts étranges. Si vous définissez la moitié des pixels sur bleu, en utilisant :nth-child(even)ou :nth-child(odd), vous remarquez que le tout est orange ou tout est bleu - pas un mélange de bleu et d'orange (ce qui serait une vague teinte violette).
Daan Wilmer
16

La largeur sera arrondie à un nombre entier de pixels .

Je ne sais pas si tous les navigateurs l'arrondiront de la même manière. Ils semblent tous avoir une stratégie différente lors de l'arrondissement des pourcentages sous-pixels. Si vous êtes intéressé par les détails de l'arrondi sous-pixel dans différents navigateurs, il y a un excellent article sur ElastiCSS .

edit : J'ai testé la démo de @ Skilldrick dans certains navigateurs par curiosité. Lorsque vous utilisez des valeurs de pixels fractionnaires (et non des pourcentages, elles fonctionnent comme suggéré dans l'article que j'ai lié), IE9p7 et FF4b7 semblent arrondir au pixel le plus proche, tandis que Opera 11b, Chrome 9.0.587.0 et Safari 5.0.3 tronquent les décimales. Non pas que j'espérais qu'ils avaient quelque chose en commun après tout ...

MartinodF
la source
7

Ils semblent arrondir les valeurs à l'entier le plus proche; mais je vois des incohérences dans Chrome, Safari et Firefox.

Par exemple, si 33,3% se convertit en 420,945 pixels

chrome et firexfox le montrent comme 421px. tandis que le safari montre son 420px.

Il semble que Chrome et Firefox suivent la logique du plancher et du plafond, contrairement à Safari. Cette page semble discuter du même problème

http://ejohn.org/blog/sub-pixel-problems-in-css/

agaase
la source
6

Les éléments doivent peindre à un nombre entier de pixels, et comme les autres réponses couvertes, les pourcentages sont en effet respectés.

Une note importante est que les pixels dans ce cas signifient des pixels css , pas des pixels d'écran, donc un conteneur de 200px avec un enfant à 50,7499% sera arrondi à 101px pixels css , qui seront ensuite rendus sur 202px sur un écran rétine, et non 400 *. 507499 ~ = 203px.

La densité d'écran est ignorée dans ce calcul, et il n'y a aucun moyen de peindre * un élément à des tailles de sous-pixel rétine spécifiques. Vous ne pouvez pas avoir d'arrière-plans ou de bordures d'éléments rendus à moins de 1 pixel CSS , même si la taille réelle de l'élément peut être inférieure à 1 pixel CSS, comme l'a montré Sandy Gifford.

[*] Vous pouvez utiliser certaines techniques comme l'ombre de boîte décalée de 0,5, etc., mais les propriétés réelles du modèle de boîte peindront jusqu'à un pixel CSS complet.

Olex Ponomarenko
la source
Excellente observation
août