고정 크기 컨테이너를 채울 수있는 동적 크기 자동 텍스트


312

사용자가 입력 한 텍스트를 고정 크기 div로 표시해야합니다. 내가 원하는 것은 텍스트가 가능한 한 상자를 채우도록 글꼴 크기를 자동으로 조정하는 것입니다.

따라서-div가 400px x 300px 인 경우. 누군가가 ABC를 입력하면 정말 큰 글꼴입니다. 문단을 입력하면 작은 글꼴이됩니다.

아마도 최대 글꼴 크기로 시작하고 싶을 것입니다-아마도 32px이며 텍스트가 너무 커서 컨테이너에 맞지 않을 때까지 글꼴 크기를 줄이십시오.


119
아마도 JS가 없어도 HTML5 / CSS3에 추가되어야 할 가장 놀라운 기능 일 것입니다.
존 매그놀리아

동적 텍스트의 길이와 컨테이너 크기를 변경하여 텍스트를 완벽하게 맞출 글꼴 크기를 결정하는 측정을했습니다. 그리고 회귀 분석을 한 후 자동으로 최상의 글꼴 크기를 생성하는 간단한 수학 함수를 고안했습니다.
Kim

2
실제로 최상의 글꼴 크기를 제공하는 그래프는 f (x) = g (letters) * (x / 1000) ^ n으로 주어집니다. 여기서 g (x)는 간단한 함수이고 n은 사용중인 글꼴 (모든 글꼴에 대해 표준 값을 가질 수는 있지만 절대적으로 완벽하게하기 위해 조정하지 않으려는 경우 ...). x는 컨테이너의 정사각형 픽셀 크기입니다.
Kim

1
여전히 관심이 있으시면 답변을 추가 할 수 있습니다. 개인적으로 스크립트가 "올바르게 도착"할 때까지 시도하고 실패하는 대신 처음에 올바른 글꼴 크기를 생성하는 것이 훨씬 더 좋은 방법이라고 생각합니다.
Kim

1
더 좋은 방법은 내 답변을 확인하십시오
Hoffmann

답변:


167

감사 공격 . jQuery를 사용하고 싶었습니다.

당신은 나를 올바른 방향으로 지적했고, 이것이 내가 끝낸 것입니다.

다음은 플러그인에 대한 링크입니다 : https://plugins.jquery.com/textfill/
그리고 소스에 대한 링크 : 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 });
});

내 HTML은 이와 같습니다

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

이것은 첫 번째 jquery 플러그인이므로 아마도 좋지 않을 것입니다. 포인터는 확실히 환영합니다.


8
실제로 단지에 jquery.com에서 그것을 청소하고 플러그인을 사용할 수로 포장 plugins.jquery.com/project/TextFill
GeekyMonkey

3
@GeekyMonkey, 플러그인을 뽑았습니까? 방금이 페이지에 대한 속임수 링크를 따라 가서 살펴 보았지만 jQuery.com이 귀하의 사이트로 연결되는 것으로 나타났습니다 404.
David는 Monica를

참고 : 어떤 이유로 든이 플러그인은 div (위의 예에서 $ ( '. jtextfill'))가 루트 문서의 일부인 경우에만 작동합니다. div가 다른 div 안에 포함되면 .width ()가 0을 반환하는 것처럼 보입니다.
Jayesh

1
해당 루프의 "while"행이 잘못 표시됩니다. "||"주위에 괄호가 있어야합니다. 하위 식. 지금 작성된 방식으로 글꼴 크기 최소값은 너비가 너무 커서 높이가 아닌 경우에만 확인됩니다.
Pointy

4
이 방법은 글꼴의 크기가 변경 될 때마다 요소를 다시 렌더링해야 할 때마다 매우 느립니다. 더 좋은 방법은 내 대답을 확인하십시오.
호프만

52

이전 솔루션 중 성능이 좋지 않아 충분히 적합한 솔루션을 찾지 못했기 때문에 루핑 대신 간단한 수학을 사용하는 솔루션을 만들었습니다. 모든 브라우저에서도 잘 작동합니다.

이 성능 테스트 사례 에 따르면 여기에있는 다른 솔루션보다 훨씬 빠릅니다.

(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);

당신이 기여하고 싶다면 이것을 이것을 Gist에 추가 했습니다 .


1
@Jon, 감사합니다! 내 스크립트가 여러 줄을 수행하지 않는 것이 맞지만 OP는 구체적으로 요구하지 않았으므로 가정이 잘못되었을 수 있습니다. 또한, 이런 종류의 행동은별로 의미가 없습니다. 여러 줄 지원을 추가하는 가장 좋은 방법은 단어의 양을 기준으로 문자열을 분할 한 다음 위의 스크립트로 각 부분을 계산하는 것이 가장 빠를 것입니다.
mekwall

4
@ Jon, 나는 여러 줄짜리 텍스트 채우기로 조금 놀았고이 솔루션으로 끝났습니다 . sandstorm의 방법이 더 정확할 수도 있지만이 방법이 더 빠릅니다.)
mekwall

2
다음은 최소 글꼴 크기 및 최대 버전입니다. gist.github.com/1714284
Jess Telford

1
@ 호프만 흠. 내 솔루션은 .css("font-size")루프를 호출하지 않습니다 . 어디서 구했습니까? 플러그인에 추가 한 멋진 기능이 없으므로 내 솔루션이 더 빠릅니다. jsperf에 플러그인을 추가 할 수 있으며 어떤 플러그인이 가장 빠른지 알 수 있습니다.)
mekwall

1
@MarcusEkwall 아 죄송하지만 어떤 이유로 나는 거기에서 while 루프를 보았습니다. 귀하의 접근 방식은 나 자신과 비슷하며 실제로 플러그인은 높이와 너비에 맞게 조정하고 텍스트와 다른 옵션을 중앙 집중화하는 것과 같은 다른 작업을 수행하기 때문에 조금 느려질 것입니다. 루프 내에서 .css 함수를 호출 중입니다.
호프만

35

내가이 답변에 대해 가끔씩 공감하는 것을 좋아하는만큼 (감사합니다!), 이것은 실제로이 문제에 대한 가장 큰 접근법은 아닙니다. 다른 멋진 답변, 특히 반복하지 않고 솔루션을 찾은 답변을 확인하십시오.


아직도, 참고로 여기에 내 원래의 대답이 있습니다 .

<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>

다음은 클래스 가있는 버전입니다 .

<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>

3
나는이와 함께 더 나은 일을 발견 offsetWidth, 나는 또한 픽셀 추가 한 후 크기에 대한 변수를 생성했다textSpan.style.fontSize = size+"px";
WEZ

2
'+ "px"'가 필요합니다.
sandun dhammika

@IdanShechter 오래 기다려서 죄송합니다! 예를 추가했습니다!
공격

생명의 은인 감사합니다! 나는 jQuery를
모른다.

32

다른 답변의 대부분은 div에 맞을 때까지 글꼴 크기를 줄이기 위해 루프를 사용합니다. 글꼴 크기가 변경 될 때마다 페이지가 요소를 다시 렌더링해야하기 때문에 매우 느립니다. 결국 사용자 브라우저를 멈추지 않고 주기적으로 내용을 업데이트 할 수있는 방식으로 자체 알고리즘을 작성해야했습니다. 다른 기능 (텍스트 회전, 패딩 추가)을 추가하고 jQuery 플러그인으로 패키지하면 다음에서 얻을 수 있습니다.

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

단순히 전화

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

컨테이너에 잘 맞습니다.

여기에서 실제로보십시오 :

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

현재로서는 몇 가지 제한 사항이 있으므로 div의 높이와 너비는 고정되어 있어야하며 여러 줄로 텍스트 줄 바꿈을 지원하지 않습니다.

최대 글꼴 크기를 설정하는 옵션을 얻는 중입니다.

편집 : 플러그인에 더 많은 문제가 있음을 발견했습니다. 표준 모델 이외의 다른 상자 모델을 처리하지 않으며 div에 여백이나 테두리를 가질 수 없습니다. 나는 그것을 할 것입니다.

Edit2 : 나는 이제 이러한 문제와 한계를 수정하고 더 많은 옵션을 추가했습니다. 최대 글꼴 크기를 설정할 수 있으며 너비, 높이 또는 둘 다를 사용하여 글꼴 크기를 제한하도록 선택할 수도 있습니다. 래퍼 요소에서 최대 너비 및 최대 높이 값을 허용하도록 노력하겠습니다.

Edit3 : 플러그인을 버전 1.2.0으로 업데이트했습니다. 코드 및 새로운 옵션 (verticalAlign, horizontalAlign, textAlign)에 대한 주요 정리 및 span 태그 내부의 내부 요소 지원 (줄 바꿈 또는 멋진 아이콘)


1
텍스트를 여러 줄로 줄 바꿈하지 않는 이유가 궁금합니다.
Manish Sapariya

1
@ManishSapariya 지원되지만 줄 바꿈 (br 태그)을 수동으로 추가해야합니다. 자동 텍스트 줄 바꿈을 지원하지 않는 이유는 빠른 텍스트 줄 바꿈 (글꼴 크기를 여러 번 대신 두 번만 변경)하기 때문에 텍스트가 단어 사이에 줄 바꿈되지 않는다는 가정을해야합니다. 플러그인이 작동하는 방식은 글꼴 크기를 1000px로 설정 한 다음 텍스트가 컨테이너와 비교되는 크기의 요소를 확인한 다음 글꼴 크기를 같은 요소로 줄입니다. 일반적인 텍스트 줄 바꿈을 지원하려면 매우 느린 느린 접근 방식 (글꼴 크기를 여러 번 줄이십시오)을 사용해야합니다.
호프만

야! 여기에 비공개 메시지가 없으므로 StackOverflow에 답변에 댓글을 달아서 요청해야합니다. jQuery 플러그인이 마음에 들지만 작동하지 않습니다. 올바른 jQuery 라이브러리를 포함하고 플러그인을 다운로드하여 포함했습니다. 이제 그것을 사용하려고하면 콘솔에 'Uncaught TypeError : undefined is a function'입니다. 이것이 당신이 익숙한 것입니까? 이 문제를 해결하는 방법을 알고 있습니까? 감사합니다
돌풍 밴 드 월마트

@GustvandeWal jquery 라이브러리를 포함시킨 후 플러그인을 포함해야합니다
Hoffmann

나는했다. <script type = "text / javascript"src = " code.jquery.com/jquery-2.1.1.min.js"></… src"js / jquery-bigtext.js "> </ script가 있습니다. > 브라우저가 jQuery 라이브러리 또는 플러그인을로드 할 수 없다는 알림을 표시하지 않습니다.
Gust van de Wal

9

이것은 GeekyMonkey가 위에 게시 한 내용을 기반으로하며 약간 수정되었습니다.

; (function($) {
/**
* Resize inner element to fit the outer element
* @author Some modifications by Sandstrom
* @author Code based on earlier works by Russ Painter (WebDesign@GeekyMonkey.com)
* @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);

차이점은 여러 하위 요소를 사용할 수 있으며 패딩을 고려한다는 것입니다. javascript와 css가 섞이지 않도록 font-size를 기본 최대 크기로 사용합니다.
sandstrom

5
이것은 훌륭하지만 어떻게 사용합니까? 나는 $ ( '. outer'). textfill (); 그리고 나는 변화가 없다.
Drew Baker

3
고마워, 이것은 아주 좋은 구현입니다. 내가 만난 한 가지 : 매우 긴 텍스트 문자열과 매우 좁은 컨테이너를 처리하는 경우 텍스트 문자열이 컨테이너에서 튀어 나오지만 outerWidth는 여전히 그렇지 않은 것처럼 계산됩니다. "단어 줄 바꿈 : 단어 나누기"던지기 해당 컨테이너의 CSS 로이 문제를 해결합니다.
Jon

8

다음은 이진 검색을 사용하여 가능한 가장 작은 단계에서 부모에 맞는 가장 큰 크기를 찾는 향상된 루핑 방법입니다 (고정 된 글꼴 크기로 스테핑하는 것보다 빠르고 정확합니다). 코드는 성능을 위해 여러 가지 방법으로 최적화됩니다.

기본적으로 10 개의 이진 검색 단계가 수행되며 최적 크기의 0.1 % 이내가됩니다. 대신 numIter를 값 N으로 설정하여 최적 크기의 1 / 2 ^ N 이내로 만들 수 있습니다.

CSS 선택기로 호출하십시오. 예 : 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);
        }
    });
};

이 옵션을 좋아하십시오. vAlign및에 대한 매개 변수를 추가하도록 수정했습니다 padding. vAlign == true선택한 요소의 선 높이를 부모 높이의 선 높이로 설정합니다. 패딩은 전달 된 값만큼 최종 크기를 줄입니다. 기본값은 5입니다. 정말 멋지다고 생각합니다.
악마의 옹호자

6

AngularJS에 대한 지시문을 만들었습니다 .GeekyMonkey의 답변에서 영감을 얻었지만 jQuery 종속성은 없습니다.

데모 : http://plnkr.co/edit/8tPCZIjvO3VSApSeTtYr?p=preview

마크 업

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

지령

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();
      });
    }
  };
});

내가 가지고있는 한 가지 문제 resizeTextng-bind실제로 텍스트를 요소에 할당 하기 전에 호출 되어 현재 텍스트가 아닌 이전 텍스트를 기준으로 크기가 조정 되는 것 같습니다 . 위의 데모에서는 사용자가 입력 할 때 반복적으로 호출되는 것이 나쁘지 않지만 null에서 실제 값으로 (한쪽 바인딩과 같이) 한 번 호출되면 최대 크기로 유지됩니다.
Miral

5

위의 스크립트를 Marcus Ekwall ( https://gist.github.com/3945316) 에서 가져 와서 내 환경 설정으로 조정하여 창 크기를 조정하면 자식이 컨테이너에 항상 맞도록 실행됩니다. 아래 스크립트를 참조 용으로 붙여 넣었습니다.

(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);

2
당신이 그 잘못을 도와 주려고 노력하는 것이 좋습니다. 그러나 링크만으로 답변을 남기면 해로울 수 있습니다. 귀하의 답변은 지금은 좋지만 링크가 끊어지면 귀하의 답변은 가치를 잃게됩니다. 답변에서 기사의 내용을 요약하면 도움이 될 것입니다. 설명을 위해이 질문을 참조하십시오 .
코디 굴드 너

5

다음은 OP의 답변을 수정 한 것입니다.

요컨대, 이것을 최적화하려고 시도한 많은 사람들이 루프가 사용되고 있다고 불평했습니다. 예, 루프가 느릴 수 있지만 다른 접근 방식은 정확하지 않을 수 있습니다.

따라서 필자의 접근 방식은 이진 검색 을 사용 하여 최상의 글꼴 크기를 찾습니다.

$.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);

또한 요소가 최소 및 최대 글꼴을 지정할 수 있습니다.

<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>

또한이 알고리즘은 단위가 없습니다. 당신은 지정할 수 있습니다 em, rem, %, 등 및 그것의 최종 결과에 대한 것을 사용합니다.

여기는 바이올린입니다 : https://jsfiddle.net/fkhqhnqe/1/


2

내 웹 사이트와 정확히 같은 문제가있었습니다. 프로젝터, 벽, 큰 화면에 표시되는 페이지가 있습니다.

내 글꼴의 최대 크기를 모르므로 @GeekMonkey 위의 플러그인을 재사용했지만 fontsize를 늘리십시오.

$.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 );
        });
    };

이 페이지에서 실제로 나를 위해 일한 유일한 플러그인 인 +1!
skybondsor

2
이 플러그인은 페이지를 충돌시킵니다.
Jezen Thomas

1

다음은 minFontSize 매개 변수를 사용할 수있는 허용되는 답변 버전입니다.

(function($) {
    /**
    * Resizes an inner element's font so that the inner element completely fills the outer element.
    * @author Russ Painter WebDesign@GeekyMonkey.com
    * @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

FitText.js ( github page )를 사용 하여이 문제를 해결할 수 있습니다. TextFill에 비해 실제로 작고 효율적입니다. TextFill은 비싼 while 루프를 사용하지만 FitText는 사용하지 않습니다.

또한 FitText는보다 유연합니다 (매우 특별한 요구 사항이있는 proyect에서 사용하고 챔피언처럼 작동합니다!).

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>

옵션을 설정할 수도 있습니다.

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

CSS :

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

필요한 경우 FitText에는 jQuery없는 버전도 있습니다.


fittext는 높이를 고려합니까?
Manish Sapariya

1
@ManishSapariya 아니에요. 컨테이너 너비를 10으로 나누고 글꼴 크기로 사용합니다.
Dan H

1

편집 :이 코드는 HTML5 비디오 위에 메모를 표시하는 데 사용되었습니다. 비디오 크기가 조정되면 (브라우저 창의 크기가 조정될 때) 글꼴 크기가 즉석에서 변경됩니다. 노트가 비디오에 연결된 경우 (YouTube의 노트와 마찬가지로) 코드에서 DOM 핸들 대신 인스턴스를 사용하는 이유 직접.

요청에 따라 이것을 달성하는 데 사용한 코드를 던져 보겠습니다. (HTML5 비디오 위에 텍스트 상자가 있습니다.) 코드는 오래 전에 작성되었으며 솔직히 말해서 꽤 지저분하다고 생각합니다. 질문에 이미 답변되어 있고 오래 전에 이미 답변이 수락되었으므로 이것을 다시 쓰지 않아도됩니다. 그러나 누군가 이것을 조금 단순화하고 싶다면 환영합니다.

// 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);

이 숫자들을 font-family에서 font-family로 조정해야 할 것입니다. 이를 수행하는 좋은 방법은 GeoGebra라는 무료 그래프 시각화 도구를 다운로드하는 것입니다. 텍스트 길이와 상자 크기를 변경하십시오. 그런 다음 크기를 수동으로 설정하십시오. 수동 결과를 좌표계에 플로팅합니다. 그런 다음 여기에 게시 한 두 방정식을 입력하고 "my"그래프가 직접 플롯 한 점에 맞을 때까지 숫자를 조정합니다.


1

제안 된 반복 솔루션은 두 가지 측면에서 극적으로 향상 될 수 있습니다.

1) 글꼴 크기에 1을 더하거나 빼지 않고 상수를 곱하십시오.

2) 먼저 코스 상수를 사용하면 0, 즉 각 루프의 크기를 두 배로 늘립니다. 그런 다음 어디에서 시작해야하는지 대략적인 생각으로 1.1을 곱한 것과 같은 미세 조정으로 동일한 작업을 수행하십시오. 완벽 주의자는 이상적인 글꼴의 정확한 정수 픽셀 크기를 원하지만 대부분의 관찰자는 100과 110 픽셀의 차이를 인식하지 못합니다. 완벽 주의자라면 더 세밀하게 조정하여 세 번 반복하십시오.

정확한 질문에 대답하는 특정 루틴이나 플러그인을 작성하는 대신 기본 아이디어에 의존하고 코드의 변형을 작성하여 텍스트, div, span, 이미지 등 모든 종류의 레이아웃 문제를 처리합니다. .. 너비, 높이, 면적, 컨테이너 내에서 다른 요소와 일치합니다 ....

예를 들면 다음과 같습니다.

  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

이것은 내가 만든 가장 우아한 솔루션입니다. 이진 검색을 사용하여 10 회 반복합니다. 순진한 방법은 while 루프를 수행하고 요소가 오버플로되기 시작할 때까지 글꼴 크기를 1 씩 늘리는 것입니다. element.offsetHeightelement.scrollHeight를 사용하여 요소가 오버플로되기 시작하는시기를 결정할 수 있습니다 . scrollHeight가 offsetHeight보다 큰 경우 글꼴 크기가 너무 큽니다.

이진 검색이 훨씬 더 나은 알고리즘입니다. 또한 수행하려는 반복 횟수에 의해 제한됩니다. flexFont를 호출하고 div id를 삽입하면 글꼴 크기가 8px ~ 96px 사이에서 조정됩니다 .

나는이 주제를 연구하고 다른 라이브러리를 시도하는 데 시간을 보냈지 만 궁극적으로 이것이 실제로 작동하는 가장 쉽고 간단한 솔루션이라고 생각합니다.

당신은 당신이 사용하는 변경하려는 경우 참고 offsetWidth하고 scrollWidth, 또는이 기능을 모두 추가 할 수 있습니다.

// Set the font size using overflow property and div height
function flexFont(divId) {
    var content = document.getElementById(divId);
    content.style.fontSize = determineMaxFontSize(content, 8, 96, 10, 0) + "px";
};

// Use binary search to determine font size
function determineMaxFontSize(content, min, max, iterations, lastSizeNotTooBig) {
    if (iterations === 0) {
        return lastSizeNotTooBig;
    }
    var obj = fontSizeTooBig(content, min, lastSizeNotTooBig);

    // if `min` too big {....min.....max.....}
    // search between (avg(min, lastSizeTooSmall)), min)
    // if `min` too small, search between (avg(min,max), max)
    // keep track of iterations, and the last font size that was not too big
    if (obj.tooBig) {
        (lastSizeTooSmall === -1) ?
            determineMaxFontSize(content, min / 2, min, iterations - 1, obj.lastSizeNotTooBig, lastSizeTooSmall) :
                determineMaxFontSize(content, (min + lastSizeTooSmall) / 2, min, iterations - 1, obj.lastSizeNotTooBig, lastSizeTooSmall);

    } else {
        determineMaxFontSize(content, (min + max) / 2, max, iterations - 1, obj.lastSizeNotTooBig, min);
    }
}

// determine if fontSize is too big based on scrollHeight and offsetHeight, 
// keep track of last value that did not overflow
function fontSizeTooBig(content, fontSize, lastSizeNotTooBig) {
    content.style.fontSize = fontSize + "px";
    var tooBig = content.scrollHeight > content.offsetHeight;
    return {
        tooBig: tooBig,
        lastSizeNotTooBig: tooBig ? lastSizeNotTooBig : fontSize
    };
}

고마워요! 그냥 받고 있어요 ReferenceError: lastSizeTooSmall is not defined. 어딘가에 정의해야할까요?
ndbroadbent

0

나는 같은 문제를 겪었고 해결책은 기본적으로 자바 스크립트를 사용하여 글꼴 크기를 제어하는 ​​것입니다. 코드 펜에서이 예제를 확인하십시오.

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

이 예는 높이에 대한 예일 것입니다.

크기를 조정하십시오

<!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

나는 좋아했다

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

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

텍스트를 축소하기 위해 루프를 사용하지 못하게하는 방법을 찾았습니다. 컨테이너 너비와 내용 너비 사이의 비율에 글꼴 크기를 곱하여 글꼴 크기를 조정합니다. 따라서 컨테이너의 너비가 내용의 1/3이면 글꼴 크기가 1/3 줄어들고 컨테이너의 너비가 줄어 듭니다. 스케일 업하기 위해 컨텐츠가 컨테이너보다 클 때까지 while 루프를 사용했습니다.

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'; 
            }
        }
    }
}

이 코드는 내가 Github에 업로드 한 테스트의 일부입니다 https://github.com/ricardobrg/fitText/


0

geekMonkey 솔루션을 사용했지만 너무 느립니다. 그가하는 일은 글꼴 크기를 최대 (maxFontPixels)로 조정 한 다음 컨테이너 내부에 맞는지 확인하는 것입니다. 그렇지 않으면 글꼴 크기를 1px 줄이고 다시 확인합니다. 왜 이전 컨테이너의 높이를 확인하고 그 값을 제출하지 않습니까? (예, 이유를 알고 있지만 이제는 높이에서만 작동하고 최소 / 최대 옵션이있는 솔루션을 만들었습니다)

훨씬 빠른 해결책은 다음과 같습니다.

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();
);

그리고 이것은 HTML이 될 것입니다 :

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

다시 :이 솔루션은 컨테이너의 높이 만 확인합니다. 그렇기 때문에 요소가 내부에 맞는 경우이 기능을 확인하지 않아도됩니다. 그러나 최소 / 최대 값 (40min, 150max)도 구현 했으므로 완벽하게 작동하며 창 크기 조정에서도 작동합니다.


-1

이 솔루션의 다른 버전은 다음과 같습니다.

shrinkTextInElement : function(el, minFontSizePx) {
    if(!minFontSizePx) {
        minFontSizePx = 5;
    }
    while(el.offsetWidth > el.parentNode.offsetWidth || el.offsetHeight > el.parentNode.offsetHeight) {

        var newFontSize = (parseInt(el.style.fontSize, 10) - 3);
        if(newFontSize <= minFontSizePx) {
            break;
        }

        el.style.fontSize = newFontSize + "px";
    }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.