web-dev-qa-db-fra.com

Taille automatique du texte dynamique pour remplir le conteneur de taille fixe

Je dois afficher le texte saisi par l'utilisateur dans un div de taille fixe. Ce que je veux, c'est que la taille de la police soit automatiquement ajustée pour que le texte remplisse le plus possible la case.

So - Si le div est 400px x 300px. Si quelqu'un entre sur ABC, c'est une police vraiment grosse. S'ils entrent dans un paragraphe, alors ce sera une police minuscule.

Je souhaiterais probablement commencer avec une taille de police maximale, peut-être 32 pixels, et, bien que le texte soit trop volumineux pour s'adapter au conteneur, réduisez la taille de la police jusqu'à ce qu'elle s'adapte.

297
GeekyMonkey

Merci Attaque . Je voulais utiliser jQuery. 

Vous m'avez orienté dans la bonne direction, et voici ce que j'ai fini avec:

Voici un lien vers le plugin: https://plugins.jquery.com/textfill/
Et un lien vers la source: http://jquery-textfill.github.io/

;(function($) {
    $.fn.textfill = function(options) {
        var fontSize = options.maxFontPixels;
        var ourText = $('span:visible:first', this);
        var maxHeight = $(this).height();
        var maxWidth = $(this).width();
        var textHeight;
        var textWidth;
        do {
            ourText.css('font-size', fontSize);
            textHeight = ourText.height();
            textWidth = ourText.width();
            fontSize = fontSize - 1;
        } while ((textHeight > maxHeight || textWidth > maxWidth) && fontSize > 3);
        return this;
    }
})(jQuery);

$(document).ready(function() {
    $('.jtextfill').textfill({ maxFontPixels: 36 });
});

et mon html est comme ça

<div class='jtextfill' style='width:100px;height:50px;'>
    <span>My Text Here</span>
</div>

Ceci est mon premier plugin jquery, donc ce n’est probablement pas aussi bon qu’il devrait être. Les pointeurs sont certainement les bienvenus.

159
GeekyMonkey

Je n’ai trouvé aucune des solutions précédentes suffisamment adéquate en raison de mauvaises performances. J’ai donc créé ma propre solution qui utilise des calculs simples au lieu de la mise en boucle. Devrait fonctionner correctement dans tous les navigateurs.

Selon ce test de performance il est beaucoup plus rapide que les autres solutions trouvées ici.

(function($) {
    $.fn.textfill = function(maxFontSize) {
        maxFontSize = parseInt(maxFontSize, 10);
        return this.each(function(){
            var ourText = $("span", this),
                parent = ourText.parent(),
                maxHeight = parent.height(),
                maxWidth = parent.width(),
                fontSize = parseInt(ourText.css("fontSize"), 10),
                multiplier = maxWidth/ourText.width(),
                newSize = (fontSize*(multiplier-0.1));
            ourText.css(
                "fontSize", 
                (maxFontSize > 0 && newSize > maxFontSize) ? 
                    maxFontSize : 
                    newSize
            );
        });
    };
})(jQuery);

Si vous voulez contribuer, j'ai ajouté ceci à Gist .

52
mekwall

Autant que j'aime les upvotes occasionnels que je reçois pour cette réponse (merci!), Ce n'est vraiment pas la meilleure approche de ce problème. S'il vous plaît vérifier quelques-unes des autres réponses merveilleuses ici, en particulier ceux qui ont trouvé des solutions sans boucle.


Pourtant, par souci de référence, voici mon réponse originale :

<html>
<head>
<style type="text/css">
    #dynamicDiv
    {
    background: #CCCCCC;
    width: 300px;
    height: 100px;
    font-size: 64px;
    overflow: hidden;
    }
</style>

<script type="text/javascript">
    function shrink()
    {
        var textSpan = document.getElementById("dynamicSpan");
        var textDiv = document.getElementById("dynamicDiv");

        textSpan.style.fontSize = 64;

        while(textSpan.offsetHeight > textDiv.offsetHeight)
        {
            textSpan.style.fontSize = parseInt(textSpan.style.fontSize) - 1;
        }
    }
</script>

</head>
<body onload="shrink()">
    <div id="dynamicDiv"><span id="dynamicSpan">DYNAMIC FONT</span></div>
</body>
</html>

Et voici une version avec classes :

<html>
<head>
<style type="text/css">
.dynamicDiv
{
    background: #CCCCCC;
    width: 300px;
    height: 100px;
    font-size: 64px;
    overflow: hidden;
}
</style>

<script type="text/javascript">
    function shrink()
    {
        var textDivs = document.getElementsByClassName("dynamicDiv");
        var textDivsLength = textDivs.length;

        // Loop through all of the dynamic divs on the page
        for(var i=0; i<textDivsLength; i++) {

            var textDiv = textDivs[i];

            // Loop through all of the dynamic spans within the div
            var textSpan = textDiv.getElementsByClassName("dynamicSpan")[0];

            // Use the same looping logic as before
            textSpan.style.fontSize = 64;

            while(textSpan.offsetHeight > textDiv.offsetHeight)
            {
                textSpan.style.fontSize = parseInt(textSpan.style.fontSize) - 1;
            }

        }

    }
</script>

</head>
<body onload="shrink()">
    <div class="dynamicDiv"><span class="dynamicSpan">DYNAMIC FONT</span></div>
    <div class="dynamicDiv"><span class="dynamicSpan">ANOTHER DYNAMIC FONT</span></div>
    <div class="dynamicDiv"><span class="dynamicSpan">AND YET ANOTHER DYNAMIC FONT</span></div>
</body>
</html>
33
attack

La plupart des autres réponses utilisent une boucle pour réduire la taille de la police jusqu'à ce qu'elle tienne sur la div. Cette opération est TRES lente, car la page doit restituer l'élément à chaque changement de taille de la police. J'ai finalement dû écrire mon propre algorithme pour le rendre performant de manière à pouvoir mettre à jour périodiquement son contenu sans geler le navigateur de l'utilisateur. J'ai ajouté d'autres fonctionnalités (rotation de texte, ajout de rembourrage) et je l'ai empaqueté comme un plugin jQuery. Vous pouvez l'obtenir à l'adresse suivante:

https://github.com/DanielHoffmann/jquery-bigtext

simplement appeler

$("#text").bigText();

et il ira bien sur votre conteneur.

Voir en action ici:

http://danielhoffmann.github.io/jquery-bigtext/

Pour l'instant, il a certaines limites, la div doit avoir une hauteur et une largeur fixes et ne prend pas en charge le texte enveloppant sur plusieurs lignes.

Je vais travailler sur l'obtention d'une option permettant de définir la taille de police maximale.

Edit: J'ai trouvé quelques problèmes supplémentaires avec le plugin, il ne gère pas d'autres modèles de boîte que le modèle standard et la div ne peut pas avoir de marges ou de bordures. J'y travaillerai.

Edit2: J'ai maintenant corrigé ces problèmes et limitations et ajouté plus d'options. Vous pouvez définir une taille de police maximale et vous pouvez également choisir de limiter la taille de la police à l'aide de la largeur, de la hauteur ou des deux. Je vais travailler à accepter les valeurs max-width et max-height dans l'élément wrapper.

Edit3: J'ai mis à jour le plugin vers la version 1.2.0. Nettoyage important du code et des nouvelles options (verticalAlign, horizontalAlign, textAlign) et prise en charge des éléments internes à l'intérieur de la balise span (comme les sauts de ligne ou les icônes font-awesome).

31
Hoffmann

Ceci est basé sur ce que GeekyMonkey a posté ci-dessus, avec quelques modifications.

; (function($) {
/**
* Resize inner element to fit the outer element
* @author Some modifications by Sandstrom
* @author Code based on earlier works by Russ Painter ([email protected])
* @version 0.2
*/
$.fn.textfill = function(options) {

    options = jQuery.extend({
        maxFontSize: null,
        minFontSize: 8,
        step: 1
    }, options);

    return this.each(function() {

        var innerElements = $(this).children(':visible'),
            fontSize = options.maxFontSize || innerElements.css("font-size"), // use current font-size by default
            maxHeight = $(this).height(),
            maxWidth = $(this).width(),
            innerHeight,
            innerWidth;

        do {

            innerElements.css('font-size', fontSize);

            // use the combined height of all children, eg. multiple <p> elements.
            innerHeight = $.map(innerElements, function(e) {
                return $(e).outerHeight();
            }).reduce(function(p, c) {
                return p + c;
            }, 0);

            innerWidth = innerElements.outerWidth(); // assumes that all inner elements have the same width
            fontSize = fontSize - options.step;

        } while ((innerHeight > maxHeight || innerWidth > maxWidth) && fontSize > options.minFontSize);

    });

};

})(jQuery);
9
sandstrom

Voici une méthode de bouclage améliorée qui utilise la recherche binaire pour trouver la plus grande taille possible qui tienne dans le parent en un minimum d'étapes (c'est plus rapide et plus précis que le pas d'une taille de police fixe). Le code est également optimisé de plusieurs manières pour améliorer les performances.

Par défaut, 10 étapes de recherche binaire sont effectuées, ce qui correspond à 0,1% de la taille optimale. Vous pouvez plutôt définir numIter sur une valeur N pour qu’elle se situe dans les limites de 1/2 ^ N de la taille optimale.

Appelez-le avec un sélecteur CSS, par exemple: fitToParent('.title-span');

/**
 * Fit all elements matching a given CSS selector to their parent elements'
 * width and height, by adjusting the font-size attribute to be as large as
 * possible. Uses binary search.
 */
var fitToParent = function(selector) {
    var numIter = 10;  // Number of binary search iterations
    var regexp = /\d+(\.\d+)?/;
    var fontSize = function(elem) {
        var match = elem.css('font-size').match(regexp);
        var size = match == null ? 16 : parseFloat(match[0]);
        return isNaN(size) ? 16 : size;
    }
    $(selector).each(function() {
        var elem = $(this);
        var parentWidth = elem.parent().width();
        var parentHeight = elem.parent().height();
        if (elem.width() > parentWidth || elem.height() > parentHeight) {
            var maxSize = fontSize(elem), minSize = 0.1;
            for (var i = 0; i < numIter; i++) {
                var currSize = (minSize + maxSize) / 2;
                elem.css('font-size', currSize);
                if (elem.width() > parentWidth || elem.height() > parentHeight) {
                    maxSize = currSize;
                } else {
                    minSize = currSize;
                }
            }
            elem.css('font-size', minSize);
        }
    });
};
6
Luke Hutchison

J'ai créé une directive pour AngularJS - inspirée à l'extrême par la réponse de GeekyMonkey mais sans la dépendance jQuery.

Démo:http://plnkr.co/edit/8tPCZIjvO3VSApSeTtYr?p=preview

Balisage

<div class="fittext" max-font-size="50" text="Your text goes here..."></div>

Directive

app.directive('fittext', function() {

  return {
    scope: {
      minFontSize: '@',
      maxFontSize: '@',
      text: '='
    },
    restrict: 'C',
    transclude: true,
    template: '<div ng-transclude class="textContainer" ng-bind="text"></div>',
    controller: function($scope, $element, $attrs) {
      var fontSize = $scope.maxFontSize || 50;
      var minFontSize = $scope.minFontSize || 8;

      // text container
      var textContainer = $element[0].querySelector('.textContainer');

      angular.element(textContainer).css('Word-wrap', 'break-Word');

      // max dimensions for text container
      var maxHeight = $element[0].offsetHeight;
      var maxWidth = $element[0].offsetWidth;

      var textContainerHeight;
      var textContainerWidth;      

      var resizeText = function(){
        do {
          // set new font size and determine resulting dimensions
          textContainer.style.fontSize = fontSize + 'px';
          textContainerHeight = textContainer.offsetHeight;
          textContainerWidth = textContainer.offsetWidth;

          // shrink font size
          var ratioHeight = Math.floor(textContainerHeight / maxHeight);
          var ratioWidth = Math.floor(textContainerWidth / maxWidth);
          var shrinkFactor = ratioHeight > ratioWidth ? ratioHeight : ratioWidth;
          fontSize -= shrinkFactor;

        } while ((textContainerHeight > maxHeight || textContainerWidth > maxWidth) && fontSize > minFontSize);        
      };

      // watch for changes to text
      $scope.$watch('text', function(newText, oldText){
        if(newText === undefined) return;

        // text was deleted
        if(oldText !== undefined && newText.length < oldText.length){
          fontSize = $scope.maxFontSize;
        }
        resizeText();
      });
    }
  };
});
6
sqren

J'ai créé le script ci-dessus à partir de Marcus Ekwall: https://Gist.github.com/3945316 et l'a modifié selon mes préférences, il se déclenche maintenant lorsque la fenêtre est redimensionnée, de sorte que l'enfant s'adapte toujours à son conteneur. J'ai collé le script ci-dessous pour référence.

(function($) {
    $.fn.textfill = function(maxFontSize) {
        maxFontSize = parseInt(maxFontSize, 10);
        return this.each(function(){
            var ourText = $("span", this);
            function resizefont(){
                var parent = ourText.parent(),
                maxHeight = parent.height(),
                maxWidth = parent.width(),
                fontSize = parseInt(ourText.css("fontSize"), 10),
                multiplier = maxWidth/ourText.width(),
                newSize = (fontSize*(multiplier));
                ourText.css("fontSize", maxFontSize > 0 && newSize > maxFontSize ? maxFontSize : newSize );
            }
            $(window).resize(function(){
                resizefont();
            });
            resizefont();
        });
    };
})(jQuery);
5
nimrod

Voici ma modification de la réponse du PO.

En bref, beaucoup de personnes qui ont essayé d'optimiser cela se sont plaintes de l'utilisation d'une boucle. Oui, alors que les boucles peuvent être lentes, les autres approches peuvent être inexactes.

Par conséquent, mon approche utilise recherche binaire pour trouver la meilleure taille de police:

$.fn.textfill = function()
{
    var self = $(this);
    var parent = self.parent();

    var attr = self.attr('max-font-size');
    var maxFontSize = parseInt(attr, 10);
    var unit = attr.replace(maxFontSize, "");

    var minFontSize = parseInt(self.attr('min-font-size').replace(unit, ""));
    var fontSize = (maxFontSize + minFontSize) / 2;

    var maxHeight = parent.height();
    var maxWidth = parent.width();

    var textHeight;
    var textWidth;

    do
    {
        self.css('font-size', fontSize + unit);

        textHeight = self.height();
        textWidth = self.width();

        if(textHeight > maxHeight || textWidth > maxWidth)
        {
            maxFontSize = fontSize;
            fontSize = Math.floor((fontSize + minFontSize) / 2);
        }
        else if(textHeight < maxHeight || textWidth < maxWidth)
        {
            minFontSize = fontSize;
            fontSize = Math.floor((fontSize + maxFontSize) / 2);
        }
        else
            break;

    }
    while(maxFontSize - minFontSize > 1 && maxFontSize > minFontSize);

    self.css('font-size', fontSize + unit);

    return this;
}

function resizeText()
{
  $(".textfill").textfill();
}

$(document).ready(resizeText);
$(window).resize(resizeText);

Cela permet également à l'élément de spécifier les polices minimum et maximum:

<div class="container">
    <div class="textfill" min-font-size="10px" max-font-size="72px">
        Text that will fill the container, to the best of its abilities, and it will <i>never</i> have overflow.
    </div>
</div>

De plus, cet algorithme est sans unité. Vous pouvez spécifier em, rem, %, etc. et l’utilisera pour le résultat final.

Voici le violon: https://jsfiddle.net/fkhqhnqe/1/

4
Boom

J'ai eu exactement le même problème avec mon site web. J'ai une page qui est affichée sur un projecteur, sur des murs, sur de grands écrans.

Comme je ne connais pas la taille maximale de ma police, j'ai réutilisé le plugin ci-dessus de @GeekMonkey mais en incrémentant la taille de la police

$.fn.textfill = function(options) {
        var defaults = { innerTag: 'span', padding: '10' };
        var Opts = jQuery.extend(defaults, options);

        return this.each(function() {
            var ourText = $(Opts.innerTag + ':visible:first', this);
            var fontSize = parseFloat(ourText.css('font-size'),10);
            var doNotTrepass = $(this).height()-2*Opts.padding ;
            var textHeight;

            do {
                ourText.css('font-size', fontSize);
                textHeight = ourText.height();
                fontSize = fontSize + 2;
            } while (textHeight < doNotTrepass );
        });
    };
2
guillaumepotier

Les solutions itératives proposées peuvent être accélérées de façon spectaculaire sur deux fronts:

1) Multipliez la taille de la police par une constante plutôt que d’ajouter ou de soustraire 1.

2) Tout d’abord, mettez une constante de cours à zéro, par exemple, doublez la taille de chaque boucle. Ensuite, avec une idée approximative du point de départ, faites la même chose avec un ajustement plus fin, disons, multipliez par 1,1. Bien que le perfectionniste puisse vouloir la taille exacte en pixels de la police idéale, la plupart des observateurs ne remarquent pas la différence entre 100 et 110 pixels. Si vous êtes un perfectionniste, recommencez une troisième fois avec un ajustement encore plus fin.

Plutôt que d'écrire une routine ou un plug-in spécifique qui répond à la question exacte, je me fie simplement aux idées de base et j'écris des variantes du code pour traiter toutes sortes de problèmes de mise en page, pas seulement le texte, y compris l'ajustement de divs, de span, d'images. .. par largeur, hauteur, surface, ... dans un conteneur, correspondant à un autre élément ....

Voici un exemple:

  var                           nWindowH_px             = jQuery(window).height();
  var                           nWas                    = 0;
  var                           nTry                    = 5;

  do{
   nWas = nTry;
   nTry *= 2;
   jQuery('#divTitle').css('font-size' ,nTry +'px');
  }while( jQuery('#divTitle').height() < nWindowH_px );

  nTry = nWas;

  do{
   nWas = nTry;
   nTry = Math.floor( nTry * 1.1 );
   jQuery('#divTitle').css('font-size' ,nTry +'px');
  }while( nWas != nTry   &&   jQuery('#divTitle').height() < nWindowH_px );

  jQuery('#divTitle').css('font-size' ,nWas +'px');
1
DaveWalley

Vous pouvez utiliser FitText.js ( github page ) pour résoudre ce problème. Est vraiment petit et efficace par rapport à TextFill. TextFill utilise une boucle while coûteuse et FitText ne le fait pas. 

De plus, FitText est plus flexible (je l’utilise dans un projet avec des exigences très spéciales et fonctionne comme un champion!).

HTML:

<div class="container">
  <h1 id="responsive_headline">Your fancy title</h1>
</div>

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script src="jquery.fittext.js"></script>
<script>
  jQuery("#responsive_headline").fitText();
</script>

Vous pouvez également définir des options pour cela:

<script>
  jQuery("#responsive_headline").fitText(1, { minFontSize: '30px', maxFontSize: '90px'});
</script>

CSS:

#responsive_headline {
   width: 100%;
   display: block;
}

Et si vous en avez besoin, FitText a également une version no-jQuery .

1
eduludi

Voici une version de la réponse acceptée qui peut également prendre un paramètre minFontSize.

(function($) {
    /**
    * Resizes an inner element's font so that the inner element completely fills the outer element.
    * @author Russ Painter [email protected]
    * @author Blake Robertson 
    * @version 0.2 -- Modified it so a min font parameter can be specified.
    *    
    * @param {Object} Options which are maxFontPixels (default=40), innerTag (default='span')
    * @return All outer elements processed
    * @example <div class='mybigdiv filltext'><span>My Text To Resize</span></div>
    */
    $.fn.textfill = function(options) {
        var defaults = {
            maxFontPixels: 40,
            minFontPixels: 10,
            innerTag: 'span'
        };
        var Opts = jQuery.extend(defaults, options);
        return this.each(function() {
            var fontSize = Opts.maxFontPixels;
            var ourText = $(Opts.innerTag + ':visible:first', this);
            var maxHeight = $(this).height();
            var maxWidth = $(this).width();
            var textHeight;
            var textWidth;
            do {
                ourText.css('font-size', fontSize);
                textHeight = ourText.height();
                textWidth = ourText.width();
                fontSize = fontSize - 1;
            } while ((textHeight > maxHeight || textWidth > maxWidth) && fontSize > Opts.minFontPixels);
        });
    };
})(jQuery);
1
blak3r

EDIT: Ce code a été utilisé pour afficher des notes sur une vidéo HTML5. Elle modifie la taille de la police à la volée lorsque la vidéo est redimensionnée (lorsque la fenêtre du navigateur est redimensionnée.) Les notes ont été connectées à la vidéo (comme les notes sur YouTube), raison pour laquelle le code utilise des instances au lieu d'un descripteur DOM directement.

Selon la demande, je vais ajouter du code que j'ai utilisé pour cela. (Zones de texte sur une vidéo HTML5.) Le code a été écrit il y a longtemps et je pense franchement qu'il est assez compliqué. Puisque la question a déjà reçu une réponse et qu'une réponse est déjà acceptée il y a longtemps, je ne me préoccupe pas de la réécrire. Mais si quelqu'un veut simplifier un peu cela, vous êtes le bienvenu!

// Figure out the text size:
var text = val['text'];
var letters = text.length;
var findMultiplier = function(x) { // g(x)
    /* By analysing some functions with regression, the resulting function that
     gives the best font size with respect to the number of letters and the size
     of the note is:
     g(x) = 8.3 - 2.75x^0.15 [1 < x < 255]
     f(x) = g(letters) * (x / 1000)^0.5
     Font size = f(size)
     */
    return 8.3 - 2.75 * Math.pow(x, 0.15);
};

var findFontSize = function(x) { // f(x)
    return findMultiplier(letters) * Math.pow(x / 1000, 0.5);
};

val.setFontSizeListener = function() {
    p.style.fontSize = '1px'; // So the text should not overflow the box when measuring.
    var noteStyle = window.getComputedStyle(table);
    var width = noteStyle.getPropertyValue('width');
    var height = noteStyle.getPropertyValue('height');
    var size = width.substring(0, width.length - 2) * height.substring(0, height.length - 2);
    p.style.fontSize = findFontSize(size) + 'px';
};
window.addEventListener('resize', val.setFontSizeListener);

Vous aurez probablement besoin de modifier ces chiffres de famille de police à famille de polices. Un bon moyen de le faire est de télécharger un visualiseur graphique gratuit appelé GeoGebra. Changer la longueur du texte et la taille de la boîte. Ensuite, vous définissez manuellement la taille. Tracer les résultats manuels dans le système de coordonnées. Ensuite, vous entrez les deux équations que j'ai publiées ici et vous ajustez les nombres jusqu'à ce que "mon" graphique corresponde à vos propres points tracés manuellement.

1
Friend of Kim

je sais que celui-ci est un vieil homme, mais il y a encore des gens qui ont besoin de cette fonctionnalité. Je suis allé avec la solution geekMonkey, mais c'est whack. tout simplement parce que c'est lent. ce qu’il fait, c’est qu’il ajuste la taille de la police au maximum (maxFontPixels) puis vérifie si elle s’intègre dans le conteneur. sinon, il réduit la taille de la police de 1 px et vérifie à nouveau. pourquoi ne pas simplement vérifier la hauteur du conteneur précédent et soumettre cette valeur ?? (Ouais, je sais pourquoi, mais je viens de faire une solution, qui ne fonctionne que sur la hauteur et a également une option min/max)

solution plus rapide:

var index_letters_resize;
(index_letters_resize = function() {
  $(".textfill").each(function() {
    var
      $this = $(this),
      height = Math.min( Math.max( parseInt( $this.height() ), 40 ), 150 );
    $this.find(".size-adjust").css({
      fontSize: height
    });
  });
}).call();

$(window).on('resize', function() {
  index_letters_resize();
);

et ce serait le HTML:

<div class="textfill">
  <span class="size-adjust">adjusted element</span>
  other variable stuff that defines the container size
</div>

à nouveau: cette solution vérifie UNIQUEMENT la hauteur du conteneur. c'est pourquoi cette fonction n'a pas à vérifier si l'élément tient à l'intérieur. mais j'ai aussi implémenté une valeur min/max (40min, 150max), donc pour moi cela fonctionne parfaitement (et fonctionne également avec le redimensionnement de la fenêtre).

0
honk31

J'ai trouvé un moyen d'empêcher l'utilisation de boucles pour réduire le texte. Il ajuste la taille de la police en la multipliant pour le taux entre la largeur du conteneur et la largeur du contenu. Donc, si la largeur du conteneur correspond à 1/3 du contenu, la taille de la police sera réduite de 1/3 et la largeur du conteneur. Pour mettre à l'échelle, j'ai utilisé une boucle while, jusqu'à ce que le contenu soit plus gros que le conteneur.

function fitText(outputSelector){
    // max font size in pixels
    const maxFontSize = 50;
    // get the DOM output element by its selector
    let outputDiv = document.getElementById(outputSelector);
    // get element's width
    let width = outputDiv.clientWidth;
    // get content's width
    let contentWidth = outputDiv.scrollWidth;
    // get fontSize
    let fontSize = parseInt(window.getComputedStyle(outputDiv, null).getPropertyValue('font-size'),10);
    // if content's width is bigger than elements width - overflow
    if (contentWidth > width){
        fontSize = Math.ceil(fontSize * width/contentWidth,10);
        fontSize =  fontSize > maxFontSize  ? fontSize = maxFontSize  : fontSize - 1;
        outputDiv.style.fontSize = fontSize+'px';   
    }else{
        // content is smaller than width... let's resize in 1 px until it fits 
        while (contentWidth === width && fontSize < maxFontSize){
            fontSize = Math.ceil(fontSize) + 1;
            fontSize = fontSize > maxFontSize  ? fontSize = maxFontSize  : fontSize;
            outputDiv.style.fontSize = fontSize+'px';   
            // update widths
            width = outputDiv.clientWidth;
            contentWidth = outputDiv.scrollWidth;
            if (contentWidth > width){
                outputDiv.style.fontSize = fontSize-1+'px'; 
            }
        }
    }
}

Ce code fait partie d'un test que j'ai téléchargé sur Github https://github.com/ricardobrg/fitText/

0
Ricardo BRGWeb

Je voulais juste ajouter ma version pour contenteditables.

$.fn.fitInText = function() {
  this.each(function() {

    let textbox = $(this);
    let textboxNode = this;

    let mutationCallback = function(mutationsList, observer) {
      if (observer) {
        observer.disconnect();
      }
      textbox.css('font-size', 0);
      let desiredHeight = textbox.css('height');
      for (i = 12; i < 50; i++) {
        textbox.css('font-size', i);
        if (textbox.css('height') > desiredHeight) {
          textbox.css('font-size', i - 1);
          break;
        }
      }

      var config = {
        attributes: true,
        childList: true,
        subtree: true,
        characterData: true
      };
      let newobserver = new MutationObserver(mutationCallback);
      newobserver.observe(textboxNode, config);

    };

    mutationCallback();

  });
}

$('#inner').fitInText();
#outer {
  display: table;
  width: 100%;
}

#inner {
  border: 1px solid black;
  height: 170px;
  text-align: center;
  display: table-cell;
  vertical-align: middle;
  Word-break: break-all;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="outer">
  <div id="inner" contenteditable=true>
    TEST
  </div>
</div>

0
wutzebaer

J'ai le même problème et la solution consiste essentiellement à utiliser du javascript pour contrôler la taille de la police. Consultez cet exemple sur codepen: 

https://codepen.io/ThePostModernPlatonic/pen/BZKzVR

Cet exemple est uniquement pour la hauteur, vous devrez peut-être en mettre quelques-uns sur la largeur.

essayez de le redimensionner 

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Documento sem título</title>
<style>
</style>
</head>
<body>
<div style="height:100vh;background-color: tomato;" id="wrap">        
  <h1 class="quote" id="quotee" style="padding-top: 56px">Because too much "light" doesn't <em>illuminate</em> our paths and warm us, it only blinds and burns us.</h1>
</div>
</body>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script>
  var multiplexador = 3;
  initial_div_height = document.getElementById ("wrap").scrollHeight;
  setInterval(function(){ 
    var div = document.getElementById ("wrap");
    var frase = document.getElementById ("quotee");
    var message = "WIDTH div " + div.scrollWidth + "px. "+ frase.scrollWidth+"px. frase \n";
    message += "HEIGHT div " + initial_div_height + "px. "+ frase.scrollHeight+"px. frase \n";           
    if (frase.scrollHeight < initial_div_height - 30){
      multiplexador += 1;
      $("#quotee").css("font-size", multiplexador); 
    }
    console.log(message);          
  }, 10);
</script>
</html>
0
Heitor Giacomini

J'ai aimé

let name = "Making statements based on opinion; back them up with references or personal experience."
let originFontSize = 15;
let maxDisplayCharInLine = 50; 
let fontSize = Math.min(originFontSize, originFontSize / (name.length / maxDisplayCharInLine));
0
Tuan Nguyen