nico3333fr / ROCSSTI

RÖCSSTI : pour démarrer vos CSS avec la patate !
https://rocssti.net/
MIT License
46 stars 4 forks source link

Sass : problème de calcul des media queries en em #31

Closed kloh-fr closed 6 years ago

kloh-fr commented 6 years ago

J'utilise une base personnalisée de RÖCSSTI (Sass, mais c'est sans nul doute pareil en Less) et je viens de découvrir que le calcul des media queries (j'abrège en MQ pour la suite) en em n'est pas correct si on utilise une autre $base-font que 16 !

Je m'en suis rendu compte parce que je suis en train de bosser sur un projet avec une taille de base de 19 et mes points de rupture définis à partir de la fonction de calcul em() ne basculaient pas à la bonne taille.

Démonstration

Voici ce que ça donne, en simplifiant le code un maximum. Pour la MQ suivante (sur la base de ma $base-font à 19) :

@media (min-width: em(640)) {
    width: em(640);
}

…le code compilé est celui-ci :

@media (min-width: 33.68421em) {
    width: 33.68421em;
}

Comme, ça tout a l'air normal. Sauf qu'en fait si on fait la conversion en pixels, ça donne ça :

@media (min-width: 538px) {
    width: 640px;
}

Mais pourquoi donc ?

Après quelques recherches, la lecture de quelques articles, la raison tient en une phrase dans les spécifications du W3C :

The ‘em’ value is relative to the initial value of ‘font-size’.

Ma solution

À court-terme, j'ai donc adapté la fonction de calcul em() pour que le calcul soit sur une taille de texte de 16 dans tous les cas – puisque c'est la taille par défaut des navigateurs, peu importe la valeur de $base-font :

@function em-mq($px) {
    @return ($px / 16) * 1em;
}

En reprenant ma MQ initiale avec cette fonction (toujours avec $base-font à 19) :

@media (min-width: em-mq(640)) {
    width: em(640);
}

…qui donnera le code compilé suivant :

@media (min-width: 40em) {
    width: 33.68421em;
}

…qui donne converti en pixels :

@media (min-width: 640px) {
    width: 640px;
}

Peut faire mieux ?

Voilà ma solution à court-terme mais on peut peut-être trouver une meilleure solution. Là tout de suite je ne sais pas trop. Ça mérite d'y réfléchir (ou pas ?). Je te laisse déjà absorber ça !

À+

nico3333fr commented 6 years ago

De mémoire, les MQ se basent sur les prefs utilisateur https://www.nicolas-hoffmann.net/source/1693-Les-media-queries-et-les-preferences-utilisateurs.html et pas sur le base-font (qui lui est la taille par défaut sur le body)

Donc effectivement, il faudrait que j'utilise $root-default-font-size pour calculer les breakpoints, si j'ai bien compris ton message.

Ce qui donnerait :

@media (max-width: em($breakpoint, $root-default-font-size)) {

Tu peux tester et me confirmer que ça roule ?

ffoodd commented 6 years ago

Je lis en diagonale mais ne vaudrait-il pas mieux utiliser la fonction rem() dans les MQ ? Qu'est-ce que ça impliquerait ?

nico3333fr commented 6 years ago

@ffoodd Non, ça ne marche pas : rem() se base sur le fait de savoir s'il y a un reset ou non pour calculer (pour les 10px = 1rem, toussa), et les MQ se moquent de savoir s'il y a un reset appliqué ou non (lis le billet que j'ai mis plus haut, y a des exemples qui le prouvent).

kloh-fr commented 6 years ago

Ah bien vu ! Dans mon cas je n'ai pas cette variable (je ne sais pas depuis quand tu l'as mais j'avoue que ça fait un moment que j'utilise la même config, et ça date…). C'est déjà une solution un peu mieux intégrée dans le cadre de RÖCSSTI effectivement !

Du coup, j'ai fait une petite mise à jour de mon code et ça fonctionne parfaitement. Et tout suit le mouvement si on change la taille de texte par défaut du navigateur. 👍

@mixin respond-to ($breakpoint, $query-type : 'max') {
  @if $query-type == "max" {
     @media (max-width: em($breakpoint, $root-default-font-size)) {
      @content;
    }
  }

  @else if $query-type == "min" {
     @media (min-width: em($breakpoint, $root-default-font-size)) {
      @content;
    }
  }

  @else  {
    @warn "Type non supporté.";
  }
}

@ffoodd En complément de Nico, dans l'un des articles que j'ai cités, il y est montré que Safari ne suit pas trop avec les MQ en rem, y compris sur mobile. Du coup pas top (ça date de mars 2017). Et un commentaire de l'article dit que ce serait aussi le cas avec Firefox depuis Quantum…

ffoodd commented 6 years ago

Ok, merci à vous deux :)

nico3333fr commented 6 years ago

Je viens de vérifier : Firefox Quantum a bien le comportement que je décris dans le billet cité plus haut (donc le comportement "normal"). Pour Safari, c'était un bug dans iOS 10, fixé dans le 11.

Je patche les versions Sass dès que possible, merci de m'avoir signalé ce bug ;)

nico3333fr commented 6 years ago

Effectivement, j'ai ajouté ça dans la version 4.0 de Röcssti pour la gestion des rem.

Le patch est publié https://github.com/nico3333fr/ROCSSTI/commit/690f92f966565f2995861afaf9ccfbf59dd1cbc1 merci beaucoup de m'avoir signalé ça 👍