テキスト幅の計算


101

jQueryを使用してテキストの幅を計算しようとしています。よくわかりませんが、間違いがあります。

だから、これがコードです:

var c = $('.calltoaction');

var cTxt = c.text();

var cWidth =  cTxt.outerWidth();

c.css('width' , cWidth);

それで、そのコードはどのように機能していませんか?別に何をする必要がありますか?
Sixten Otto

回答:


142

これは私にとってよりうまくいきました:

$.fn.textWidth = function(){
  var html_org = $(this).html();
  var html_calc = '<span>' + html_org + '</span>';
  $(this).html(html_calc);
  var width = $(this).find('span:first').width();
  $(this).html(html_org);
  return width;
};

4
+1-これは、brainreavisのソリューションのような包含ブロック要素だけでなく、テキストを本当に測定します。
Ben

スリック。+1。後の3行目にセミコロン'</span>'がないようですが、違いはないようです(FF9でそれを使用しても使用しなくても)。
shmeeps

21
ただし、これには注意してください...このメソッドは、子要素のイベントのバインドを解除します。
brianreavis

この関数をさまざまな方法で使用しようとしましたが、nullが返され続けます。誰かがこの関数が実際に使用される方法の構文を投稿していただけませんか?jQueryオブジェクトで.textWidth()関数を実行しますか?この関数にテキストを渡しますか?関数をjQuery関数(つまり、$。textWidth(jqObject))として実行しますか?これらのオプションはどれも機能していないようです。おかげで...
moosefetcher 2013年

2
@moosefetcher $(selector).textWidth(); Learn.jquery.com/plugins/basic-plugin-creation/…を
uesports135 '21

89

投稿された他の関数よりも優れている関数は次のとおりです

  1. 短いです
  2. 渡すときにそれは動作します<input><span>または"string"
  3. 既存のDOM要素を再利用するため、頻繁に使用する場合は高速です。

デモ:http : //jsfiddle.net/philfreo/MqM76/

// Calculate width of text from DOM element or string. By Phil Freo <http://philfreo.com>
$.fn.textWidth = function(text, font) {
    if (!$.fn.textWidth.fakeEl) $.fn.textWidth.fakeEl = $('<span>').hide().appendTo(document.body);
    $.fn.textWidth.fakeEl.text(text || this.val() || this.text()).css('font', font || this.css('font'));
    return $.fn.textWidth.fakeEl.width();
};

1
うわー!純粋な素晴らしさ!
ミシェルトリアナ2014

3
素晴らしい解決策、受け入れるべき答えだと思います!ありがとう、仲間!
Ilia Rostovtsev 2014年

素晴らしい!シンプルでクリーン。
Carey Estes、2014

これは良いことですが、スペースを扱いません。このソリューションの拡張については、@ edsioufiの回答を参照してください。
Badgerspot 2014

要素内に非表示のテキストがある場合、幅がゆがみます。これを説明するには、テキストの幅を計算する前に、非表示のノードを必ず削除してください。非表示のノードを安全に削除するには、おそらく最初にクローンを作成し、そこで削除する必要があります。
thdoan 14

36

私の解決策

$.fn.textWidth = function(){
    var self = $(this),
        children = self.children(),
        calculator = $('<span style="display: inline-block;" />'),
        width;

    children.wrap(calculator);
    width = children.parent().width(); // parent = the calculator wrapper
    children.unwrap();
    return width;
};

基本的にはルーンのに比べて改善が、それは使用されません.htmlので、軽く


Ajarnゲルハルト:答えとしてこれを掲示あなたが不足しているので、これはIE8で動作していない/の閉じ括弧の前に<span>:タグcalculator = $('<span style="display: inline-block;" />'),
ペトル・R.

1
測定している要素の下に子要素がある場合、これはnullを返すようです。子要素なしで動作させることはできますか?jsfiddle.net/h22tj/41を
Casper

+1-unwrap()があることを知りませんでした。
Orwellophile 2013

Chromeでは常にnullを返します。
emeraldhieu 2014年

12

textWidth受け入れ回答に提供する機能とstring、引数としては、(それらがダミー容器でレンダリングされていない)空白を先頭と末尾を考慮しないであろう。また、テキストにHTMLマークアップが含まれている場合は機能しません(サブストリング<br>は出力を生成せず&nbsp;、1つのスペースの長さを返します)。

これは、textWidthを受け入れる関数の問題にすぎませんstring。DOM要素が指定さ.html()れ、その要素で呼び出された場合、おそらくそのようなユースケースでこれを修正する必要はないからです。

ただし、たとえば、テキストの幅を計算しinputて、ユーザーが入力するテキスト要素の幅を動的に変更する場合(私の現在の使用例)、おそらく先頭と末尾のスペースを&nbsp;文字列に置き換えて文字列をエンコードします。 htmlに。

私はphilfreoのソリューションを使用したので、これを修正したバージョン(追加に関するコメント付き)を次に示します。

$.fn.textWidth = function(text, font) {
    if (!$.fn.textWidth.fakeEl) $.fn.textWidth.fakeEl = $('<span>').appendTo(document.body);
    var htmlText = text || this.val() || this.text();
    htmlText = $.fn.textWidth.fakeEl.text(htmlText).html(); //encode to Html
    htmlText = htmlText.replace(/\s/g, "&nbsp;"); //replace trailing and leading spaces
    $.fn.textWidth.fakeEl.html(htmlText).css('font', font || this.css('font'));
    return $.fn.textWidth.fakeEl.width();
};

ありがとう。あなたの答えは最も価値があります。
Vishal 2014

1
奇妙なことに、私がこれを試したとき、それは正しくコピーされませんでしたfont-size。それが機能するように追加css('font-size'), this.css('font-size'))する必要がありました。なぜそれfontだけでその価値がコピーされないのですか?
コーディング終了

@GoneCodingこれらの追加機能はどこに追加しましたか?
webmagnets 2018

@webmagnets:既存の.css方法と同じ場所ですが、角かっこが間違っているようです。する必要がありますcss('font-size', this.css('font-size'))
Gone Coding

11

jQueryの幅関数は、ボックスモデルの不整合が原因でテキストの幅を決定しようとすると、少し不審になる場合があります。確実な方法は、要素内にdivを挿入して実際のテキスト幅を決定することです。

$.fn.textWidth = function(){
  var sensor = $('<div />').css({margin: 0, padding: 0});
  $(this).append(sensor);
  var width = sensor.width();
  sensor.remove();
  return width;
};

このミニプラグインを使用するには、単純に:

$('.calltoaction').textWidth();

1
これはテキストではなくブロックの幅を与えませんか?
Josh Rickard、2010年

-1これは確かに、テキストの幅ではなくボックスの幅を測定しているようです。
Nathan Arthur

1
単にdivの代わりにスパンを使用して幅の問題を修正しませんか?もしそうなら、この関数は受け入れられた答えよりも少し優れています。
Josh、

@ジョシュ:あなたがそれをaに置き換えると、spanあなたはただゼロを得ます。H2親要素が非表示のオーバーフローを持っているでこのソリューションを試してみましたが、テキストの切り捨てられた長さしか得られません。おそらく、これがされる方法の説明は仕事になってはそれがより良い仕事に役立つでしょうか?
コーディングを終了

8

私はこのソリューションがうまく機能し、サイジング前に元のフォントを継承することがわかりました:

$.fn.textWidth = function(text){
  var org = $(this)
  var html = $('<span style="postion:absolute;width:auto;left:-9999px">' + (text || org.html()) + '</span>');
  if (!text) {
    html.css("font-family", org.css("font-family"));
    html.css("font-size", org.css("font-size"));
  }
  $('body').append(html);
  var width = html.width();
  html.remove();
  return width;
}

1
私はこれを使用してしまいましたが、追加しましたorg.css("font-weight")。また、そのif(!text)部分は直感的ではないと思います。たとえばjQuery("#someContainer").textWidth("Lorem ipsum")、特定のコンテナに適用された場合の「Lorem ipsum」のテキスト幅を知りたいと思います。
Sleavely

8

テキストを保持している要素の幅が固定されている場合に備えて、RuneもBrainも機能しませんでした。オカメラに似たことをした。より少ないセレクターを使用します。

編集:それはおそらくfont-size次のコードがhtmlCalc要素を挿入するbodyので、親の関係に関する情報を失うので、relativeを使用する要素では機能しません。

$.fn.textWidth = function() {
    var htmlCalc = $('<span>' + this.html() + '</span>');
    htmlCalc.css('font-size', this.css('font-size'))
            .hide()
            .prependTo('body');
    var width = htmlCalc.width();
    htmlCalc.remove();
    return width;
};

これは、IE8をサポートしている私にとって最良のソリューションであり、プロセス中の要素へのバインドを壊すことはありません!どうも。
ouija

注:jQuery拡張メソッドでthisは、はすでにjQueryオブジェクトなので$(this)、冗長です。
コーディング

計算された幅が小さすぎるという点で、これは私にとってはうまくいきませんでした。受け入れられた答えは正しく機能しました
PandaWood

5

選択ボックス内のテキストを使用してこれを実行しようとしている場合、またはこれらの2つが機能していない場合は、代わりにこれを試してください。

$.fn.textWidth = function(){
 var calc = '<span style="display:none">' + $(this).text() + '</span>';
 $('body').append(calc);
 var width = $('body').find('span:last').width();
 $('body').find('span:last').remove();
 return width;
};

または

function textWidth(text){
 var calc = '<span style="display:none">' + text + '</span>';
 $('body').append(calc);
 var width = $('body').find('span:last').width();
 $('body').find('span:last').remove();
 return width;
};

最初にテキストを取得したい場合


4

間違っているのは、jQueryオブジェクトではなく単純な文字列であるcTxtでメソッドを呼び出しているということです。cTxtは実際には含まれているテキストです。


2

h1pのようなテキスト要素を参照している場合、.children()は空のセットを返すため、Nico'sに少し変更を加えます。したがって、jQueryオブジェクトにメソッドを作成しているので、代わりに.contents()を使用、$(this)の代わりにthisを使用します。

$.fn.textWidth = function(){
    var contents = this.contents(),
        wrapper  = '<span style="display: inline-block;" />',
        width    = '';

    contents.wrapAll(wrapper);
    width = contents.parent().width(); // parent is now the wrapper
    contents.unwrap();
    return width;
    };

1

ゴーストを2日間追跡した後、テキストの幅が正しくない理由を理解しようとしたところ、幅の計算を停止するテキスト文字列の空白が原因であることがわかりました。

したがって、別のヒントは、空白が問題を引き起こしているかどうかを確認することです。使用する

&nbsp;

改行しないスペースで、それが修正されるかどうかを確認します。

人々が提案した他の関数もうまく機能しますが、問題を引き起こしたのは空白文字でした。


white-space: nowrapこれを回避するには、インラインCSSに一時的に追加するだけです。
コーディングを終了

1

特定の要素内のテキストノードと要素の組み合わせの幅を決定しようとしている場合は、wrapInner()ですべてのコンテンツをラップする必要がありますで、幅を計算して。

*注意:デフォルトでは提供されていないため、jwrapを拡張してunwrapInner()関数を追加する必要もあります。

$.fn.extend({
  unwrapInner: function(selector) {
      return this.each(function() {
          var t = this,
              c = $(t).children(selector);
          if (c.length === 1) {
              c.contents().appendTo(t);
              c.remove();
          }
      });
  },
  textWidth: function() {
    var self = $(this);
    $(this).wrapInner('<span id="text-width-calc"></span>');
    var width = $(this).find('#text-width-calc').width();
    $(this).unwrapInner();
    return width;
  }
});

.wrapInnerの+1。おそらくご存じのとおり、jQueryで純粋なテキスト要素を処理するのは地獄です。適用可能な他のjQueryメソッドがある場合は、お知らせください。私は.get(0).childrenに頼らなければなりませんでしたが、それはきれいではありません。
Orwellophile 2013

1

@philfreoの答えを拡張してください:

通常はテキストが広くなる傾向があるためtext-transform、をチェックする機能を追加しましたtext-transform: uppercase

$.fn.textWidth = function (text, font, transform) {
    if (!$.fn.textWidth.fakeEl) $.fn.textWidth.fakeEl = $('<span>').hide().appendTo(document.body);
    $.fn.textWidth.fakeEl.text(text || this.val() || this.text())
        .css('font', font || this.css('font'))
        .css('text-transform', transform || this.css('text-transform'));
    return $.fn.textWidth.fakeEl.width();
};

0
var calc = '<span style="display:none; margin:0 0 0 -999px">' + $('.move').text() + '</span>';

0

getColumnWidth()を呼び出して、テキストのwithを取得します。これは完璧に機能します。

someFile.css
.columnClass { 
    font-family: Verdana;
    font-size: 11px;
    font-weight: normal;
}


function getColumnWidth(columnClass,text) { 
    tempSpan = $('<span id="tempColumnWidth" class="'+columnClass+'" style="display:none">' + text + '</span>')
          .appendTo($('body'));
    columnWidth = tempSpan.width();
    tempSpan.remove();
return columnWidth;
}

注:-インライン.cssが必要な場合は、font-detailsをスタイルのみで渡します。


0

Nicoのコードを自分のニーズに合わせて変更しました。

$.fn.textWidth = function(){
    var self = $(this),
        children = self.contents(),
        calculator = $('<span style="white-space:nowrap;" />'),
        width;

    children.wrap(calculator);
    width = children.parent().width(); // parent = the calculator wrapper
    children.unwrap();
    return width;
};

.contents()を使用しています。.children()が必要なテキストノードを返さないためです。また、返された幅が折り返しの原因となっていたビューポートの幅の影響を受けることもわかったので、white-space:nowrapを使用しています。ビューポートの幅に関係なく正しい幅を取得します。


0
$.fn.textWidth = function(){
        var w = $('body').append($('<span stlye="display:none;" id="textWidth"/>')).find('#textWidth').html($(this).html()[0]).width();
        $('#textWidth').remove();
        console.log(w);
        return w;
    };

ほぼワンライナー。最初のキャラクターの


0

リストにある解決策が100%機能しないため、@ chmurson(@Okameraに基づく)と@philfreoからのアイデアに基づいて、このハイブリッドを考え出しました。

(function ($)
{
    var calc;
    $.fn.textWidth = function ()
    {
        // Only create the dummy element once
        calc = calc || $('<span>').css('font', this.css('font')).css({'font-size': this.css('font-size'), display: 'none', 'white-space': 'nowrap' }).appendTo('body');
        var width = calc.html(this.html()).width();
        // Empty out the content until next time - not needed, but cleaner
        calc.empty();
        return width;
    };
})(jQuery);

ノート:

  • thisjQuery拡張メソッドの内部はすでにjQueryオブジェクトであるため$(this)、多くの例にある追加の要素は必要ありません。
  • ダミー要素をボディに追加するのは1回だけで、再利用します。
  • また、を指定してwhite-space: nowrap、それが単一行として測定されることを保証する必要があります(他のページスタイルに基づく行の折り返しではありません)。
  • これをfont単独で使用することはできず、明示的にコピーfont-sizeする必要もありました。まだ理由がわかりません(まだ調査中です)。
  • これ、そのように入力フィールドをサポートしません@philfreo

0

場合によっては、テキストだけでなくHTMLの幅も追加で高さを測定する必要があります。私は@philfreoの回答を取り入れ、より柔軟で有用なものにしました。

function htmlDimensions(html, font) {
  if (!htmlDimensions.dummyEl) {
    htmlDimensions.dummyEl = $('<div>').hide().appendTo(document.body);
  }
  htmlDimensions.dummyEl.html(html).css('font', font);
  return {
    height: htmlDimensions.dummyEl.height(),
    width: htmlDimensions.dummyEl.width()
  };
}

0

テキストの幅は、親によって異なる場合があります。たとえば、テキストをh1タグに追加すると、divまたはlabelよりも幅が広くなるため、次のようなソリューションを使用します。

<h1 id="header1">

</h1>

alert(calcTextWidth("bir iki", $("#header1")));

function calcTextWidth(text, parentElem){
    var Elem = $("<label></label>").css("display", "none").text(text);
    parentElem.append(Elem);
  var width = Elem.width();
  Elem.remove();
    return width;
}

0

大量のテキストに対する@ rune-kaagaardのようなソリューションで問題が発生しました。私はこれを発見しました:

$.fn.textWidth = function() {
	var width = 0;
	var calc = '<span style="display: block; width: 100%; overflow-y: scroll; white-space: nowrap;" class="textwidth"><span>' + $(this).html() + '</span></span>';
	$('body').append(calc);
	var last = $('body').find('span.textwidth:last');
	if (last) {
			var lastcontent = last.find('span');
			width = lastcontent.width();
			last.remove();
	}
	return width;
};

JSFiddle GitHub


-1

私はあなたが使うべきだと思います $('.calltoaction').val;

また、そのためにクラスの代わりにid(#)を使用します。そのようなクラスが複数ある場合、どのように処理しますか?


はい、ドキュメントには複数あります。なぜidを提案するのですか?
ドム
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.