Une taille de police en fonction de la largeur d’écran

Cet article a 1 année. Il commence à dater, lisez-le donc en gardant son âge en tête ! Merci

J’ai souvent eu l’occasion à travers mes divers projets Web mobile (responsive), d’avoir à réduire la taille des polices de titre car même un simple mot ne passait pas en largeur. Pour éviter d’avoir une césure sur chaque mot du titre, le plus simple était de s’autoriser une réduction approximative du corps. (approximative… façon de parler). Je vous propose des solutions relative.

CSS3 à la rescousse

Il existe une unité encore peu connue car prise en charge par nos navigateurs depuis peu de temps, il s’agit des unités relative au viewport. Pour comprendre ce qu’est le viewport, je vous invite à lire cette article de Raphaël Goetter : Comprendre le viewport dans le Web mobile.

Pour résumer, nous allons proposer un corps de texte qui dépend de la largeur de la fenêtre du navigateur.
Vous connaissez certainement les unités px, em, rem ou pt pour dimensionner vos corps de texte ? Rajoutez à cette liste :

  • vw : « Viewport Width », correspond à l’unité relative à la largeur de votre écran
  • vh : « Viewport Height », correspond à l’unité relative à la hauteur de votre écran
  • vmin (vm pour IE9) : « Viewport Min », correspond à l’unité relative à la plus petite des deux dimensions (largeur ou hauteur selon l’orientation)
  • vmax : « Viewport Max », correspond à l’unité relative à la plus grande des deux dimensions (largeur ou hauteur selon l’orientation)

Très bien, mais que représente une unité de vw, par exemple ?
C’est assez simple mais pas forcément intuitif de prime abord : 1 unité représente 1% de la dimension de référence.

Prenons un exemple plus parlant.
Si j’écris ce morceau de code CSS appliqué à mon titre de niveau 1 :

h1 {
   font-size: 10vw;
}

Mon corps de texte aura un équivalent de 10% de la largeur de mon viewport, à savoir la largeur de la fenêtre de votre navigateur.
Sur l’écran que j’utilise actuellement, la définition est de 1920px de large, mon titre de niveau 1 aura alors une font-size équivalente à 192px.

Bien que la spécification du W3C sur ces unités prévoit qu’au changement de dimensions du viewport, les dimensions des éléments bénéficiant des unités vw, vh, vmin et vmax soient mis à jour, il semblerait que Chrome n’en fasse qu’à sa tête (Safari également probablement, mais je n’ai pas la version 6 sur PC ;) )

Il vous faudra donc recharger la page sur la page de démonstration à chaque redimensionnement de la fenêtre du navigateur.
Voir la démonstration
J’ai ajouté un petit script JavaScript pour auto rafraichir le calcul, basé sur l’évènement « resize » de la fenêtre.
Pour les curieux, le voici, il est basé sur jQuery.

<script>
  $(window).resize(function() {
	$('h1, h2').css('z-index', 'auto'); //auto reflow
  });
</script>

Le support est encore partiel, mais ces unités sont utilisables pour bientôt, et déjà pour la cible iPhone, Chrome 20+, Firefox 19+, Opera 15.0+ et IE10+.
Voir le support sur CanIuse

Pour les curieux, voici également une petite expérimentation de respect d’un ratio 16:9 en fonction du viewport.

Solution de secours en JS

Fittext.js

Il existe une alternative en JavaScript – comme souvent – qui se nomme FitText.js, qui est un plugin jQuery (hélas).
Cette solution fonctionne a priori partout sauf sur IE et propose de rajouter dynamiquement un attribut style sur un élément en faisant varier la taille de font-size en pixels.

  1. Téléchargez la ressource sur Github
  2. Appelez la librairie jQuery et le script Fittext depuis votre document HTML
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
    <script src="jquery.fittext.js"></script>
  3. Puis ciblez les éléments textuels que vous souhaitez contraindre
    <script>
       $(".responsive_headline").fitText(); // basique
       $(".responsive_h3").fitText(1.2); // compression proportionnelle
       $(".responsive_headline").fitText(0.8); // décompression proportionnelle
       $(".responsive_headline").fitText(1.2, { minFontSize: '20px', maxFontSize: '40px' }); // compression avec taille max et taille min
    </script>

Voir la démonstration sur fittextjs.com

C’est probablement la meilleure alternative aujourd’hui, cependant elle ne fonctionne pas sur Internet Explorer.

Conclusion

Ces essais manquent de tests, n’hésitez pas à me faire vos retours dans les commentaires sur différents navigateurs (Safari 6 Mac, Android, etc.).
Merci à vous !

46 commentaires sur “Une taille de police en fonction de la largeur d’écran”

  1. 29 octobre 2012

    « Il existe une alternative en JavaScript – comme souvent – qui se nomme FitText.js, qui est un plugin jQuery (hélas). » Pourquoi « hélas » ?
    J’allais justement me pencher sur le problème des largeur de titres, donc merci :)

    • Geoffrey dit :
      29 octobre 2012

      Hello,
      Oui je ne suis pas allé au bout de mon idée : jQuery sur mobile ça me semble bien lourd, surtout s’il faut le charger juste pour gérer du texte. Je pense qu’une solution JS sans framework aurait été la bienvenue.
      Bon courage pour ton projet :)

  2. 29 octobre 2012

    Ah oui d’accord ! Merci :)

  3. Julien dit :
    29 octobre 2012

    Excellent. Je cherchais cette technique depuis un moment. Merci.

    Quelle est la différence avec -webkit-text-size-adjust ?

  4. Geoffrey dit :
    29 octobre 2012

    Salut Julien,

    -webkit-text-size-adjust ne s’adresse qu’à webkit, plus précisément à Safari iPhone.

    Contrairement à l’unité vw et suivantes, -webkit-text-size-adjust ne sert qu’à préciser un calcul en pourcentage d’une taille de police initiale, et non en fonction de la largeur de l’écran.

    Je ne sais pas si mon explication est très claire… ^^ »

  5. Julien dit :
    29 octobre 2012

    Si si, je me doutais que le préfixe renvoyait à chrome et safari mais je vois mieux la différence. Merci.

    • Geoffrey dit :
      29 octobre 2012

      Je risquerais de dire des bêtises, mais le « adjust » n’est pas compris par Chrome il me semble, c’est vraiment du iOS Safari (à moins qu’il soit compris par Chrome sur iOS).

  6. jpvincent dit :
    29 octobre 2012

    Je ne suis pas bon en typographie, mais je me souviens d’une règle de typographie utile, qui dit qu’une ligne de texte doit faire entre 45 et 75 caractères pour être confortable à lire (généralement on retient 66).
    Logiquement on pourrait mixer em et vw pour avoir du texte qui respecte toujours cette règle quelle que soit la largeur disponible : comment calculerait tu cela ?
    100 / 66 = 1,5 vw ?

  7. Geoffrey dit :
    30 octobre 2012

    Hello JPVincent :)

    Je ne pense pas qu’on puisse trouver un mode de calcul aussi simple, puisque l’unité prend comme référence la largeur de l’écran et non la largeur disponible dans son parent direct. Si tu commences à avoir du texte dans une boîte flottante, avec des marges et padding, tu vas vite te retrouver avec des calculs faussés.

    Mais effectivement c’est un excellent moyen de conserver un nombre de mots par ligne confortable pour la lecture.

    PS : j’espère ne pas avoir mal compris ton commentaire…

  8. jpvincent dit :
    30 octobre 2012

    effectivement ça ne marche que sur du mono colonne, du coup tu as un design vraiment fluide, mais ça n’aide pas au responsive layout.
    Ma question pouvait sembler bizarre, parce que j’en suis au stade des interrogations sur ces intégrations fluides, je n’ai pas encore vraiment mis les mains dedans

  9. Kevin Py dit :
    9 novembre 2012

    J’ai voulu tester sur mon prochain site, juste pour voir, mais il y a l’air d’avoir une incompatibilité avec le maximum scale. Voici ma règle:

    Donc, jusque là, rien d’anormal (à mon avis). Par contre, avec des dimensions en rapport avec le viewport, cela annule le maximum scale.

    A voir chez d’autres gens.

    • Geoffrey dit :
      9 novembre 2012

      Salut,
      Bizarrement le code a sauté…
      Sur quel terminal/installation as-tu testé ?
      Avec quelle solution ? (CSS ou JS)
      Pourquoi un maximum-scale ?
      Quelle est ta cible ?

  10. Kevin Py dit :
    10 novembre 2012

    J’ai testé sur mon iPhone 4S (pas encore sur mon iPad 2), le tout en comme tu l’as indiquer.

    J’ai mis un maximum scale, car le design est responsive et que la typo se veut clair et agréable à lire. Voila pourquoi j’ai mis un maximum scale, afin que l’utilisateur n’est pas à zoomer, car tout s’affiche en grand pour le confort de l’oeil.

    • Geoffrey dit :
      11 novembre 2012

      Bonsoir,
      Le problème du minimum et maximum-scale, c’est qu’en les utilisant tu prétends connaître le confort de lecture de tous tes visiteurs. Or c’est impossible. Peut-être que l’utilisateur aura besoin de zoomer au delà de la limite que tu lui imposes…
      Le problème survient en utilisant la technique CSS ou JS ? Ne pas oublier que pour le moment le corps ne s’adapte pas automatiquement au zoom et dezoom à cause d’un bug webkit. Il faut utiliser le petit hack de reflow en JS pour que ça fonctionne.

  11. Kevin Py dit :
    14 novembre 2012

    Salut,
    désolé de pas t’avoir répondu avant. En ce qui concerne le maximum scale, il s’agit d’une webapp, donc pas besoin de zoom normalement ^^.

    Sinon, il s’agit de la solution css.

  12. Geoffrey dit :
    14 novembre 2012

    Hello,

    Je n’ai pas pu reproduire le bogue de mon côté :/ Navré.

    Pour revenir sur cette histoire de maximum scale, un mec qui a 3 sur 10 à chaque œil ne pourra pas lire le contenu de ta web app sur un corps de texte équivalent à 18px car il ne peut pas zoomer (les chiffres ne sont peut-être pas réalistes).

    S’il te contacte (s’il y arrive) pour ce problème tu vas lui répondre quoi ? Qu’il « n’a pas besoin de zoom normalement » ?

    L’accessibilité n’est pas une option. Si tu portes des lunettes qui te permettent une bonne correction, et qu’un jour tu les casses, tu verras à quel point l’accessibilité numérique peut t’être utile ;)

    Bonne journée.

  13. Kevin Py dit :
    14 novembre 2012

    T’as tout à fait raison, mais comme il s’agissait d’une webapp, on peut constater que les apps ne zoom pas.

    Sinon, c’est pas grave pour ce bug, le maximum scale n’est pas une bonne pratique ^^.

  14. Greg dit :
    17 novembre 2012

    Salut salut :)

    Merci pour l’article.
    J’ai voulu tenter un truc fou :
    -webkit-transform: perspective(156vw);
    Et bien raté, le 156vw est interprété comme 156px -_-’ Dommage ;)

    A+

  15. Geoffrey dit :
    18 novembre 2012

    Salut :)

    Ah oui tu as tenté un truc de fou en effet :D
    L’unité ne s’applique pas à toutes les propriétés oui. J’ai pas vu ce que disais le w3c à ce propos.

  16. 9 janvier 2013

    salut Geoffrey

    tout d’abord je te souhaite une très bonne année et pleins de bonheur.

    je me permets de te demander sur ce sujet quelle option tu adopte sur tes sites ? car ton tuto est super complet, mais il ne laisse pas apparaitre ta préférence !

    bonne journée :)

    • Geoffrey dit :
      9 janvier 2013

      Hello,
      Merci et bonne année également :)
      En fait tout dépend du support souhaité par le client.
      En général je préfère les solutions sans JS, je fais donc en sorte d’avoir un texte « qui rentre » de base, puis j’améliore la lisibilité avec la technique CSS (si elle est comprise par le terminal du visiteur, bien sûr).
      Tout est une histoire de compromis, comme toujours :)

  17. 20 février 2013

    Je confirme que ça marche parfaitement sur Firefox 19.

    Par contre, je ne considère pas que ton exemple est un équivalent de FitText.

    Ton « font-size: 12vw; » appliqué au h1 ne fonctionne que pour « CreativeJuiz », notamment parce qu’il y a deux « i » fins dedans. Avec des lettres plus larges (essaie d’en mettre autant mais que des « M » par exemple), ça ne tiendra pas dans la largeur disponible. Il faudra réduire la valeur. Ce n’est donc pas généralisable.

    Le problème est toujours le même, il faudrait pouvoir définir la largeur d’une phrase, avec une instruction similaire à background-size « contain » ou « cover » :

    p.fittext {
    word-wrap: none;
    text-size: contain;
    }

    • Geoffrey dit :
      20 février 2013

      Bonjour Nicolas,

      Merci pour l’info du support de Firefox 19.
      Je ne comprends pas bien ton intervention.

      Bien sûr que la taille choisie ne fonctionne que pour le texte choisi, tout comme un design de 960px de large ne fonctionnera que pour cette largeur et sera repensé pour des tailles supérieures ou inférieures.
      Cette technique n’a pas pour but de contraindre un texte à s’afficher sur une ligne quel que soit le nombre de caractères, c’est impensable, je n’imagine même pas les dégâts sur la lisibilité en production sur un CMS.

      Le jour où tu penseras avoir résolu ton « problème » tu en amèneras un nouveau : celui de la lisibilité.
      Bonne journée :)

  18. 20 février 2013

    Oups, coquille, c’est ceci qu’il faudrait écrire :

    p.fittext {
    white-space: nowrap;
    text-size: contain;
    }

  19. 20 février 2013

    Geoffrey, cette technique ne serait intéressante bien entendu que sur de la titraille, cela se veut juste une version standardisée et sans JS de FitText… ;-)

    • Geoffrey dit :
      20 février 2013

      Il y a bien WebKit qui avait tenté un « text-size-adjust », je ne sais pas ce que ça donnerait avec une valeur en vm*. En fait je n’ose ni tester ni y accorder du crédit :p
      Merci pour ton intervention et proposition :)

  20. 20 février 2013

    Une fois de plus, text-size-adjust s’intéresse à la hauteur du texte, pas à sa largeur, donc cela ne me semble pas utilise dans le cas présent.

    • Geoffrey dit :
      20 février 2013

      Ok merci pour l’info, j’ai un peu de mal avec « largeur » et « hauteur » d’un texte, pour moi c’est une « taille de corps ». Mais je comprends l’idée et ça ne concerne effectivement pas cette problématique :)

  21. casp dit :
    4 mars 2013

    Moi j’ai opter pour la solution JS, car de toute façon je fait appel à jquery pour d’autres script.

    Maintenant je devrais peux être supprimer tout le JS pour la version smartphone ? Je ne me rend pas trop compte. Je ne suis pas encore au point de ce côté, peux être est ce du à mon rejet malgré mon métier de webdesigner des smartphones,(que je trouve extrêmement polluant, inutile etc.. je préfère les téléphones qui ne font que téléphoner sans couleur. De plus en plus dur à trouver)

    Bref je devie..

    Conclusion, je suis assez satisfait de FitText. Je l’ai utilisé sur l’ensemble du site, bien qu’il recommande de ne pas le faire… Ai je eu tort ? je ne sais pas pourquoi j’imagine temps de calcul ? Mais je n’ai rien constaté d’alarmant.

    Seul défault par rapport à chrome il recalcul la taille par étape et non de manière parfaitement fluide, Ce qui m’a causé parfois quelques souci.

    Pour IE pas de problème constaté cela fonctionne. Sur IE7 8 9 et 10

    Cordialement.

  22. JiPe38 dit :
    8 mars 2013

    Bonjour
    font-size: 12vw;
    Ne marche pas avec Firefox 13.0.1, ni avec IE 8.0, les antiquités que l’administrateur des pc de ma boite nous fournit généreusement…

  23. Seb dit :
    17 mars 2013

    merci, pour ce post, ça répond à mes interrogations sur le design responsive et la police.

    juste pour info, ça ne fonctionne pas sur Opera (Version 12.14)

  24. Céline dit :
    27 mars 2013

    Bonjour,
    J’aurai une question, peut-être idiote ! Est-ce que ça ne revient pas au même d’écrire « font-size: 10%; » ? Puisque 10vw = 10%.

    • Geoffrey dit :
      28 mars 2013

      Hello,
      Non puisque le 10% du font-size prend en référence la cascade CSS, il s’agit donc de 10% de la taille de base de la font. 10vw prend en référence la largeur de la vue sur l’écran, le référent n’étant donc pas le même, on ne peut pas confondre les deux.

  25. Céline dit :
    28 mars 2013

    D’accord oui ! Merci beaucoup pour tes explications ;) Oui effectivement ce n’est pas la même chose ! :$

  26. Usu dit :
    27 avril 2013

    Merci Geoffrey pour ce petit tuto !
    Je suis actuellement en train de refaire le site de mon auto-entreprise et je voulais savoir à la base s’il était possible de définir soi-même les tailles de tous les éléments de son site par rapport à la taille du navigateur sans js.
    Et après quelques tests, je confirme c’est possible grâce à ces fameuses unités liés au viewport.
    Voici le résultat : http://www.honet-design.fr/test.php
    C’est surtout la valeur vmin qui m’a été utile ici : les zoom n’ont aucun effet, les changements de taille du navigateur sont totalement pris en compte, c’était mon but initial :D
    Cependant, on se rend rapidement compte que l’accessibilité devient mauvaise sur les appareils ou le vh est plus grand que le vw.

    Sans parler du fait que ca ne fonctionne que sous FF19.

    Mais les tests était rigolo à faire ^^

    • Geoffrey dit :
      27 avril 2013

      Salut salut,
      Merci de partager tes tests avec nous :)
      Effectivement le test est pas mal et présente bien les limites de la chose. C’est comme cela qu’on peut se rendre compte des possibilités de nos outils et langages préférés.
      Bonne continuation dans ta refonte !

  27. Vincent dit :
    5 juin 2013

    Merci pour cet article !
    En revanche sur Chrome j’avoue que ça ne fonctionne pas chez moi.
    v27 sur un win 7. J’ai essayé de chercher éventuellement une option à activer dans les flags de chrome, mais sans succès.

    • Geoffrey dit :
      5 juin 2013

      Ah oui d’accord, je vois ça. Ben c’est encore une régression de Chrome d’une version à l’autre j’imagine.
      Aaaaaah ! Chrome, ce nouvel IE.
      En tout cas c’est supporté par Firefox, et pas besoin de script pour lui (et pas de régression, juste une progression :p), il respecte la spec.

  28. Florian dit :
    8 juin 2013

    Sympa comme technique.

    C’est frustrant quand on développe des web apps en mobile first, on doit attendre sans cesse le support des navigateurs et des nouvelles recommandations du W3C pour avoir un site de plus en plus responsive.

    Je rêve de partir deux ans au soleil et de revenir avec un HTML5 et CSS3 « terminé ».

  29. nicolas dit :
    13 novembre 2013

    Bonsoir à tous j’ai un problème avec jquery.fittext, en gros quand j’applique la formule et que je visualise mon site sur firefox ça marche du feu de dieu mais dès que j’essaie de le visualiser sur chrome, je suis obligé d’actualiser la page pour que le fittext marche et j’avoue que pour l’instant je bloque, si quelqu’un à la réponse je le remercie par avance

    • Geoffrey dit :
      9 avril 2014

      Navré je n’avais jamais vu passer ton commentaire pourtant validé :/
      As-tu essayé avec le FitText sans JS proposé par Gaetan ?
      Merci.

  30. maiky dit :
    27 janvier 2014

    ça fait plus d’1 an et ce n’est qu’aujourd’hui que je vois cette possibilité, à la date d’aujourd’hui je suppose que cette norme à été adopté par tous les navigateurs en tout cas c’est tout le pire que je puisse souhaiter. Ce code m’a rendu énormément service et je pouvais pas passer à coter d’un grand merci et de reconnaissance.

    • Geoffrey dit :
      27 janvier 2014

      Hello,
      Il n’est jamais trop tard :)
      Le support est bien meilleur mais ça n’est pas encore suffisamment répandu et parfois bogué. Mais c’est à utiliser dans le sens de l’amélioration progressive.
      Bonne continuation.

Laisser un commentaire

Certains codes HTML ne sont pas échappés automatiquement. Pour afficher du code dans votre commentaire, merci d'échapper vos chevrons en utilisant "&lt;" et "&gt;" en lieu et place de "<"" et ">".

Il est difficile de proposer un support pour tous les articles de ce blog. En ne fournissant pas un moyen de consulter votre code bogué, vous vous assurez de ne pas avoir de réponse adaptée. Utilisez CodePen.io à défaut d'une page web.

 
Le studio web