コンテナの幅に基づくフォントのスケーリング


1187

フォントの拡大縮小に頭を悩ませています。

私は現在、このサイトに本文がありますfont-sizeは100%です。でも100%?これは16ピクセルで計算されるようです。

100%はどういうわけかブラウザウィンドウのサイズを指しているのではないかという印象を受けましたが、ウィンドウのサイズがモバイルの幅に変更されても、フルスクリーンのワイドスクリーンデスクトップに変更されても、常に16ピクセルなので、そうではありません。

コンテナーに関連してサイトのテキストをどのように拡大できますか?使ってみたemが、これもスケーリングしません。

私の考えでは、サイズを変更するとメニューなどが潰れるため、コンテナの幅に関連して他の要素px font-size.menuItem中でを減らす必要があります。(たとえば、大きなデスクトップのメニューでは、22px完全に機能します。タブレットの幅まで下に移動し、16pxより適切です。)

ブレークポイントを追加できることは承知していますが、テキストを拡大縮小するだけでなく、追加のブレークポイントも必要です。そうしないと、テキストを制御するために、幅が100ピクセル減少するたびに数百のブレークポイントが発生します。


34
font-size: 100%;テキストのサイズ(つまり、親から継承したサイズ)の100%を意味します。デフォルトは16pxです。したがって、50%を使用した場合、それはfont-size:8px
Andy

31
あなたが探しているものは、レスポンシブまたはビューポートサイズのタイポグラフィと呼ばれます。css-tricks.com/viewport-sized-typography
gearsdigital

8
与えるFitTextに見て。
Patsy Issa

12
@Andy:実際には、「デフォルト」はユーザーがブラウザのテキストサイズを設定しているものであり、必ずしも16pxに解決されるとは限りません。
ScottS 2013年

1
この回答を見てみましょうstackoverflow.com/a/28485608/4251431
バシールAL-MOMANI

回答:


1496

編集:コンテナーが本体ではない場合、 CSSトリックはテキストをコンテナー合わせるのすべてのオプションをカバーします。

コンテナーが本体である場合、探しているのはビューポートのパーセンテージの長さです。

ビューポート・パーセンテージの長さはサイズに対して相対的初期包含ブロック。最初の包含ブロックの高さまたは幅が変更されると、それらはそれに応じてスケーリングされます。ただし、ルート要素のオーバーフローの値がautoの場合、スクロールバーは存在しないと見なされます。

値は次のとおりです。

  • vw (ビューポートの幅の%)
  • vh (ビューポートの高さの%)
  • vi (ルート要素のインライン軸方向のビューポートサイズの1%)
  • vb (ルート要素のブロック軸方向のビューポートサイズの1%)
  • vminvwまたはの小さい方vh
  • vmax(より大きいまたはvwまたはvh

1 v *は、最初の包含ブロックの1%に相当します。

これを使用すると、次のようになります。

p {
    font-size: 4vw;
}

ご覧のとおり、ビューポートの幅が大きくなると、font-sizeメディアクエリを使用する必要なく、が大きくなります。

これらの値は、pxまたはemと同様にサイズ設定単位であるため、幅、マージン、パディングなどの他の要素のサイズ設定にも使用できます。

ブラウザのサポートはかなり良いですが、次のようなフォールバックが必要になる可能性があります。

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

サポート統計を確認してください:http : //caniuse.com/#feat=viewport-units

また、CSS-Tricksでより広い外観を確認してください:ビューポートサイズのタイポグラフィ

最小/最大サイズの設定と、サイズをもう少し制御することについての素晴らしい記事は次のとおりです。レスポンシブタイポグラフィの正確な制御

そして、テキストがビューポートを満たすようにcalc()を使用してサイズを設定することについての記事があります: 。http //codepen.io/CrocoDillon/pen/fBJxu

また、こちらの記事もご覧ください。「溶融誘導」と呼ばれる技法を使用して、行の高さも調整しています。CSSの最先端を行く


547
しかし、コンテナがビューポート(ボディ)ではない場合はどうなりますか?
Alex

12
@アレックス、それはJS領域です。FitText.js提供されている記事@jbenjohnsonの下部にある代替案を試してください。
Robbert 2013年

10
これがいわゆる要素クエリの出番です。メディアクエリとは異なり、要素クエリはビューポートではなく、それを含むブロックに基づいてサイズを決定します。しかし、残念ながらそれはまだ存在していません。ただし、興味がある場合は、いくつかのポリフィルと概念実証が存在します。coding.smashingmagazine.com / 2013/06/25 / およびフィラメント
グループ.com / lab / element_query_workarounds

139
これは質問に答えないため、ダウングレードされました。彼はビューポートではなくコンテナについて尋ねました。完全に異なるユースケース。
SongBox 2016

6
「初期包含ブロック」はルート要素を指します。これは、尋ねられた質問に対する正しい答えではありません。
グリフ2017

320

しかし、コンテナがビューポート(ボディ)でない場合はどうなりますか?

この質問は、受け入れられた回答の下でアレックスによってコメントで尋ねられます

その事実はvw、そのコンテナのサイズにある程度使用できないことを意味しません。ここで、バリエーションを確認するには、コンテナのサイズがある程度柔軟であると想定する必要があります。直接的なパーセンテージを通じて、widthまたは100%からマージンを差し引いて。コンテナーが常に、たとえば200pxワイドに設定されている場合、ポイントは「スムーズ」になりfont-sizeます。次に、その幅で機能するを設定するだけです。

例1

ただし、幅がフレキシブルなコンテナでは、何らかの方法でコンテナがまだビューポートからサイズ変更されていることを認識しておく必要があります。そのvwため、ビューポートに対するそのパーセンテージサイズの違いに基づいて設定を調整することです。つまり、親ラッパーのサイズを考慮する必要があります。この例を見てみましょう

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

ここで想定するとdivの子であるbody、それは50%それで100%、この基本的なケースでは、ビューポートのサイズである幅、。基本的には、vw見栄えのするを設定します。上記のCSSコンテンツの私のコメントでわかるように、フルビューポートサイズに関して数学的にそれを「考える」ことができますが、そうする必要ありません。コンテナはビューポートのサイズ変更に伴って変化するため、テキストはコンテナとともに「変化」します。更新:2つの異なるサイズのコンテナーの例を次に示します。

例2

これに基づいて計算を強制することにより、ビューポートのサイズ変更を確実にすることができます。この例を考えてみましょう

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

サイズ設定は依然としてビューポートに基づいていますが、本質的にはコンテナーサイズ自体に基づいて設定されます。

コンテナのサイズは動的に変化する必要があります...

コンテナ要素のサイズ設定が、@mediaブレークポイントまたはJavaScript を介してパーセンテージ関係を動的に変更することになった場合、ベース「ターゲット」がテキストのサイズ設定と同じ「関係」を維持するために再計算する必要がありました。

上記の例1を見てください。divがJavaScriptまたはJavaScript 25%によって幅に切り替えられた場合、@media同時に、font-sizeはメディアクエリまたはJavaScriptのいずれかでの新しい計算に調整する必要があります5vw * .25 = 1.25。これにより、元の50%コンテナの「幅」がビューポートのサイズ変更から半分に減らされた場合と同じサイズにテキストサイズが設定されますが、独自のパーセンテージ計算の変更により縮小されました。

挑戦

CSS3のcalc()機能の使用中に、その機能が動作しないよう、動的に調整することが困難になるでしょうfont-size。この時点で目的。したがって、幅が変化してcalc()いる場合は、CSS 3だけで調整することはできません。もちろん、マージンの幅を少し調整しても、の変更を保証するには不十分なfont-size場合があるため、問題にならない場合があります。


(ビューポートのパーセンテージの長さとウィンドウのサイズ変更に関するChromeのバグがあります:code.google.com/p/chromium/issues/detail?id=124331
thirtydot '12

@thirtydot:それは残念です(しかし、知っておくと良いです、ありがとう)。バグがすぐに解決されることを願っていますが、しばらくの間それが持続しているようです。
ScottS 2013年

20
すばらしい答えですが、それを含む要素に最大幅がある場合は機能しません。
Himmators 2014年

3
@KristofferNolgren:これは私の回答で述べた2つのポイントに関連しています:(1)「コンテナのサイズがある程度柔軟であると仮定する」( 'max-width'に到達すると、それが屈曲しないため、問題が発生します) )。(2)「max-width」に到達する時点を決定できる場合は、前述したように、@mediaブレークポイントを設定して、その時点でのフォントのサイズを変更できます(基本的に、到達時に固定サイズになりますmax-width) 。max-width状況に対処するための単なる考え。
ScottS 2014年

コンテナー要素がメディアクエリを通じて動的に変化するときのフィドルを投げることができると思いますか?私は上手く理解できていない気がします。
J82

59

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/


SVGを使用したソリューションと、次を使用したテキストの折り返し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
このアイデアは、最初は見栄えがします。次に、<html>内のSVGのフォントを簡単に制御できないことに気付きます。フォントはモバイルとデスクトップで異なり、最終的な幅に影響します。
ストポ

@Stopi iFrameソリューションについてどう思いますか?
Dantio

10
HTML / CSSからSVGのスタイルを完全に設定できます
gman

1
svgがインラインの場合、SVGをcssでスタイル設定できます(imgタグは使用しないでください)。

8
これは、動的コンテナに基づいてスケーリングする、最も優れた、最も予測可能なソリューションです。
JoshuaDavid

35

私のプロジェクトの1つでは、vwとvhの「混合」を使用して、フォントサイズを自分のニーズに合わせて調整します。次に例を示します。

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

これでOPの質問に答えられないことはわかっていますが、おそらく他の人への解決策になる可能性があります。


3
vminまたはvmax代わりにを使用した方がよい場合があります。
sebastian_k

4
chrome開発ツールはこれを無効なプロパティ値と呼びます
phil294

31

calc()CSSユニットと数学を使用したPure-CSSソリューション

これは正確にはOPが要求するものではありませんが、誰かの日になるかもしれません。この答えは、スプーンフィーディングで簡単ではなく、開発者側の調査が必要です。

ようやくcalc()、さまざまなユニットで使用するための純粋なCSSソリューションを手に入れました。の式を計算するには、数式の基本的な数学的理解が必要ですcalc()

これを解決したとき、DOMでいくつかの親を埋め込んだフルページ幅のレスポンシブヘッダーを取得する必要がありました。ここでは自分の値を使用します。自分の値に置き換えてください。

数学へ

必要になるだろう:

  • 一部のビューポートで比率を適切に調整しました。320ピクセルを使用したため、高さが24ピクセル、幅が224ピクセルになったため、比率は9.333 ...または28/3になります。
  • コンテナの幅、私が持っていたpadding: 3em全幅なので、これは100wv - 2 * 3em

Xはコンテナーの幅なので、独自の式に置き換えるか、値を調整して全ページのテキストを取得します。Rあなたが持つ比率です。一部のビューポートで値を調整し、要素の幅と高さを調べて、独自の値に置き換えることで取得できます。また、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

そして強打!動いた!私が書いた

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

私のヘッダーに、それはすべてのビューポートでうまく調整されました。

しかし、それはどのように機能しますか?

ここに定数が必要です。100vwビューポートの全幅を意味し、私の目標は、いくつかのパディングを伴う全幅ヘッダーを確立することでした。

比率。1つのビューポートで幅と高さを取得すると、比率を試すことができます。比率を使用すると、他のビューポートの幅での高さを把握できます。それらを手で計算すると、かなりの時間がかかり、少なくとも多くの帯域幅を必要とするため、適切な答えではありません。

結論

なぜ誰もこれを理解しておらず、CSSをいじることは不可能だと言う人もいるのではないでしょうか。要素の調整にJavaScriptを使用したくないので、さらに掘り下げることなくJavaScript(およびjQueryを忘れる)の回答を受け入れません。全体として、これが理解できたことは良いことであり、これはWebサイト設計における純粋なCSS実装への1つのステップです。

私はテキストに異常な慣習があることをお詫びします。私は英語のネイティブスピーカーではなく、スタックオーバーフローの回答を書くのもまったく新しいです。

また、一部のブラウザには邪悪なスクロールバーがあることにも注意してください。たとえば、Firefoxを使用しているときに100vw、スクロールバーの下(コンテンツが展開できない場所)に広がるビューポートの全幅を意味することに気づきました。そのため、全幅のテキストは注意深くマージンをとる必要があり、多くのブラウザーとデバイスでテストすることが望ましいです。


13
このソリューションは、(1)フォントがわかっている、(2)フォントがユーザーのデバイスで使用できる、(3)テキストが常に同じである場合にのみ機能します。これは非常に限られたユースケースになります。
Andrei

私のコンテナがたとえば640pxで16:9の比率で修正されている場合はどうなりますか?どの計算を書くべきですか?
ペリーミモン

1
コンテナの幅xは640pxで、比率はr16:9なので、 x = 640px, r = 16 / 9, y = x / r = 640px / (16 / 9) = 360px
hegez

注:これは、実際にテキストのサイズが16:9である場合にのみ機能します。これは奇妙な状況です。おそらく、もう一度答えを読むことが役立つかもしれません。また、これはワンライナーでのみ機能します。
hegez

正直に言うと、「一部のビューポートでは適切に調整された比率です。320ピクセルを使用したため、高さが24ピクセル、幅が224ピクセルになったため、比率は9.333 ...または28/3です」比率について説明することをお勧めしますもうちょっと。比率は何を表していますか?
3limin4t0r

28

この問題には大きな哲学があります。

最も簡単な方法は、ボディに特定のフォントサイズを指定することです(私は10をお勧めします)。その後、他のすべての要素のフォントがemまたはになりremます。それらの単位を理解するための例を挙げましょう。 Em常にその親を基準にしています:

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 常に体に相対的です:

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

次に、コンテナの幅に応じてfont-sizeを変更するスクリプトを作成できます。しかし、これは私がお勧めするものではありません。たとえば、900ピクセルの幅のコンテナーでpは、12ピクセルのfont-sizeの要素があるとしましょう。そして、あなたの考えでは、4ピクセルのフォントサイズで300ピクセル幅のコンテナになるでしょう。下限がある必要があります。

他の解決策は、メディアクエリを使用することです。これにより、異なる幅のフォントを設定できます。

しかし、私がお勧めする解決策は、それを支援するJavaScriptライブラリを使用することです。そして、これまでに見つけたfittext.js


6
remユニットは、意味、ルート要素に相対的であるhtml要素ではなく、body要素。DOMのルート要素はhtmlタグです。developer.mozilla.org/en-US/docs/Web/CSS/length .. remは常にhtmlタグに相対的です。これはルートエレメントであり、bodyタグではありません..しかし、良い答えです:)
Jonathan Marzullo

fittext.jsは仕事を完了します、私はその解決策をお勧めします!
Jacek Dziurdzikowski

FitTextは私にとって勝者でした。いくつかの代替案を試しましたが、これは最も単純で、Drupal / Backdrop CMSとうまく統合されているように見えました。github.com/davatron5000/FitText.js
補助Joel

23

これが関数です:

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

次に、すべてのドキュメントの子要素のフォントサイズをemまたはに変換します%

次に、このようなものをコードに追加して、基本フォントサイズを設定します。

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

http://jsfiddle.net/0tpvccjt/


1
これまでのところ、これが最良のソリューションです。
短くて

悪い習慣と非常に非効率的
ジャックギ

@tntrox今日と同じくらい非効率的ですが、4年前ははるかに非効率的でした。より良い代替案の代わりに、私はこの答えを拒否します。はい、IEをサポートするには、Javascriptが必要です。しかし、これほどひどいJavaScriptは必要ありません。
ジャックギフィン

3
私の無知がここに現れていると思います。しかし、なぜ上記はひどいのですか?

ひどいとは思いません。読みやすくするために、書式を少し変更することをお勧めします。少なくとも、各変数を別々の行に配置します。return this関数の最後にある必要はないかもしれません。パフォーマンスのために、ドラッグ時に再描画されないようにonresizeをデバウンスすることもできます。これはかなり単純なコードなので、誰かが少しの努力で改善されたソリューションをベースにすることができます。
Mnebuerquo

19

JavaScript なしでこれを行う方法があります!

インラインSVG画像を使用できます。インラインの場合、SVGでCSSを使用できます。この方法を使用すると、SVG画像がコンテナーサイズに応答することを覚えておく必要があります。

次の解決策を試してください...

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

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

もっと派手なものが欲しいですか?

SVG画像を使用すると、形やジャンクを使ってクールなこともできます。スケーラブルテキストのこの優れた使用例を確認してください...

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


4
このソリューションは、vwサイジングで受け入れられているものと同じです。テキストを変更すると、すべてが範囲外になります。
N69S

14

これは非常に実用的ではないかもしれませんが、div /ページのサイズを読み取るためにリッスン/ループ(間隔)するJavaScriptなしで、フォントを親の直接の関数にしたい場合は、それを行う方法があります。iframe。

iframe内のすべてのものは、iframeのサイズをビューポートのサイズと見なします。したがって、コツは、幅をテキストにしたい最大幅で、高さが最大高さ*特定のテキストのアスペクト比に等しいiframeを作成することです。

ビューポートユニットはテキストの親ユニットと一緒に配置できないという制限を別にして(%サイズが他の人と同じように動作するなど)、ビューポートユニットは非常に強力なツールを提供します:最小/最大の寸法を取得できます。他のどこにもそれを行うことはできません-言うことはできません...このdivの高さを親の幅にする*何か。

そうは言っても、トリックはvminを使用し、iframeサイズを設定して、[fraction] *全高が高さを制限するディメンションである場合は適切なフォントサイズ、[fraction] *全幅がwidthが限界寸法。これが高さが幅とアスペクト比の積でなければならない理由です。

私の特定の例では、

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

この方法の小さな問題は、iframeのCSSを手動で設定する必要があることです。CSSファイル全体を添付すると、多くのテキスト領域で多くの帯域幅を消費します。それで、私がしたいことは、CSSから直接必要なルールを添付することです。

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

CSSルール/テキスト領域に影響するすべてのCSSルールを取得する小さな関数を記述できます。

JavaScriptを循環させたり聞いたりせずにそれを行う別の方法は考えられません。真の解決策は、親コンテナの関数としてスケールのテキストへの道を提供するために、ブラウザのためになるも同じVMIN / VMAXタイプの機能を提供します。

JSFiddle:https ://jsfiddle.net/0jr7rrgm/3/ (一度クリックすると赤い四角がマウスにロックされ、もう一度クリックすると解放されます)

フィドルのほとんどのJavaScriptは、私のカスタムクリックアンドドラッグ機能です。


@quemeful 「new」「shiny」(ドラムロールをお願いします...)srcdoc属性を導入した場合はそうではありません。jsfiddle.net / wauzgob6
Jack Giffin

9

vwem&co を使用します。確かに機能しますが、IMOは常に微調整のために人間のタッチが必要です。

これは、@ tnt-roxの回答に基づいて書いた、人間のタッチを自動化しようとするスクリプトです。

$('#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>

基本的にフォントサイズを縮小し、1em最大幅に達するまで0.1ずつ増加します。

JSFiddle


1
ems人間のタッチと垂直方向のリズムが必要であることを認める人のための+1 は、一種の魔術ではありません。
serraosays

7

100%はベースフォントサイズを基準にしています。これを設定していない場合は、ブラウザのユーザーエージェントのデフォルトになります。

あなたが望んでいる効果を得るために、私はJavaScriptコードを使用して、ウィンドウのサイズを基準にして基本フォントサイズを調整します。


7

CSS内で、これを下部に追加して、デザインが壊れ始めた場所の幅を320ピクセルに変更します。

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

        body { font-size: 1em; }

    }

次に、フォントサイズを「px」または「em」で指定します。


7

私の独自のjQueryベースのソリューションは、コンテナーの高さが大幅に増加する(つまり、改行される)まで、フォントサイズを徐々に大きくすることで機能します。

とてもシンプルですが、かなりうまく動作し、非常に使いやすいです。使用されているフォントについて何も知る必要はありません。すべてがブラウザによって処理されます。

あなたはそれをhttp://jsfiddle.net/tubededentifrice/u5y15d0L/2/で遊ぶことができます

魔法はここで起こります:

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
このスクリプトはすべてのサイズ変更イベントおよび/または方向の変更で実行されるため、これを使用することはお勧めしません。JavaScriptベースのソリューションを使用する代わりに、上記のようなCSSベースのソリューションを探します。
Pilatus

1
サイズ変更と向きの変更は「まれな」イベントであり、ここではパフォーマンスの問題はありません。必要に応じて、イベントにバインドしないでください(応答しないWebサイトなどで、コンテナーのサイズが変更されない場合など)。CSSソリューションは、このソリューションのように(フォントの幅など)何も考えずに機能するわけではありません。
Vincent、

私はあなたの答えをjQuery関数としてラップしました。最大許容高さ、最小および最大フォントサイズを受け取ります。jsfiddle.net/oriadam/qzsy760kを
oriadam



6

font-sizeの代わりにCSS変換を使用した簡単なスケール関数を用意しました。コンテナー内で使用でき、メディアクエリなどを設定する必要はありません。

ブログ投稿: 全幅CSS&JSスケーラブルヘッダー

コード:

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

作業デモ:https : //codepen.io/maciejkorsan/pen/BWLryj


OPはCSSソリューションを探していると思います。
m02ph3u5 2017年

5

CSS変数を使用する

CSS変数についてはまだ誰も言及していません。この方法が私にとって最も効果的でした。

モバイルユーザーの画面の幅の100%であるmax-widthが800pxのページの列があるとします。そのため、デスクトップでは、列の両側にスペースがあります。これをページの上部に配置します。

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

そして今、あなたvwはあなたのフォントのサイズを設定するために(組み込みユニットの代わりに)その変数を使うことができます。例えば

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

これは純粋な CSSアプローチではありませんが、かなり近いものです。



5

私の問題も同様でしたが、見出し内のテキストのスケーリングに関連していました。私はFit Fontを試しましたが、テキストフローのように少し異なる問題を解決していたため、結果を得るにはコンプレッサーを切り替える必要がありました。

だから私はあなたが持っているoverflow: hiddenと仮定して、フォントサイズをコンテナに合うように縮小する独自の小さなプラグインを書きました、そしてwhite-space: nowrapそれでフォントを最小に縮小しても完全な見出しを表示することができない場合でも、それは表示できるものを切り捨てるだけです。

(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

芸術的には、文字数に関係なく、2行以上のテキストを同じ幅に収める必要がある場合は、素晴らしいオプションがあります。

動的な解決策を見つけるのが最善です。そのため、入力されたテキストはすべて、素晴らしい表示になります。

どのようにアプローチするか見てみましょう。

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>

最初の行の幅(els[0].clientWidth)とフォントサイズ(parseFloat(window.getComputedStyle(els[0],null).getPropertyValue("font-size")))を参照として取得し、それに応じて後続の行のフォントサイズを計算するだけです。


4

ビューポートのサイズはこの問題の解決策ではないため、fitTextプラグインを使用してみてください。

ライブラリを追加するだけです:

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

そして、テキストの係数を設定することにより、正しいフォントサイズを変更します:

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

テキストの最大値と最小値を設定できます。

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

これは大きな表示テキストにのみ役立ち、段落には推奨されません。
Shiv

3

私のコードを見てください。それはそこfont size smallerfit何でもします。

しかし、これは良いユーザーエクスペリエンスにつながらないと思います

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

結果


2

JavaScriptフォールバック(または唯一のソリューション)として、私のjQuery Scalemプラグインを使用できます。これにより、referenceオプションを渡すことにより、親要素(コンテナー)を基準にしてスケーリングできます。


2

誰かに役立つ場合、このスレッドのほとんどの解決策は、テキストを複数行に折り返してeを形成することでした。

しかし、私はこれを見つけました、そしてそれはうまくいきました:

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

使用例:

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


2

常にこの属性を持つ要素があります:

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

または

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

全画面表示にすると、既にスケール変数が計算されているはずです(スケール> 1またはスケール= 1)。次に、フルスクリーンで:

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

小さなコードでうまく動作します。


2

ダイナミックテキストの場合、このプラグインは非常に便利です。

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

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

そしてスクリプト:

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

2

これは私のために働きました:

`font-size:10px`の設定から得られた幅/高さに基づいて、フォントサイズを概算しようとします。基本的には、「 `font-size:10px`を使用して幅20ピクセル、高さ11ピクセルの場合、幅50ピクセル、高さ30ピクセルのコンテナーを計算するための最大フォントサイズは何ですか?」

答えは二重比率システムです:

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

Xは幅に一致するフォントサイズ、Yは高さに一致するフォントサイズです。最小値を取る

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

注意:関数の引数は、span要素またはその親よりも小さい要素である必要があります。そうでない場合、子と親の両方に同じ幅/高さの関数があると失敗します。



1

font-sizeをウィンドウではなくコンテナに合わせるresizeFont()には、この質問で共有した関数を参照してください(他の回答の組み合わせ、そのほとんどはすでにここにリンクされています)。を使用してトリガーされwindow.addEventListener('resize', resizeFont);ます。

バニラJavaScript:コンテナーに合わせてfont-awesomeのサイズを変更

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

おそらくvw / vhをフォールバックとして使用できるため、動的に割り当てるemか、rem、JavaScriptを使用してユニット化しして、JavaScriptが無効になっている場合にフォントがウィンドウに合わせてスケーリングされるようにします。

.resizeスケーリングするテキストを含むすべての要素にクラスを適用します。

ウィンドウサイズ変更イベントリスナーを追加する前に関数をトリガーします。次に、コンテナに収まらないテキストは、ページのロード時およびサイズ変更時に縮小されます。

注:デフォルトでは、font-sizeどちらかに設定する必要がありますemremまたは%適切な結果を達成するために。


1

HTML

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

font-sizeを最大化するJavaScriptコード:

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`;
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.