Mise à l'échelle des polices en fonction de la largeur du conteneur


1189

J'ai du mal à comprendre la mise à l'échelle des polices.

J'ai actuellement ce site avec un corps à font-size100%. 100% de quoi cependant? Cela semble se calculer à 16 pixels.

J'avais l'impression que 100% feraient en quelque sorte référence à la taille de la fenêtre du navigateur, mais apparemment pas parce qu'il s'agit toujours de 16 pixels, que la fenêtre soit redimensionnée sur une largeur mobile ou sur un grand écran de bureau.

Comment faire le texte à l'échelle de mon site par rapport à son conteneur? J'ai essayé d'utiliser em, mais cela ne s'adapte pas non plus.

Mon raisonnement est que les choses comme mon menu ne sont écrasées lorsque vous redimensionnez, donc je dois réduire les px font-sized' .menuItementre autres éléments par rapport à la largeur du conteneur. (Par exemple, dans le menu sur un grand bureau, 22pxfonctionne parfaitement. Descendez à la largeur de la tablette et 16pxest plus approprié.)

Je sais que je peux ajouter des points d'arrêt, mais je veux vraiment que le texte soit mis à l'échelle ainsi que d'avoir des points d'arrêt supplémentaires, sinon, je vais me retrouver avec des centaines de points d'arrêt pour chaque diminution de 100 pixels de largeur pour contrôler le texte.


34
font-size: 100%;signifie 100% de la taille du texte (c'est-à-dire celui dont il hérite de son parent). Par défaut, c'est 16 pixels. Donc, si vous avez utilisé 50%, ce serait la taille de police: 8px
Andy

31
Ce que vous recherchez s'appelle une typographie réactive ou de la taille d'une fenêtre. css-tricks.com/viewport-sized-typography
gearsdigital

8
Donnez FitText un coup d' oeil.
Patsy Issa

12
@Andy: En fait, "par défaut" correspond à la taille de texte du navigateur définie par les utilisateurs, qui ne se résout pas nécessairement à 16 pixels.
ScottS

Réponses:


1496

EDIT: si le conteneur n'est pas le corps, CSS Tricks couvre toutes vos options dans l' ajustement du texte à un conteneur .

Si le conteneur est le corps, vous recherchez des longueurs en pourcentage de la fenêtre d'affichage :

Les longueurs en pourcentage de la fenêtre sont relatives à la taille du bloc contenant initial . Lorsque la hauteur ou la largeur du bloc contenant initial est modifiée, elles sont mises à l'échelle en conséquence. Cependant, lorsque la valeur de débordement sur l'élément racine est auto, toutes les barres de défilement sont supposées ne pas exister.

Les valeurs sont:

  • vw (% de la largeur de la fenêtre)
  • vh (% de la hauteur de la fenêtre)
  • vi (1% de la taille de la fenêtre dans la direction de l'axe en ligne de l'élément racine)
  • vb (1% de la taille de la fenêtre dans la direction de l'axe du bloc de l'élément racine)
  • vmin(le plus petit de vwou vh)
  • vmax(le plus grand ou vwou vh)

1 v * est égal à 1% du bloc contenant initial.

Son utilisation ressemble à ceci:

p {
    font-size: 4vw;
}

Comme vous pouvez le constater, lorsque la largeur de la fenêtre d'affichage augmente, il en va de même pour font-size, sans avoir besoin d'utiliser des requêtes de médias.

Ces valeurs sont une unité de dimensionnement, tout comme pxou em, elles peuvent donc également être utilisées pour dimensionner d'autres éléments, tels que la largeur, la marge ou le rembourrage.

La prise en charge du navigateur est assez bonne, mais vous aurez probablement besoin d'une solution de secours, telle que:

p {
    font-size: 16px;
    font-size: 4vw;
}

Consultez les statistiques de support: http://caniuse.com/#feat=viewport-units .

Consultez également les astuces CSS pour une vision plus large: Typographie de taille de fenêtre

Voici un bel article sur la définition des tailles minimum / maximum et l'exercice d'un peu plus de contrôle sur les tailles: Contrôle précis de la typographie réactive

Et voici un article sur la définition de votre taille à l'aide de calc () afin que le texte remplisse la fenêtre d'affichage: http://codepen.io/CrocoDillon/pen/fBJxu

Veuillez également consulter cet article, qui utilise également une technique baptisée «fusion fondue» pour ajuster la hauteur de ligne. Fondu leader en CSS


548
Mais que faire si le conteneur n'est pas la fenêtre (corps)?
Alex

12
@Alex, c'est le territoire JS. Essayez l' FitText.jsalternative fournie au bas de l'article @jbenjohnson fourni.
Robbert

10
C'est là que les soi-disant requêtes d'éléments entrent en jeu. Contrairement aux requêtes multimédias, les requêtes d'éléments dimensionneraient les choses en fonction de son bloc contenant, et non de la fenêtre d'affichage, ce qui serait étonnant! Mais malheureusement, il n'existe pas encore. Cependant, certains polyfills et preuves de concept existent si vous êtes intéressé: coding.smashingmagazine.com/2013/06/25/… et filamentgroup.com/lab/element_query_workarounds
jbenjohnson

140
Rétrogradé car cela ne répond pas à la question. Il a posé des questions sur le conteneur, pas sur la fenêtre. Cas d'utilisation complètement différent.
SongBox

6
"bloc contenant initial" fait référence à l'élément racine. Ce n'est pas la bonne réponse à la question posée.
Glyphe

320

Mais que faire si le conteneur n'est pas la fenêtre (corps)?

Cette question est posée dans un commentaire d'Alex sous la réponse acceptée .

Ce fait ne signifie pas qu'il ne vwpeut pas être utilisé dans une certaine mesure pour dimensionner ce conteneur. Maintenant, pour voir toute variation, il faut supposer que le conteneur est en quelque sorte de taille flexible. Que ce soit par un pourcentage direct widthou en étant 100% moins les marges. Le point devient "théorique" si le conteneur est toujours défini sur, disons, 200pxlarge - alors définissez simplement un font-sizequi fonctionne pour cette largeur.

Exemple 1

Avec un conteneur à largeur flexible, cependant, il faut comprendre que d'une certaine manière, le conteneur est toujours dimensionné hors de la fenêtre . En tant que tel, il s'agit d'ajuster un vwparamètre basé sur cette différence de taille en pourcentage à la fenêtre, ce qui signifie prendre en compte le dimensionnement des wrappers parents. Prenez cet exemple :

div {
    width: 50%;
    border: 1px solid black;
    margin: 20px;
    font-size: 16px;
    /* 100 = viewport width, as 1vw = 1/100th of that
       So if the container is 50% of viewport (as here)
       then factor that into how you want it to size.
       Let's say you like 5vw if it were the whole width,
       then for this container, size it at 2.5vw (5 * .5 [i.e. 50%])
    */
    font-size: 2.5vw;
}

En supposant qu'ici divest un enfant de body, il est 50%de cette 100%largeur, qui est la taille de la fenêtre d'affichage dans ce cas de base. Fondamentalement, vous voulez définir un vwqui va bien vous paraître. Comme vous pouvez le voir dans mon commentaire dans le contenu CSS ci-dessus, vous pouvez "réfléchir" mathématiquement à la taille complète de la fenêtre d'affichage, mais vous n'avez pas besoin de le faire. Le texte va "fléchir" avec le conteneur car le conteneur fléchit avec le redimensionnement de la fenêtre. MISE À JOUR: voici un exemple de deux conteneurs de tailles différentes .

Exemple 2

Vous pouvez aider à garantir le dimensionnement de la fenêtre en forçant le calcul en fonction de cela. Considérez cet exemple :

html {width: 100%;} /* Force 'html' to be viewport width */
body {width: 150%; } /* Overflow the body */

div {
    width: 50%;
    border: 1px solid black;
    margin: 20px;
    font-size: 16px;
    /* 100 = viewport width, as 1vw = 1/100th of that
       Here, the body is 150% of viewport, but the container is 50%
       of viewport, so both parents factor  into how you want it to size.
       Let's say you like 5vw if it were the whole width,
       then for this container, size it at 3.75vw
       (5 * 1.5 [i.e. 150%]) * .5 [i.e. 50%]
    */
    font-size: 3.75vw;
}

Le dimensionnement est toujours basé sur la fenêtre, mais est essentiellement configuré en fonction de la taille du conteneur lui-même.

La taille du conteneur doit-elle changer dynamiquement ...

Si le dimensionnement de l'élément conteneur finissait par changer dynamiquement sa relation en pourcentage via des @mediapoints d'arrêt ou via JavaScript, alors quelle que soit la "cible" de base, il faudrait recalculer pour conserver la même "relation" pour le dimensionnement du texte.

Prenons l'exemple n ° 1 ci-dessus. Si le a divété changé en 25%largeur par @mediaou par JavaScript, alors en même temps, le font-sizedevrait ajuster dans la requête multimédia ou par JavaScript au nouveau calcul de 5vw * .25 = 1.25. Cela donnerait à la taille du texte la même taille qu'elle aurait été si la "largeur" ​​du 50%conteneur d' origine avait été réduite de moitié par rapport au dimensionnement de la fenêtre d'affichage, mais a maintenant été réduite en raison d'une modification de son propre calcul de pourcentage.

Un défi

Avec la calc()fonction CSS3 utilisée, il deviendrait difficile de s'ajuster dynamiquement, car cette fonction ne fonctionne pas pour le font-sizemoment. Vous ne pouvez donc pas effectuer un ajustement CSS 3 pur si votre largeur change calc(). Bien sûr, un ajustement mineur de la largeur pour les marges peut ne pas être suffisant pour justifier un changement font-size, il peut donc ne pas avoir d'importance.


(Il y a un bogue Chrome avec des longueurs en pourcentage de la fenêtre d' affichage et un redimensionnement de la fenêtre: code.google.com/p/chromium/issues/detail?id=124331 )
thirtydot

@thirtydot: C'est malheureux (mais bon à savoir, merci). J'espère que le bogue sera bientôt résolu, mais il semble qu'il persiste depuis un certain temps.
ScottS

20
Bonne réponse, cependant, cela ne fonctionnera pas si l'élément contenant a une largeur maximale.
Himmators

3
@KristofferNolgren: Cela concerne deux points soulevés dans ma réponse: (1) "en supposant que le conteneur est en quelque sorte de taille flexible" (une fois que 'max-width' est atteint, il ne fléchit plus, donc il y a alors un problème ). (2) Si l'on peut déterminer à quel point la `` largeur maximale '' serait atteinte, alors comme je l'ai noté, vous pouvez définir un @mediapoint d'arrêt pour changer la taille de la police à ce point (en lui donnant essentiellement une taille fixe à atteindre max-width) . Juste une pensée pour travailler avec une max-widthsituation.
ScottS

Pensez-vous que vous pouvez jeter un violon lorsque l'élément conteneur change dynamiquement par le biais de requêtes multimédias? Je ne suis pas sûr de comprendre.
J82

59

Solution avec SVG:

<div style="width: 60px;">  
  <svg width="100%" height="100%" viewBox="0 -200 1000 300"
     xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <text font-size="300" fill="black">Text</text>
  </svg>
</div>

https://jsfiddle.net/qc8ht5eb/


Solution avec SVG et habillage de texte en utilisant foreignObject:

<svg viewBox="0 0 100 100">
  <foreignObject width="100%" height="100%">
    <h1>heading</h1>

    lorem ipsum dolor sit amet
  </foreignObject>
</svg> 

https://jsfiddle.net/2rp1q0sy/


1
Cette idée est belle au début. Ensuite, vous réalisez que vous ne pouvez pas contrôler facilement la police sur SVG dans <html>. La police est différente sur mobile et sur ordinateur, ce qui a un impact sur la largeur finale.
Stopi

@Stopi que pensez-vous d'une solution iFrame? exemple
Dantio

10
Vous pouvez totalement
styliser

1
SVG peut être stylisé avec css si le svg est en ligne (n'utilisez pas de balise img).

8
Il s'agit de la solution la meilleure et la plus prévisible qui évolue en fonction d'un conteneur dynamique.
JoshuaDavid

35

Dans l'un de mes projets, j'utilise un "mélange" entre vw et vh pour ajuster la taille de police à mes besoins, par exemple:

font-size: calc(3vw + 3vh);

Je sais que cela ne répond pas à la question du PO, mais peut-être que cela peut être une solution pour n'importe qui d'autre.


3
Il vaut peut-être mieux utiliser vminet / ou à la vmaxplace.
sebastian_k

4
chrome dev tools appelle cela une valeur de propriété non valide
phil294

31

Solution Pure-CSS avec calc(), unités CSS et mathématiques

Ce n'est précisément pas ce que demande OP, mais peut faire la journée de quelqu'un. Cette réponse n'est pas facile à utiliser à la cuillère et nécessite des recherches du côté du développeur.

Je suis finalement venu pour obtenir une solution pure CSS pour cette utilisation calc()avec différentes unités. Vous aurez besoin d'une compréhension mathématique de base des formules pour déterminer votre expression calc().

Quand j'ai travaillé cela, j'ai dû obtenir un en-tête réactif pleine largeur avec du rembourrage quelques parents dans DOM. Je vais utiliser mes valeurs ici, les remplacer par les vôtres.

Aux mathématiques

Tu auras besoin de:

  • Rapport bien ajusté dans certaines fenêtres. J'ai utilisé 320 pixels, donc j'ai 24 pixels de haut et 224 pixels de large, donc le rapport est de 9,333 ... soit 28/3
  • La largeur du conteneur, j'avais padding: 3emet toute la largeur, donc cela est arrivé à100wv - 2 * 3em

X est la largeur du conteneur, alors remplacez-le par votre propre expression ou ajustez la valeur pour obtenir le texte pleine page. Rest le rapport que vous aurez. Vous pouvez l'obtenir en ajustant les valeurs dans une fenêtre, en inspectant la largeur et la hauteur des éléments et en les remplaçant par vos propres valeurs. C'est aussi width / heigth;)

x = 100vw - 2 * 3em = 100vw - 6em
r = 224px/24px = 9.333... = 28 / 3

y = x / r
  = (100vw - 6em) / (28 / 3)
  = (100vw - 6em) * 3 / 28
  = (300vw - 18em) / 28
  = (75vw - 4.5rem) / 7

Et bang! Ça a marché! J'ai écrit

font-size: calc((75vw - 4.5rem) / 7)

à mon en-tête et il s'est bien ajusté dans chaque fenêtre.

Mais comment ça fonctionne?

Nous avons besoin de constantes ici. 100vwsignifie la pleine largeur de la fenêtre, et mon objectif était d'établir un en-tête pleine largeur avec un peu de rembourrage.

Le rapport. Obtenir une largeur et une hauteur dans une fenêtre m'a permis de jouer avec un rapport, et avec un rapport, je sais quelle devrait être la hauteur dans une autre largeur de fenêtre. Les calculer à la main prendrait beaucoup de temps et prendrait au moins beaucoup de bande passante, donc ce n'est pas une bonne réponse.

Conclusion

Je me demande pourquoi personne n'a compris cela et certaines personnes disent même que ce serait impossible de bricoler avec CSS. Je n'aime pas utiliser JavaScript pour ajuster les éléments, donc je n'accepte pas les réponses JavaScript (et j'oublie jQuery) sans creuser plus. Dans l'ensemble, il est bon que cela ait été compris et c'est une étape vers des implémentations purement CSS dans la conception de sites Web.

Je m'excuse de toute convention inhabituelle dans mon texte, je ne suis pas un locuteur natif en anglais et je suis également assez nouveau pour écrire des réponses Stack Overflow.

Il convient également de noter que nous avons des barres de défilement maléfiques dans certains navigateurs. Par exemple, lors de l'utilisation de Firefox, j'ai remarqué que cela 100vwsignifie la pleine largeur de la fenêtre d'affichage, s'étendant sous la barre de défilement (où le contenu ne peut pas se développer!), Donc le texte pleine largeur doit être soigneusement margé et de préférence testé avec de nombreux navigateurs et appareils.


13
Cette solution ne fonctionne que SI (1) vous connaissez la police, (2) la police est disponible sur l'appareil de l'utilisateur et (3) le texte est toujours le même. Cela en fait un cas d'utilisation très limité.
Andrei Volgin

je ne comprends pas si mon conteneur est fixe avec par exemple: 640px et un rapport de 16: 9. quels calculs dois-je écrire?
pery mimon

1
La largeur de votre conteneur xest de 640px et son rapport r16: 9, donc: x = 640px, r = 16 / 9, y = x / r = 640px / (16 / 9) = 360px
hegez

Remarque: cela ne fonctionne que si vous avez réellement un texte de 16: 9, ce qui est une situation étrange. Peut-être que lire la réponse une deuxième fois peut aider. En outre, cela ne fonctionne que pour les monolignes.
hegez

Pour être honnête, vous n'expliquez pas "Ratio bien ajusté dans certaines fenêtres. J'ai utilisé 320 pixels, donc j'ai 24 pixels de haut et 224 pixels de large, donc le ratio est de 9,333 ... ou 28/3" Je suggère d'expliquer le ratio un peu plus. Que représente le ratio?
3limin4t0r

28

Il y a une grande philosophie pour ce problème.

La chose la plus simple à faire serait de donner une certaine taille de police au corps (je recommande 10), puis tous les autres éléments auraient leur police dans emou rem. Je vais vous donner un exemple pour comprendre ces unités. Emest toujours relatif à son parent:

body{font-size: 10px;}
.menu{font-size: 2em;} /* That means 2*10 pixels  = 20 pixels */
.menu li{font-size: 1.5em;} /* That means 1.5*20 pixels = 30 pixels */

Rem est toujours relatif au corps:

body{font-size: 10px;}
.menu{font-size: 2rem;} /* That means 2*10 pixels = 20 pixels */
.menu li{font-size: 1.5rem;} /* that means 1.5*10 pixels = 15 pixels */

Et puis vous pouvez créer un script qui modifierait la taille de la police par rapport à la largeur de votre conteneur. Mais ce n'est pas ce que je recommanderais. Parce que dans un conteneur d'une largeur de 900 pixels par exemple, vous auriez unp élément avec une taille de police de 12 pixels disons. Et selon votre idée, cela deviendrait un conteneur de 300 pixels de large avec une taille de police de 4 pixels. Il doit y avoir une limite inférieure.

D'autres solutions consisteraient à effectuer des requêtes sur les supports, afin que vous puissiez définir la police pour différentes largeurs.

Mais les solutions que je recommanderais sont d'utiliser une bibliothèque JavaScript qui vous aide avec ça. Et fittext.js que j'ai trouvé jusqu'ici.


6
L' remunité est relative à l'élément racine, c'est-à-dire l' htmlélément, pas l' bodyélément. L'élément racine dans le DOM est la htmlbalise. developer.mozilla.org/en-US/docs/Web/CSS/length .. remest toujours relatif à la htmlbalise, qui est l'élément racine, pas la balise body .. mais une bonne réponse :)
Jonathan Marzullo

fittext.js fait le travail, j'ai recommandé cette solution!
Jacek Dziurdzikowski

FitText a été le gagnant pour moi. J'ai essayé quelques alternatives, mais cela semblait le plus simple et aussi bien intégré au CMS Drupal / Backdrop. github.com/davatron5000/FitText.js
Auxiliaire Joel

23

Voici la fonction:

document.body.setScaledFont = function(f) {
  var s = this.offsetWidth, fs = s * f;
  this.style.fontSize = fs + '%';
  return this
};

Convertissez ensuite toutes les tailles de police des éléments enfants de vos documents en em'ou' %.

Ajoutez ensuite quelque chose comme ceci à votre code pour définir la taille de police de base.

document.body.setScaledFont(0.35);
window.onresize = function() {
    document.body.setScaledFont(0.35);
}

http://jsfiddle.net/0tpvccjt/


1
Jusqu'à présent, c'est la meilleure solution
Court

Mauvaises pratiques et très inefficaces
Jack Giffin

@tntrox Aussi inefficace qu'aujourd'hui, il était beaucoup plus inefficace il y a 4 ans. Je rejette cette réponse au lieu de bien meilleures alternatives. Oui, pour le support IE, il faudrait Javascript. Mais, on n'a pas besoin de Javascript c'est terrible.
Jack Giffin

3
Je suppose que mon ignorance se manifeste ici. Mais POURQUOI ce qui précède est-il terrible?

Je ne pense pas que ce soit terrible. Je recommanderais quelques modifications mineures de mise en forme pour le rendre plus lisible. Je mettrais au moins chaque var sur une ligne distincte. Il n'est peut-être pas nécessaire de le faire return thisà la fin de la fonction. Pour les performances, vous souhaiterez peut-être également anti-redimensionner afin qu'il ne soit pas redessiné lorsque vous faites glisser. C'est un code assez simple, donc quelqu'un pourrait baser sa solution améliorée avec peu d'effort.
Mnebuerquo

19

Il existe un moyen de le faire sans JavaScript!

Vous pouvez utiliser une image SVG en ligne. Vous pouvez utiliser CSS sur un SVG s'il est en ligne. Vous devez vous rappeler que l'utilisation de cette méthode signifie que votre image SVG répondra à sa taille de conteneur.

Essayez d'utiliser la solution suivante ...

HTML

<div>
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 360.96 358.98" >
      <text>SAVE $500</text>
  </svg>
</div>

CSS

div {
  width: 50%; /* Set your container width */
  height: 50%; /* Set your container height */

}

svg {
  width: 100%;
  height: auto;

}

text {
  transform: translate(40px, 202px);
  font-size: 62px;
  fill: #000;
}

Exemple: https://jsfiddle.net/k8L4xLLa/32/

Vous voulez quelque chose de plus flashy?

Les images SVG vous permettent également de faire des trucs sympas avec des formes et des déchets. Découvrez ce grand cas d'utilisation de texte évolutif ...

https://jsfiddle.net/k8L4xLLa/14/


4
Cette solution n'est pas différente de celle acceptée avec vwdimensionnement. si vous changez le texte, tout sort des limites.
N69S

14

Cela peut ne pas être super pratique, mais si vous voulez qu'une police soit une fonction directe du parent, sans avoir de JavaScript qui écoute / boucle (intervalle) pour lire la taille de la div / page, il existe un moyen de le faire . Iframes.

Tout élément de l'iframe considérera la taille de l'iframe comme la taille de la fenêtre. Donc, l'astuce consiste à créer un iframe dont la largeur est la largeur maximale que vous souhaitez que votre texte soit, et dont la hauteur est égale à la hauteur maximale * le rapport hauteur / largeur du texte particulier.

Mis à part la limitation selon laquelle les unités de fenêtre ne peuvent pas également venir avec les unités parentales latérales pour le texte (comme dans, avoir la taille% se comporte comme tout le monde), les unités de fenêtre fournissent un outil très puissant: pouvoir obtenir la dimension minimum / maximum . Vous ne pouvez faire cela nulle part ailleurs - vous ne pouvez pas dire ... faire de la hauteur de ce div la largeur du parent * quelque chose.

Cela étant dit, l'astuce consiste à utiliser vmin et à définir la taille de l'iframe de sorte que [fraction] * hauteur totale soit une bonne taille de police lorsque la hauteur est la dimension limite, et [fraction] * largeur totale lorsque la largeur est la dimension limite. C'est pourquoi la hauteur doit être un produit de la largeur et du rapport hauteur / largeur.

Pour mon exemple particulier, vous avez

.main iframe{
  position: absolute;
  top: 50%;
  left: 50%;
  width: 100%;
  height: calc(3.5 * 100%);
  background: rgba(0, 0, 0, 0);
  border-style: none;
  transform: translate3d(-50%, -50%, 0);
}

Le petit inconvénient de cette méthode est que vous devez définir manuellement le CSS de l'iframe. Si vous joignez l'intégralité du fichier CSS, cela prendrait beaucoup de bande passante pour de nombreuses zones de texte. Donc, ce que je fais, c'est attacher la règle que je veux directement à partir de mon CSS.

var rule = document.styleSheets[1].rules[4];
var iDoc = document.querySelector('iframe').contentDocument;
iDoc.styleSheets[0].insertRule(rule.cssText);

Vous pouvez écrire une petite fonction qui obtient la règle CSS / toutes les règles CSS qui affectent la zone de texte.

Je ne peux pas penser à une autre façon de le faire sans avoir du vélo / écouter du JavaScript. La vraie solution serait que les navigateurs fournissent un moyen de mettre à l'échelle le texte en fonction du conteneur parent et fournissent également la même fonctionnalité de type vmin / vmax.

JSFiddle: https://jsfiddle.net/0jr7rrgm/3/ (cliquez une fois pour verrouiller le carré rouge sur la souris, puis cliquez à nouveau pour libérer)

La plupart du JavaScript dans le violon n'est que ma fonction de clic-glisser personnalisée.


@quemeful Ce n'est pas le cas lorsque nous introduisons l' attribut "nouveau" et "brillant" (roulement de tambour s'il vous plaît ...) srcdoc: jsfiddle.net/wauzgob6/3
Jack Giffin

9

En utilisant vw, em& co. fonctionne à coup sûr, mais OMI, il a toujours besoin d'une touche humaine pour un réglage fin.

Voici un script que je viens d' écrire basé sur @ tnt-rox » réponse qui tente de automatisent toucher de l' homme que:

$('#controller').click(function(){
    $('h2').each(function(){
        var
            $el = $(this),
            max = $el.get(0),
            el = null
        ;
        max =
            max
            ? max.offsetWidth
            : 320
        ;
        $el.css({
            'font-size': '1em',
            'display': 'inline',
        });
        el = $el.get(0);

        el.get_float = function(){
            var
                fs = 0
            ;
            if (this.style && this.style.fontSize) {
                fs = parseFloat(this.style.fontSize.replace(/([\d\.]+)em/g, '$1'));
            }
            return fs;
        };

        el.bigger = function(){
            this.style.fontSize = (this.get_float() + 0.1) + 'em';
        };

        while (el.offsetWidth < max) {
            el.bigger();
        }

        // Finishing touch.
        $el.css({
            'font-size': ((el.get_float() -0.1) +'em'),
            'line-height': 'normal',
            'display': '',
        });
    });  // end of (each)
});    // end of (font scaling test)
div {
  width: 50%;
  background-color: tomato;
  font-family: 'Arial';
}

h2 {
  white-space: nowrap;
}

h2:nth-child(2) {
  font-style: italic;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<input type="button" id="controller" value="Apply" />
<div>
  <h2>Lorem ipsum dolor</h2>
  <h2>Test String</h2>
  <h2>Sweet Concatenation</h2>
  <h2>Font Scaling</h2>
</div>

Il réduit essentiellement la taille de la police à 1em, puis commence à incrémenter de 0,1 jusqu'à ce qu'il atteigne la largeur maximale.

JSFiddle


1
+1 juste pour quelqu'un qui reconnaît qu'il emsfaut une touche humaine et un rythme vertical n'est pas une sorte de sorcellerie.
serraosays

7

100% est relatif à la taille de police de base, qui, si vous ne l'avez pas définie, serait la valeur par défaut de l'agent utilisateur du navigateur.

Pour obtenir l'effet que vous recherchez, j'utiliserais un morceau de code JavaScript pour ajuster la taille de la police de base par rapport aux dimensions de la fenêtre.


7

À l'intérieur de votre CSS, essayez d'ajouter ceci en bas en changeant la largeur de 320 pixels à l'endroit où votre conception commence à se casser:

    @media only screen and (max-width: 320px) {

        body { font-size: 1em; }

    }

Donnez ensuite la taille de police en "px" ou "em" comme vous le souhaitez.


7

Ma propre solution, basée sur jQuery, fonctionne en augmentant progressivement la taille de la police jusqu'à ce que le conteneur augmente considérablement en hauteur (ce qui signifie qu'il a un saut de ligne).

C'est assez simple, mais fonctionne assez bien et il est très facile à utiliser. Vous ne devez pas savoir quoi que ce soit au sujet de la police utilisée, tout est pris en charge par le navigateur.

Vous pouvez jouer avec sur http://jsfiddle.net/tubededentifrice/u5y15d0L/2/

La magie opère ici:

var setMaxTextSize=function(jElement) {
    // Get and set the font size into data for reuse upon resize
    var fontSize=parseInt(jElement.data(quickFitFontSizeData)) || parseInt(jElement.css("font-size"));
    jElement.data(quickFitFontSizeData, fontSize);

    // Gradually increase font size until the element gets a big increase in height (i.e. line break)
    var i = 0;
    var previousHeight;
    do
    {
        previousHeight=jElement.height();
        jElement.css("font-size", "" + (++fontSize) + "px");
    }
    while(i++ < 300 && jElement.height()-previousHeight < fontSize/2)

    // Finally, go back before the increase in height and set the element as resized by adding quickFitSetClass
    fontSize -= 1;
    jElement.addClass(quickFitSetClass).css("font-size", "" + fontSize + "px");

    return fontSize;
};

1
Étant donné que ce script s'exécutera à chaque événement de redimensionnement et / ou changement d'orientation, je ne recommande pas d'utiliser cela. Au lieu d'utiliser une solution basée sur javascript, recherchez une solution basée sur css comme indiqué ci-dessus.
Pilatus

1
Les changements de redimensionnement et d'orientation sont des événements "rares", il n'y a aucun problème de performances ici. Si vous préférez, ne vous liez pas aux événements (s'ils ne redimensionnent pas les conteneurs par exemple, pour les sites Web non réactifs). Les solutions CSS ne fonctionnent pas dans tous les cas sans avoir à penser à quoi que ce soit (comme la largeur de la police), comme le fait cette solution.
Vincent

J'ai enveloppé votre réponse comme une fonction jQuery. Il reçoit la hauteur maximale autorisée, les tailles de police min et max. Voir jsfiddle.net/oriadam/qzsy760k
oriadam

6

Ce composant Web modifie la taille de la police afin que la largeur du texte interne corresponde à la largeur du conteneur. Vérifiez la démo .

Vous pouvez l'utiliser comme ceci:

<full-width-text>Lorem Ipsum</full-width-text>


6

J'ai préparé une fonction d'échelle simple en utilisant la transformation CSS au lieu de la taille de la police. Vous pouvez l'utiliser à l'intérieur de n'importe quel conteneur, vous n'avez pas à définir de requêtes multimédias, etc. :)

Article de blog: en- tête évolutif CSS et JS pleine largeur

Le code:

function scaleHeader() {
  var scalable = document.querySelectorAll('.scale--js');
  var margin = 10;
  for (var i = 0; i < scalable.length; i++) {
    var scalableContainer = scalable[i].parentNode;
    scalable[i].style.transform = 'scale(1)';
    var scalableContainerWidth = scalableContainer.offsetWidth - margin;
    var scalableWidth = scalable[i].offsetWidth;
    scalable[i].style.transform = 'scale(' + scalableContainerWidth / scalableWidth + ')';
    scalableContainer.style.height = scalable[i].getBoundingClientRect().height + 'px';
  }
}

Démo de travail: https://codepen.io/maciejkorsan/pen/BWLryj


Je pense que OP recherche une solution CSS.
m02ph3u5

5

Utiliser des variables CSS

Personne n'a encore mentionné de variables CSS, et cette approche a fonctionné le mieux pour moi, donc:

Disons que votre page contient une colonne qui représente 100% de la largeur de l'écran d'un utilisateur mobile, mais qui a une max-widthrésolution de 800 pixels, donc sur le bureau, il y a de l'espace de chaque côté de la colonne. Mettez ceci en haut de votre page:

<script> document.documentElement.style.setProperty('--column-width', Math.min(window.innerWidth, 800)+'px'); </script>

Et maintenant, vous pouvez utiliser cette variable (au lieu de l' vwunité intégrée ) pour définir la taille de votre police. Par exemple

p {
  font-size: calc( var(--column-width) / 100 );
}

Ce n'est pas une approche CSS pure , mais c'est assez proche.


5

Essayez http://simplefocus.com/flowtype/ . C'est ce que j'utilise pour mes sites, et cela a parfaitement fonctionné.


Les liens sont volatils. Veuillez expliquer la solution directement dans votre réponse. De plus, je ne veux pas cliquer sur un lien aléatoire avec n'importe quel contenu.
lilalinux

5

Mon problème était similaire, mais lié à la mise à l'échelle du texte dans un en-tête. J'ai essayé Fit Font, mais je devais basculer le compresseur pour obtenir des résultats, car il résolvait un problème légèrement différent, tout comme Text Flow.

J'ai donc écrit mon propre petit plugin qui a réduit la taille de la police pour s'adapter au conteneur, en supposant que vous l'avez fait overflow: hiddenet white-space: nowrapque même si la réduction de la police au minimum ne permet pas d'afficher l'intégralité de l'en-tête, elle coupe simplement ce qu'elle peut afficher.

(function($) {

  // Reduces the size of text in the element to fit the parent.
  $.fn.reduceTextSize = function(options) {
    options = $.extend({
      minFontSize: 10
    }, options);

    function checkWidth(em) {
      var $em = $(em);
      var oldPosition = $em.css('position');
      $em.css('position', 'absolute');
      var width = $em.width();
      $em.css('position', oldPosition);
      return width;
    }

    return this.each(function(){
      var $this = $(this);
      var $parent = $this.parent();
      var prevFontSize;
      while (checkWidth($this) > $parent.width()) {
        var currentFontSize = parseInt($this.css('font-size').replace('px', ''));
        // Stop looping if min font size reached, or font size did not change last iteration.
        if (isNaN(currentFontSize) || currentFontSize <= options.minFontSize ||
            prevFontSize && prevFontSize == currentFontSize) {
          break;
        }
        prevFontSize = currentFontSize;
        $this.css('font-size', (currentFontSize - 1) + 'px');
      }
    });
  };
})(jQuery);

5

Artistiquement, si vous avez besoin de tenir deux ou plusieurs lignes de texte dans la même largeur, quel que soit leur nombre de caractères, vous avez de belles options.

Il est préférable de trouver une solution dynamique, donc quel que soit le texte entré, nous nous retrouvons avec un bel affichage.

Voyons comment nous pouvons nous approcher.

var els     = document.querySelectorAll(".divtext"),
refWidth    = els[0].clientWidth,
refFontSize = parseFloat(window.getComputedStyle(els[0],null)
                               .getPropertyValue("font-size"));

els.forEach((el,i) => el.style.fontSize = refFontSize * refWidth / els[i].clientWidth + "px")
#container {
  display: inline-block;
  background-color: black;
  padding: 0.6vw 1.2vw;
}
.divtext {
  display: table;
  color: white;
  font-family: impact;
  font-size: 4.5vw;
}
<div id="container">
  <div class="divtext">THIS IS JUST AN</div>
  <div class="divtext">EXAMPLE</div>
  <div class="divtext">TO SHOW YOU WHAT</div>
  <div class="divtext">YOU WANT</div>
</div>

Tout ce que nous faisons est d'obtenir la largeur ( els[0].clientWidth) et la taille de police ( parseFloat(window.getComputedStyle(els[0],null).getPropertyValue("font-size"))) de la première ligne comme référence, puis de calculer la taille de police des lignes suivantes en conséquence.


4

Essayez d'utiliser le plugin fitText , car la taille des fenêtres n'est pas la solution à ce problème.

Ajoutez simplement la bibliothèque:

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>

Et changez la taille de la police pour corriger en définissant le coefficient de texte:

$("#text_div").fitText(0.8);

Vous pouvez définir des valeurs maximales et minimales de texte:

$("#text_div").fitText(0.8, { minFontSize: '12px', maxFontSize: '36px' });

Ceci n'est utile que pour le texte grand écran et n'est pas recommandé pour les paragraphes.
Shiv

3

Regardez mon code. Il fait le font size smallerà fittout ce qu'il y.

Mais je pense que cela ne mène pas à une bonne expérience utilisateur

var containerWidth = $("#ui-id-2").width();
var items = $(".quickSearchAutocomplete .ui-menu-item");
var fontSize = 16;

items.each(function(){
    // Displaying a value depends sometimes on your case. You may make it block or inline-table instead of inline-block or whatever value that make the div take overflow width.
    $(this).css({"whiteSpace": "nowrap", "display": "inline-block"});
    while ($(this).width() > containerWidth){
         console.log("$(this).width()" + $(this).width() + "containerWidth" + containerWidth)
         $(this).css("font-size", fontSize -= 0.5);
    }
});

Résultat


2

En tant que solution de rechange JavaScript (ou votre seule solution), vous pouvez utiliser mon plug-in jQuery Scalem , qui vous permet de mettre à l'échelle par rapport à l'élément parent (conteneur) en passant l' referenceoption.


2

Au cas où cela serait utile à quiconque, la plupart des solutions de ce fil de discussion consistaient à enrouler le texte sur plusieurs lignes, le formulaire e.

Mais j'ai trouvé ça, et ça a marché:

https://github.com/chunksnbits/jquery-quickfit

Exemple d'utilisation:

$('.someText').quickfit({max:50,tolerance:.4})


2

Ayez toujours votre élément avec cet attribut:

JavaScript: element.style.fontSize = "100%";

ou

CSS: style = "font-size: 100%;"

Lorsque vous passez en plein écran, vous devriez déjà avoir une variable d' échelle calculée (échelle> 1 ou échelle = 1). Ensuite, en plein écran:

document.body.style.fontSize = (scale * 100) + "%";

Cela fonctionne bien avec peu de code.


2

Pour le texte dynamique, ce plugin est assez utile:

http://freqdec.github.io/slabText/

Ajoutez simplement CSS:

.slabtexted .slabtext
{
    display: -moz-inline-box;
    display: inline-block;
    white-space: nowrap;
}
.slabtextinactive .slabtext
{
    display: inline;
    white-space: normal;
    font-size: 1em !important;
    letter-spacing: inherit !important;
    word-spacing: inherit !important;
    *letter-spacing: normal !important;
    *word-spacing: normal !important;
}
.slabtextdone .slabtext
{
    display: block;
}

Et le script:

$('#mydiv').slabText();

2

Cela a fonctionné pour moi:

J'essaie d'approximer la taille de la police en fonction d'une largeur / hauteur obtenue à partir du paramètre `font-size: 10px`. Fondamentalement, l'idée est "si j'ai 20 pixels de largeur et 11 pixels de hauteur avec` font-size: 10px`, alors quelle serait la taille de police maximale pour calculer un conteneur de 50 pixels de largeur et 30 pixels de hauteur? "

La réponse est un système à double proportion:

{20: 10 = 50: X, 11: 10 = 30: Y} = {X = (10 * 50) / 20, Y = (10 * 30) / 11}

Maintenant, X est une taille de police qui correspondra à la largeur, et Y est une taille de police qui correspondra à la hauteur; prendre la plus petite valeur

function getMaxFontSizeApprox(el){
    var fontSize = 10;
    var p = el.parentNode;

    var parent_h = p.offsetHeight ? p.offsetHeight : p.style.pixelHeight;
    if(!parent_h)
        parent_h = 0;

    var parent_w = p.offsetHeight ? p.offsetWidth : p.style.pixelWidth;
    if(!parent_w)
        parent_w = 0;

    el.style.fontSize = fontSize + "px";

    var el_h = el.offsetHeight ? el.offsetHeight : el.style.pixelHeight;
    if(!el_h)
        el_h = 0;

    var el_w = el.offsetHeight ? el.offsetWidth : el.style.pixelWidth;
    if(!el_w)
        el_w = 0;

    // 0.5 is the error on the measure that JavaScript does
    // if the real measure had been 12.49 px => JavaScript would have said 12px
    // so we think about the worst case when could have, we add 0.5 to 
    // compensate the round error
    var fs1 = (fontSize*(parent_w + 0.5))/(el_w + 0.5);
    var fs2 = (fontSize*(parent_h) + 0.5)/(el_h + 0.5);

    fontSize = Math.floor(Math.min(fs1,fs2));
    el.style.fontSize = fontSize + "px";
    return fontSize;
}

NB: l'argument de la fonction doit être un élément span ou un élément plus petit que son parent, sinon si les enfants et le parent ont tous les deux la même fonction largeur / hauteur échouera.



1

Afin de faire correspondre la taille de la police à son conteneur, plutôt qu'à la fenêtre, consultez la resizeFont()fonction que j'ai partagée dans cette question (une combinaison d'autres réponses, dont la plupart sont déjà liées ici). Il est déclenché à l'aide de window.addEventListener('resize', resizeFont);.

Vanilla JavaScript: redimensionne la police en fonction du conteneur

JavaScript:

function resizeFont() {
  var elements  = document.getElementsByClassName('resize');
  console.log(elements);
  if (elements.length < 0) {
    return;
  }
  _len = elements.length;
  for (_i = 0; _i < _len; _i++) {
    var el = elements[_i];
    el.style.fontSize = "100%";
    for (var size = 100; el.scrollHeight > el.clientHeight; size -= 10) {
      el.style.fontSize = size + '%';
    }
  }
}

Vous pouvez peut-être utiliser vw / vh comme solution de rechange, de sorte que vous attribuez dynamiquement emourem unités utilisant JavaScript, en vous assurant que les polices s'adaptent à la fenêtre si JavaScript est désactivé.

Appliquer le .resize classe à tous les éléments contenant du texte que vous souhaitez mettre à l'échelle.

Déclenchez la fonction avant d'ajouter l'écouteur d'événements de redimensionnement de fenêtre. Ensuite, tout texte qui ne correspond pas à son conteneur sera réduit lors du chargement de la page, ainsi que lors du redimensionnement.

REMARQUE: La valeur par défaut font-sizedoit être réglé sur em, remou %pour obtenir des résultats appropriés.


1

HTML

<div style="height:100px; width:200px;">
  <div id='qwe'>
    test
  </div>
</div>

Code JavaScript pour maximiser la taille de la police:

var fontSize, maxHeight, maxWidth, textElement, parentElement;
textElement = document.getElementById('qwe');
parentElement = textElement.parentElement;    
maxHeight = parentElement.clientHeight;
maxWidth = parentElement.clientWidth;
fontSize = maxHeight;
var minFS = 3, maxFS = fontSize;
while (fontSize != minFS) {
  textElement.style.fontSize = `${fontSize}px`;
  if (textElement.offsetHeight < maxHeight && textElement.offsetWidth <= maxWidth) {
    minFS = fontSize;
  } else{
    maxFS = fontSize;
  }
  fontSize = Math.floor((minFS + maxFS)/2);
}
textElement.style.fontSize = `${minFS}px`;
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.