Проверьте, не переполняется ли содержимое элемента? - PullRequest
113 голосов
/ 17 февраля 2012

Какой самый простой способ определить, был ли переполнен элемент?

Мой пример использования: я хочу ограничить определенное поле для контента высотой 300 пикселей.Если внутреннее содержимое выше этого, я обрезаю его переполнением.Но если он переполнен, я хочу показать кнопку «больше», но если нет, я не хочу показывать эту кнопку.

Есть ли простой способ обнаружить переполнение или есть лучший метод?

Ответы [ 13 ]

151 голосов
/ 03 марта 2012

Эта функция вернет вам логическое значение, если элемент DOM переполнен:

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

Элемент может быть переполнен по вертикали, по горизонтали или по обеим сторонам

38 голосов
/ 16 декабря 2015

Если вы хотите показать только идентификатор для большего количества контента, то вы можете сделать это с помощью чистого 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;
}

Код и пример вы можете найти на http://dabblet.com/gist/2462915

И объяснение вы можете найти здесь: http://lea.verou.me/2012/04/background-attachment-local/.

12 голосов
/ 17 февраля 2012

Сравнение element.scrollHeight с element.clientHeight должно выполнить задачу.

Ниже приведены изображения из MDN, поясняющие Element.scrollHeight и Element.clientHeight.

Scroll Height

Client Height

4 голосов
/ 17 февраля 2012

Будет ли что-то вроде этого: http://jsfiddle.net/Skooljester/jWRRA/1/ работать?Он просто проверяет высоту содержимого и сравнивает его с высотой контейнера.Если он больше, чем вы можете вставить в код, чтобы добавить кнопку «Показать больше».

Обновление: Добавлен код для создания кнопки «Показать больше» в верхней части контейнера..

3 голосов
/ 11 июля 2018

Я сделал многокомпонентную ручку, демонстрирующую приведенные выше ответы (например, используя переполнение скрытого и высоты), а также то, как вы бы раскрыли / свернули переполненные элементы

Пример 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, так что это может быть немного многословно.Я предлагаю проверить codepens, которые я сделал, это проще понять.

// 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>
3 голосов
/ 17 февраля 2012

Если вы используете jQuery, вы можете попробовать хитрость: создайте внешний div с overflow: hidden и внутренний div с содержимым.Затем используйте функцию .height(), чтобы проверить, больше ли высота внутреннего элемента div, чем высота внешнего элемента div.Я не уверен, что это сработает, но попробуйте.

1 голос
/ 01 мая 2015

Это решение 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();
    }
});

Надеюсь, это поможет.

1 голос
/ 11 апреля 2013

Вот скрипка для определения того, был ли элемент переполнен, используя 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 голос
/ 27 февраля 2012

Другая проблема, которую вы должны рассмотреть, - это недоступность JS. Подумайте о прогрессивном очаровании или постепенном ухудшении. Я бы предложил:

  • добавление "кнопки" по умолчанию
  • добавление правил переполнения по умолчанию
  • скрывающая кнопка и при необходимости модификации CSS в JS после сравнения element.scrollHeight с element.clientHeight
1 голос
/ 17 февраля 2012

используйте js, чтобы проверить, больше ли offsetHeight у ребенка, чем у родителей ... если это так, сделайте так, чтобы родители переполнились scroll/hidden/auto, в зависимости от того, что вы хотите, а также display:block на большем делении.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...