要素のコンテンツがオーバーフローしているかどうかを確認しますか?


153

要素がオーバーフローしたかどうかを検出する最も簡単な方法は何ですか?

私の使用例は、特定のコンテンツボックスの高さを300pxに制限することです。内部のコンテンツがそれよりも高い場合は、オーバーフローで切り捨てます。しかし、オーバーフローしている場合は「詳細」ボタンを表示したいが、そうでない場合はそのボタンを表示したくない。

オーバーフローを検出する簡単な方法はありますか、それともより優れた方法はありますか?

回答:


86

より多くのコンテンツの識別子のみを表示したい場合は、純粋なCSSでこれを行うことができます。これには純粋なスクロールシャドウを使用します。コツはの使用ですbackground-attachment: local;。あなたのCSSは次のようになります:

.scrollbox {
  overflow: auto;
  width: 200px;
  max-height: 200px;
  margin: 50px auto;

  background:
    /* Shadow covers */
    linear-gradient(white 30%, rgba(255,255,255,0)),
    linear-gradient(rgba(255,255,255,0), white 70%) 0 100%,
    
    /* Shadows */
    radial-gradient(50% 0, farthest-side, rgba(0,0,0,.2), rgba(0,0,0,0)),
    radial-gradient(50% 100%,farthest-side, rgba(0,0,0,.2), rgba(0,0,0,0)) 0 100%;
  background:
    /* Shadow covers */
    linear-gradient(white 30%, rgba(255,255,255,0)),
    linear-gradient(rgba(255,255,255,0), white 70%) 0 100%,
    
    /* Shadows */
    radial-gradient(farthest-side at 50% 0, rgba(0,0,0,.2), rgba(0,0,0,0)),
    radial-gradient(farthest-side at 50% 100%, rgba(0,0,0,.2), rgba(0,0,0,0)) 0 100%;
  background-repeat: no-repeat;
  background-color: white;
  background-size: 100% 40px, 100% 40px, 100% 14px, 100% 14px;
  
  /* Opera doesn't support this in the shorthand */
  background-attachment: local, local, scroll, scroll;
}
<div class="scrollbox">
  <ul>
    <li>Not enough content to scroll</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
  </ul>
</div>


<div class="scrollbox">
  <ul>
    <li>Ah! Scroll below!</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
    <li>6</li>
    <li>7</li>
    <li>8</li>
    <li>9</li>
    <li>10</li>
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
    <li>6</li>
    <li>7</li>
    <li>8</li>
    <li>The end!</li>
    <li>No shadow there.</li>
  </ul>
</div>

http://dabblet.com/gist/2462915にあるコードと例

そしてここで見つけることができる説明:http : //lea.verou.me/2012/04/background-attachment-local/


1
いいアイデアですが、あなたの例では、背景(影)はテキストの背後にあります!
DreamTeK 2018

素晴らしいトリックですが、Chromeでは下部に静的な影のみが表示され、消えることはなく、上部の影も表示されません
Jared

214

要素は、垂直方向、水平方向、またはその両方でオーバーフローする可能性があります。この関数は、DOM要素がオーバーフローした場合にブール値を返します。

function isOverflown(element) {
  return element.scrollHeight > element.clientHeight || element.scrollWidth > element.clientWidth;
}

ES6の例:

const isOverflown = ({ clientWidth, clientHeight, scrollWidth, scrollHeight }) => {
    return scrollHeight > clientHeight || scrollWidth > clientWidth;
}

41
素晴らしい解決策!jQueryのバリアントは$("#element").overflown()次のとおりです(で使用):$.fn.overflown=function(){var e=this[0];return e.scrollHeight>e.clientHeight||e.scrollWidth>e.clientWidth;}
Sygmoral、2013

@micnicこんにちは、私はionic2を使用して同じことをやろうとしています...しかし、関数は常にtrueを返します...角度2で物事を行う別の方法があります
Yasir

@DavidBracoly、この関数は純粋なDOM API用です。Ionic/ Angularの経験はありません。元のDOM要素を取得してこの関数を使用する必要があります
micnic

3
Firefoxのみ:element.addEventListener ("overflow", () => log( "overflow" ), false);参照:オーバーフローイベント
Reza

18

と比較してタスクを実行element.scrollHeightするelement.clientHeight必要があります。

以下は、Element.scrollHeightとElement.clientHeightを説明するMDNの画像です。

スクロールの高さ

クライアントの高さ


2
そうですが、quirksmodeによると、ほとんどの場合に機能し、他の投稿されたソリューションよりもはるかに簡単です。
ベルギ

@Harry:現在のすべてのブラウザ(少なくともデスクトップブラウザ)でサポートされているため、正式に非標準であってもかまいません。
Marat Tanalin

1
ここでは、これらのプロパティは常に同じ値を持っています。
コッポー

7

上記の回答(例:オーバーフローの非表示と高さを使用)を示すマルチパートコードペンを作成しましたが、オーバーフローしたアイテムを展開/折りたたむ方法も示しました

例1:https : //codepen.io/Kagerjay/pen/rraKLB(実際の単純な例、JavaScriptなし、オーバーフローしたアイテムをクリップするためだけ)

例2:https : //codepen.io/Kagerjay/pen/LBErJL(単一のイベントハンドラーは、オーバーフローしたアイテムでさらに表示/表示しない)

例3:https : //codepen.io/Kagerjay/pen/MBYBoJ(オーバーフローしたアイテムの多くの表示/非表示のマルチイベントハンドラー)

以下の例3添付しました。Jade/ Pugを使用しているため、少し冗長になる可能性があります。私が理解しやすくしたコードペンをチェックすることをお勧めします。

// Overflow boolean checker
function isOverflown(element){
  return element.scrollHeight > element.clientHeight || element.scrollWidth > element.clientWidth;
}

// Jquery Toggle Text Plugin
$.fn.toggleText = function(t1, t2){
  if (this.text() == t1) this.text(t2);
  else                   this.text(t1);
  return this;
};

// Toggle Overflow
function toggleOverflow(e){
  e.target.parentElement.classList.toggle("grid-parent--showall");
  $(e.target).toggleText("Show More", "Show LESS");
}

// Where stuff happens
var parents = document.querySelectorAll(".grid-parent");

parents.forEach(parent => {
  if(isOverflown(parent)){
    parent.lastElementChild.classList.add("btn-show");
    parent.lastElementChild.addEventListener('click', toggleOverflow);
  }
})
body {
  background-color: #EEF0ED;
  margin-bottom: 300px;
}

.grid-parent {
  margin: 20px;
  width: 250px;
  background-color: lightgrey;
  display: flex;
  flex-wrap: wrap;
  overflow: hidden;
  max-height: 100px;
  position: relative;
}
.grid-parent--showall {
  max-height: none;
}

.grid-item {
  background-color: blue;
  width: 50px;
  height: 50px;
  box-sizing: border-box;
  border: 1px solid red;
}
.grid-item:nth-of-type(even) {
  background-color: lightblue;
}

.btn-expand {
  display: none;
  z-index: 3;
  position: absolute;
  right: 0px;
  bottom: 0px;
  padding: 3px;
  background-color: red;
  color: white;
}

.btn-show {
  display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section>
  <p>Any grid-parent over 10 child items has a "SHOW MORE" button to expand</p>
  <p>Click "SHOW MORE" to see the results</p>
</section>
<radio></radio>
<div class="wrapper">
  <h3>5 child elements</h3>
  <div class="grid-parent">
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="btn-expand">Show More</div>
  </div>
  <h3>8 child elements</h3>
  <div class="grid-parent">
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="btn-expand">Show More</div>
  </div>
  <h3>10 child elements</h3>
  <div class="grid-parent">
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="btn-expand">Show More</div>
  </div>
  <h3>13 child elements</h3>
  <div class="grid-parent">
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="btn-expand">Show More</div>
  </div>
  <h3>16 child elements</h3>
  <div class="grid-parent">
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="btn-expand">Show More</div>
  </div>
  <h3>19 child elements</h3>
  <div class="grid-parent">
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="btn-expand">Show More</div>
  </div>
</div>


4

次のようになりますか:http : //jsfiddle.net/Skooljester/jWRRA/1/動作しますか?コンテンツの高さをチェックし、それをコンテナの高さと比較するだけです。コードに入力できる値よりも大きい場合は、[もっと見る]ボタンを追加します。

更新:コンテナの上部に[もっと見る]ボタンを作成するコードが追加されました。


3

jQueryを使用している場合は、トリックを試してみてくださいoverflow: hidden。コンテンツを使用して外部divを作成し、内部divを作成します。次に、.height()関数を使用して、内側のdivの高さが外側のdivの高さより大きいかどうかを確認します。動作するかどうかはわかりませんが、試してみてください。


1

jsを使用して、子のoffsetHeight親が親より多いかどうかを確認します。そうである場合は、親がオーバーフローするようにし、さらにdivでオーバーフローさscroll/hidden/autodisplay:blockます。


1

オフセットの親を基準にして境界を確認できます。

// Position of left edge relative to frame left courtesy
// http://www.quirksmode.org/js/findpos.html
function absleft(el) {
  var x = 0;
  for (; el; el = el.offsetParent) {
    x += el.offsetLeft;
  }
  return x;
}

// Position of top edge relative to top of frame.
function abstop(el) {
  var y = 0;
  for (; el; el = el.offsetParent) {
    y += el.offsetTop;
  }
  return y;
}

// True iff el's bounding rectangle includes a non-zero area
// the container's bounding rectangle.
function overflows(el, opt_container) {
  var cont = opt_container || el.offsetParent;
  var left = absleft(el), right = left + el.offsetWidth,
      top = abstop(el), bottom = top + el.offsetHeight;
  var cleft = absleft(cont), cright = cleft + cont.offsetWidth,
      ctop = abstop(cont), cbottom = ctop + cont.offsetHeight;
  return left < cleft || top < ctop
      || right > cright || bottom > cbottom;
}

これを要素に渡すと、その境界が完全にコンテナ内にあるかどうかがわかり、明示的なコンテナが提供されていない場合は、デフォルトで要素のオフセットの親になります。それは使用しています


1

考慮すべきもう1つの問題は、JSが利用できないことです。漸進的なエンチャントや優雅な劣化について考えてみてください。私はお勧めします:

  • デフォルトで「もっとボタン」を追加する
  • デフォルトでオーバーフロールールを追加する
  • element.scrollHeightをelement.clientHeightと比較した後、ボタンを非表示にし、必要に応じてJSでCSSを変更します。

1

ラッパーと内部コンテンツdivの違いを測定するために、overflow:hiddenおよびJQuery height()でラッパーdivを使用して要素がオーバーフローしているかどうかを判断するためのフィドルがあります。

outers.each(function () {
    var inner_h = $(this).find('.inner').height();
    console.log(inner_h);
    var outer_h = $(this).height();
    console.log(outer_h);
    var overflowed = (inner_h > outer_h) ? true : false;
    console.log("overflowed = ", overflowed);
});

ソース: jsfiddle.netのフレームワークと拡張機能


1

これは私のために働いたjQueryソリューションです。clientWidthなどは機能しませんでした。

function is_overflowing(element, extra_width) {
    return element.position().left + element.width() + extra_width > element.parent().width();
}

これが機能しない場合は、要素の親が適切な幅であることを確認してください(個人的には、parent().parent())positionは親を基準にして使用する必要がありました。extra_width要素( "タグ")には少し時間がかかる画像が含まれているため、これも含めました。ロードしますが、関数呼び出し中は幅がゼロになり、計算が損なわれます。これを回避するには、次の呼び出しコードを使用します。

var extra_width = 0;
$(".tag:visible").each(function() {
    if (!$(this).find("img:visible").width()) {
        // tag image might not be visible at this point,
        // so we add its future width to the overflow calculation
        // the goal is to hide tags that do not fit one line
        extra_width += 28;
    }
    if (is_overflowing($(this), extra_width)) {
        $(this).hide();
    }
});

お役に立てれば。


0
setTimeout(function(){
    isOverflowed(element)           
},500)

function isOverflowed(element){
    return element.scrollHeight > element.clientHeight || element.scrollWidth > element.clientWidth;
}

これは私のために働いた。ありがとうございました。


3
これはマイクの回答とどう違うのですか?
Cautionnow1

0

答えの代わりにjqueryを使用するには、[0]キーを使用して次のような生の要素にアクセスします。

if ($('#elem')[0].scrollHeight > $('#elem')[0].clientHeight){

0

カプセル化の理由でElementを拡張しました。マイクの答えから。

/*
 * isOverflowing
 * 
 * Checks to see if the element has overflowing content
 * 
 * @returns {}
 */
Element.prototype.isOverflowing = function(){
    return this.scrollHeight > this.clientHeight || this.scrollWidth > this.clientWidth;
}

このように使う

let elementInQuestion = document.getElementById("id_selector");

    if(elementInQuestion.isOverflowing()){
        // do something
    }
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.