web-dev-qa-db-ja.com

固定Divに収まるようにJavaScriptスケールテキスト

JavaScript/jQueryで、固定幅Div内の可変長テキスト行をスケーリングして、1行が常にDiv内に(1行として)収まるようにするにはどうすればよいですか?

ありがとう。

53
Stephen Watkins

これはややハックですが、あなたが望むことをします。

<div id="hidden-resizer" style="visibility: hidden"></div>

これをページの下部に配置します。ページ上の他の要素は移動しません。

次にこれを行います:

var size;
var desired_width = 50;
var resizer = $("#hidden-resizer");

resizer.html("This is the text I want to resize.");

while(resizer.width() > desired_width) {
  size = parseInt(resizer.css("font-size"), 10);
  resizer.css("font-size", size - 1);
}

$("#target-location").css("font-size", size).html(resizer.html());
69
sworoc

HTML:

<div class="box" style="width:700px">This is a sentence</div>
<div class="box" style="width:600px">This is a sentence</div>
<div class="box" style="width:500px">This is a sentence</div>
<div class="box" style="width:400px">This is a sentence</div>

JavaScript:

$( '.box' ).each(function ( i, box ) {

    var width = $( box ).width(),
        html = '<span style="white-space:nowrap"></span>',
        line = $( box ).wrapInner( html ).children()[ 0 ],
        n = 100;

    $( box ).css( 'font-size', n );

    while ( $( line ).width() > width ) {
        $( box ).css( 'font-size', --n );
    }

    $( box ).text( $( line ).text() );

});

ライブデモ:http://jsfiddle.net/e8B9j/2/show/

URLから「/ show /」を削除してコードを表示します。

30
Šime Vidas

これを行うjQueryプラグインを作成しました。

http://michikono.github.com/boxfit

プラグインは、テキストを水平方向と垂直方向の両方でボックス内で使用可能な最大サイズに拡大縮小し、中央に配置します。

あなたがする必要がある唯一のことは、その中にテキストでdivを定義することです:

<div id="scale">some text</div>

そして、呼び出します:

$('#scale').boxfit()

このメソッドは、テキストの折り返しと中央揃えを無効/有効にするいくつかの引数を受け入れます。

13
Michi Kono

新しいブラウザの場合、Inline-SVGを使用できます。これは、CSSを介して画像のようにスケーリングできます。

.smallerVersion{
max-width: 50%
}
<!DOCTYPE html>
<html>
<head>
<title>Scale SVG example</title>
</head>

<body>





<h2>Default version:</h2>
<svg viewBox="0 0 240 80" xmlns="http://www.w3.org/2000/svg">
  <style>
    .small { font: italic 13px sans-serif; }
    .heavy { font: bold 30px sans-serif; }

    /* Note that the color of the text is set with the    *
     * fill property, the color property is for HTML only */
    .Rrrrr { font: italic 40px serif; fill: red; }
  </style>

  <text x="20" y="35" class="small">My</text>
  <text x="40" y="35" class="heavy">cat</text>
  <text x="55" y="55" class="small">is</text>
  <text x="65" y="55" class="Rrrrr">Grumpy!</text>
</svg>

<h2>Scaled version:</h2>
<svg class="smallerVersion" viewBox="0 0 240 80" xmlns="http://www.w3.org/2000/svg">
  <style>
    .small { font: italic 13px sans-serif; }
    .heavy { font: bold 30px sans-serif; }

    /* Note that the color of the text is set with the    *
     * fill property, the color property is for HTML only */
    .Rrrrr { font: italic 40px serif; fill: red; }
  </style>

  <text x="20" y="35" class="small">My</text>
  <text x="40" y="35" class="heavy">cat</text>
  <text x="55" y="55" class="small">is</text>
  <text x="65" y="55" class="Rrrrr">Grumpy!</text>
</svg>




</body>

</html>

width: 100%;

7
Benjamin

他の回答のほとんどは、divに収まるまでループを使用してフォントサイズを縮小します。フォントのサイズが変更されるたびにページで要素を再レンダリングする必要があるため、これは非常に遅くなります。最終的には、ユーザーブラウザーをフリーズせずにコンテンツを定期的に更新できるように実行するために、独自のアルゴリズムを作成する必要がありました。他の機能(テキストの回転、パディングの追加)を追加し、jQueryプラグインとしてパッケージ化しました。次のURLで入手できます。

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

単に電話する

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

コンテナにうまく収まります。

こちらで実際にご覧ください:

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

現時点ではいくつかの制限があり、divの高さと幅は固定されている必要があり、複数行へのテキストの折り返しはサポートされていません。

Edit2:これらの問題と制限を修正し、オプションを追加しました。最大フォントサイズを設定できます。また、幅、高さ、またはその両方(デフォルトは両方)を使用してフォントサイズを制限することもできます。ラッパー要素でmax-widthとmax-heightの値を受け入れることに取り組みます。

5
Hoffmann

正確な方法はわかりませんが、近似値は次のとおりです。

var factor = 1/3;  // approximate width-to-height ratio
var div = $('#mydiv');
div.css('font-size', div.width() / (div.text().length * factor) + 'px');

使用しているフォントに基づいてfactorを調整する必要があります。 1/3はTimes New Romanで問題なく動作するようです。

3
casablanca
2
testere

Div内で、パディングのないスパンにテキストを配置します。その場合、スパンの幅はテキストの長さになります。
使用する正しいフォントサイズを見つけるためのテストされていないコード:

var objSpan = $('.spanThatHoldsText');  
var intDivWidth = $('.divThatHasAFixedWidth').width();  
var intResultSize;  

for (var intFontSize = 1; intFontSize < 100; intFontSize++)  

  objSpan.css('font-size', intFontSize);  

  if (objSpan.width() > intDivWidth) {  
    intResultSize = intFontSize - 1;  
    break;  
  }  

}

objSpan.css('font-size', intResultSize);
2
EmKay

ターゲットクラスのサポートによる@sworocの修正バージョン

function resizeText(text, size, target) {

    var fontSize = 0;
    var resizer = $('<span>');

    resizer.html(text).hide();
    resizer.attr('class', target.attr('class'));
    $('body').append(resizer);

    while(resizer.width() < size) {
        fontSize++
        resizer.css("font-size", fontSize);
    }

    target.css('font-size', fontSize).html(text);
    resizer.remove();
}

使用法

resizeText("@arunoda", 350, $('#username'));
2

ここに私が思いついたコーヒースクリプトソリューションがあります。フォントのサイズを変更する必要がある要素を複製し、計算の最後に削除します。パフォーマンスを向上させるために、サイズ変更が200ミリ秒間停止した後にのみ計算を実行するコードがあります。

クラスautofontで要素にタグを付けます。これは控えめに行われます。

# 
# Automagically resize fonts to fit the width of the 
# container they are in as much as possible. 
#
fixfonts = ->

  scaler = 1.2

  for element in $('.autofont')

    size =  1
    element = $(element)
    desired_width = $(element).width()

    resizer = $(element.clone())
    resizer.css
      'font-size': "#{size}em"
      'max-width': desired_width
      'display': 'inline'
      'width': 'auto'
    resizer.insertAfter(element)

    while resizer.width() < desired_width
      size = size * scaler
      resizer.css
        'font-size':  "#{size}em"

    $(element).css
        'font-size': "#{size / scaler }em"

    resizer.remove()

$(document).ready =>
  fixfonts()

  timeout = 0
  doresize = ->
    timeout--
    if timeout == 0
      fixfonts()

  $(window).resize ->
    timeout++
    window.setTimeout doresize, 200
2
bradgonesurfing

私は同様の問題を抱えていたため、このために独自のプラグインを作成しました。 1つの解決策は、上記のように、縮小して合わせる方法を使用することです。ただし、複数のアイテムを収める必要がある場合や、ウィンドウのサイズ変更などのパフォーマンスに関心がある場合は、 jquery-quickfit をご覧ください。

テキストの各文字に合わせてサイズ不変測定値を測定および計算し、これを使用して、テキストをコンテナに収める次の最適なフォントサイズを計算します。

計算はキャッシュされるため、複数のテキストを処理したり、ウィンドウのサイズ変更などのようにテキストを複数回合わせる必要がある場合、非常に高速になります(2番目のサイズ変更によるパフォーマンスの低下はほとんどありません)。

制作例、14x16x2テキストのフィッティング

1
chunks_n_bits

これは、コンテナの高さも考慮に入れた@teambobの提案( 上記のコメント )に対する私の修正です。

<div class="box" style="width:700px; height:200px">This is a sentence</div>
<div class="box" style="width:600px; height:100px">This is a sentence</div>
<div class="box" style="width:500px; height:50px">This is a sentence</div>
<div class="box" style="width:400px; height:20px">This is a sentence</div>

その後..

$('.box').each(function(i, box) {

    var width = $(box).width(),
        height = $(box).height(),
        html = '<span style="white-space:nowrap">',
        line = $(box).wrapInner(html).children()[0],
        maxSizePX = 2000;

    $(box).css('font-size', maxSizePX);
    var widthFontSize = Math.floor(width/$(line).width()*maxSizePX),
        heightFontSize = Math.floor(height/$(line).height()*maxSizePX),
        maximalFontSize = Math.min(widthFontSize, heightFontSize, maxSizePX);

    $(box).css('font-size', maximalFontSize);
    $(box).text($(line).text());

});

Fiddle を参照してください

1
Ville

この問題に対処するために、(まだ)別のプラグインを作成しました。

https://github.com/jeremiahrose/perfectFit.js

SVGを生成するため、非常に高速です。ページのロード時に1回だけ実行されます。 divに正確に合うように個々の単語を自動的にラップおよびスケーリングできます。

1
Jeremiah Rose

これをsworocの投稿に追加する方法を理解できませんでしたが、とにかく共有すると思いました:AJAXナビゲーションを使用している場合、Lonesomedayのソリューションは台無しになります。 :

if ($('#hidden-resizer').length == 0){ 
    $('<div />', {id: 'hidden-resizer'}).hide().appendTo(document.body); 
}
1
deweydb

私の解決策は次のとおりです。提供されたdiv内の新しいdivのテキストを測定し、スタイルが継承されるようにします。次に、フォントサイズを設定するために、スパンを持つテキストをdivに挿入します。デフォルトのフォントサイズに最大化されますが、収まるように縮小されます。

ループしません。指定されたdivに直接描画する前に、スローアウェイdivにテキストを1回だけ描​​画します。 @Hoffmannの回答を参照してください-私は質問に答えるために「プラグイン」全体が好きではありませんでした。

jqueryが必要です。

var txt = txt || {}
txt.pad_factor = 1.1;
txt.insertText_shrinkToFit = function(div,text)
{
  var d = txt.cache || $('<div></div>');
  txt.cache = d;

  d.css('white-space','nowrap');
  d.css('position','absolute');
  d.css('top','-10000px');
  d.css('font-size','1000px');

  var p = $(div);
  var max_w = parseInt(p.css('max-width')) || p.width();
  var max_h = parseInt(p.css('font-size'));

  p.append(d);
  d.html(text);
  var w = d.width() * txt.pad_factor; 
  d.remove();

  var h = Math.floor(max_w*1000/w);
  var s = ( max_h < h ? max_h : h ) + "px";

  p.html('<SPAN style="font-size:' + s + '">' + text + '</SPAN>');
}

例えば:

<html><head><script src=http://code.jquery.com/jquery-latest.min.js></script>
<script>/*insert code, from above, here.*/</script></head><body>

<div id=mysmalldiv style="max-width:300px;font-size:50px"></div>
<script>
  txt.insertText_shrinkToFit("#mysmalldiv","My super long text for this div.");
</script>

</body></html>

テストの場合:これは、1.1 pad_factorが必要であることがわかった方法です。ニーズに合わせて調整できます。

<div id=mytestdiv style="max-width:300px;font-size:50px"></div>
<script>
  var t = "my text ";
  var i = 0;
  var f = function() {
    t += i + " ";
    txt.insertText_shrinkToFit("#mytestdiv",t);
    i++;
    if(i < 100) 
      setTimeout(f,1000);
  }
  f();
</script>

注:これはpxフォントサイズを想定しています。私はemまたはptでテストしていません。

0
JJ Stiff

次のような複数のことができます

overflow:hidden

これは余分な行をカットします

overflow:auto //これはスクロールバーを表示します

これを見て

http://www.w3schools.com/Css/pr_pos_overflow.asp

これを試みてください//テキストの長さを確認してください

if($('#idfortext').length>sometthing)
{
var fontsize=10;
}
$('#yourid').css('font-size',fontsize)
0
kobe

純粋なCSSのヘッダーなどの単一行テキストに対してこれを行うには、素晴らしい方法があります。

h1{
    font-size: 4.5vw;
    margin: 0 0 0 0;
    line-height: 1em;
    height: 1em;
}

h1:after{
    content:"";
    display: inline-block;
    width: 100%;
}

フォントサイズがヘッダー1行を維持するのに十分小さいことを確認してください。 「px」の代わりに「vw」(ビューポートの幅)を使用すると、これを非常に簡単に行うと同時にスケーリングできます。ビューポートの幅は、ブラウザウィンドウを非常に大きくすると不快になる傾向があります。多くのサイトは、これを使用して、実際のワイド画面で特定の幅にサイトを維持します。

body{
   max-width: 820px;
   margin: 0 auto;
}

サイトの残りの部分がスケーリングを停止した後のビューポートウィンドウの大きさにフォントが基づいていないことを確認するには、これを使用します。

@media(min-width:820px){
   h1{
      font-size: 30px; 
   }
}
0
patrick

テキストの幅をピクセル単位で正確に測定する方法があるかどうかはわかりません(これは問題の根本で実際に探しているものです)。ブラウザごとにフォントが異なる場合があるためです。文の文字数に基づいて「ファジー」サイズ変更に加えて、このCSSコードを使用してみてください。固定幅フォント(またはスタイル)を使用してテキストを表示し、各文字が同じスペースを占めるようにすることができます。この方法で、あなたは最良の推測をすることができ、CSSは必要に応じてテキストを切り取る前に少なくとも素敵な「...」を提供します。

.truncate 
{ 
    overflow: hidden; 
    white-space: nowrap; 
    text-overflow: Ellipsis; 
} 
0
Dutchie432

コンテナの幅と高さに合うプラグイン

http://blissitec.github.io/scaletextjs/

0
Stevanicus

これは私が今日見つけたものです:

  1. 本当に大きな偽のフォントサイズ(f)をターゲットテキストに設定します
  2. テキストコンテナの幅(w)高さ(h)を測定し、font-size(f)で除算します。

    • iw = w/f
    • ih = h/f
  3. メインコンテナの幅(W)をiwで、メインコンテナの高さ(H)をihで除算します。

    • kw = W/iw
    • kh = H/ih
  4. Kwとkhの間で最も低い値を選択します。これが目的のFontSizeです。

https://jsfiddle.net/pinkynrg/44ua56dv/

function maximizeFontSize($target) {

  var testingFont = 1000;
    $target.find(".text-wrapper").css("font-size", testingFont+"px");

  var textWidth = $(".text-wrapper").width()/1000;
  var textHeight = $(".text-wrapper").height()/1000;
  var width = $(".container").width();
  var height = $(".container").height();

  var kWidth = width/textWidth;
  var kHeight = height/textHeight;
  var fontSize = kWidth < kHeight ? kWidth : kHeight;

  // finally
  $(".text-wrapper")
    .css("font-size", fontSize+"px")
    .css("line-height", height+"px");
}
0
Francesco Meli

ここでいくつかの投稿を行い、そこからjQueryプラグインを作成しました。一番下から始めて上に行くことはあまりパフォーマンスが良くないことがわかったので、現在のフォントサイズが近いと仮定して、そこから作業しました。

  $.fn.fitTextToWidth = function(desiredWidth) {
    // In this method, we want to start at the current width and grow from there, assuming that we are close to the desired size already.
    var $el = $(this);
    var resizer = $('<'+$el.get(0).tagName+' />').css({'vsibility':'hidden','position':'absolute','left':'-9999px','display':'inline'}).html($el.html());
    resizer.appendTo(document.body);

    var size = parseInt($el.css('font-size'));
    resizer.css('font-size',size+'px');

    var growing = desiredWidth > resizer.width() ? true : false;
    var adder = growing ? 1 : -1;
    do {
        size += adder;
        resizer.css('font-size',size+'px');
    } while(((growing && resizer.width()<desiredWidth) || (!growing && resizer.width()>desiredWidth)) && size>10 && size<100);
    if (growing)
        size -= 2; //we never want to go over
    resizer.remove();

    $el.css('font-size',size+'px'); 
  }

  // Example use:
  $('#main h1').fitTextToWidth(350);

これに関する唯一の落とし穴は、要素のCSSがグローバルであり、要素タイプにのみ適用されると想定していることです。言い換えると、同じ名前のタグを作成し、変更したい要素と同じCSS属性を持つと仮定します。これが当てはまらない場合は、resizerが作成される行を変更します。

0
Cory Gagliardi