Проверьте, не переполняется ли содержимое элемента?
Какой самый простой способ обнаружить переполнение элемента?
Мой вариант использования: я хочу ограничить определенную область содержимого до 300 пикселей. Если внутреннее содержимое выше этого, я обрезаю его переполнением. Но если он переполнен, я хочу показать кнопку "больше", но если нет, я не хочу показывать эту кнопку.
Есть ли простой способ обнаружить переполнение или есть лучший способ?
Ответы
Ответ 1
Если вы хотите показать только идентификатор для большего количества контента, то вы можете сделать это с помощью чистого 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 does not 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>
Ответ 2
Элемент может быть переполнен вертикально, горизонтально или обоими. Эта функция вернет вам логическое значение, если элемент 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;
}
Ответ 3
Сравнение element.scrollHeight
с element.clientHeight
должно выполнить задачу.
Ниже приведены изображения из MDN, поясняющие Element.scrollHeight и Element.clientHeight.
![Scroll Height]()
![Client Height]()
Ответ 4
Я сделал многокомпонентную ручку, демонстрирующую приведенные выше ответы (например, используя overflow hidden и height), а также как вы будете расширять/сворачивать переполненные элементы
Пример 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>
Ответ 5
Будет ли что-то вроде этого: http://jsfiddle.net/Skooljester/jWRRA/1/ работать? Он просто проверяет высоту содержимого и сравнивает его с высотой контейнера. Если это больше, чем вы можете добавить код, чтобы добавить кнопку "Показать больше".
Обновление: Добавлен код для создания кнопки "Показать больше" в верхней части контейнера.
Ответ 6
Если вы используете jQuery, вы можете попробовать трюк: сделать внешний div с overflow: hidden
и внутренним div с содержимым. Затем используйте функцию .height()
, чтобы проверить, больше ли высота внутреннего div больше высоты внешнего div. Я не уверен, что это сработает, но попробуй.
Ответ 7
используйте js, чтобы проверить, является ли дочерний элемент offsetHeight
больше, чем родители. Если это так, сделайте родительский переполнения scroll/hidden/auto
в зависимости от того, что вы хотите, а также display:block
для более div..
Ответ 8
Еще одна проблема, которую вы должны рассмотреть, - это недоступность JS. Подумайте о прогрессивном зачаровании или грациозном деградации. Я бы предложил:
- добавление "больше кнопки" по умолчанию
- добавление правил переполнения по умолчанию
- скрытая кнопка и при необходимости изменения CSS в JS после сравнения element.scrollHeight с element.clientHeight
Ответ 9
Вот скрипка для определения того, был ли элемент переполнен с использованием div-оболочки с переполнением: 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
Ответ 10
Это решение 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();
}
});
Надеюсь, что это поможет.
Ответ 11
Вы можете проверить границы относительно родителя смещения.
// 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 bounding rectangle includes a non-zero area
// the container 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;
}
Если вы передадите этот элемент, он скажет вам, находятся ли его границы целиком внутри контейнера и по умолчанию будет относиться к родительскому смещению элемента, если явный контейнер не предоставляется. Он использует
Ответ 12
setTimeout(function(){
isOverflowed(element)
},500)
function isOverflowed(element){
return element.scrollHeight > element.clientHeight || element.scrollWidth > element.clientWidth;
}
Это сработало для меня. Спасибо.
Ответ 13
Альтернативой jquery ответа является использование клавиши [0] для доступа к необработанному элементу, например так:
if ($('#elem')[0].scrollHeight > $('#elem')[0].clientHeight){