Ответ 1
Проблема заключается в порядке выполнения Javascript. initPictures()
должен быть выполнен перед проверкой ширины тела. Fiddle
По мере развития этого вопроса собственно название должно быть: Разница в ширине тела при загрузке страницы.. Это также связано с изменением размеров изображений на странице. Если мы удалим фотографии, разница исчезнет.
Обратите внимание, что этот вопрос не требует практического решения (я мог бы просто задержать выполнение script с помощью setTimeout(), и проблема будет решена). Я спрашиваю, потому что я хотел бы понять технические аспекты этого поведения.
При написании script для ответа здесь, на SO, я обнаружил странную разницу в высоте элемента, если рассчитывается при загрузке страницы или позже.
Здесь фрагмент:
document.initPictures = function() {
$('.resizeMe').css({
'height': $('#theContainer .col-sm-6').eq(1).height() + 6,
'display': 'flex',
'flex-direction': 'column',
'transition': 'height .4s cubic-bezier(0.55, 0, 0.55, 0.2)'
});
$('.resizeMe img').each(function() {
var src = $(this).attr('src');
$('.resizeMe').append('<div style="flex-basis: 50%; background-image: url(' + src + '); background-size:cover; background-position: center center"' + '</div>');
$(this).remove();
})
};
document.resizePictures = function() {
if ($('#theContainer').outerWidth() > 768) {
$('.resizeMe').css({
'height': $('#theContainer .col-sm-6').eq(1).height()
});
} else {
$('.resizeMe').css({
'height': $('.resizeMe').outerWidth()
});
}
};
$(window).resize(function() {
document.resizePictures();
});
document.initPictures();
.main-img {
width: 100%;
height: auto
}
#theContainer {
margin-top: 15px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="#" onclick="location.href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css'; return false;" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
<div class="row-fluid" id="theContainer">
<div class="col-sm-6 resizeMe">
<img class="filler" src="http://www.keenthemes.com/preview/metronic/theme/assets/global/plugins/jcrop/demos/demo_files/image1.jpg" />
<img class="filler" src="http://www.keenthemes.com/preview/metronic/theme/assets/global/plugins/jcrop/demos/demo_files/image2.jpg" />
</div>
<div class="col-sm-6">
<img class="main-img" src="http://joombig.com/demo-extensions1/images/gallery_slider/Swan_large.jpg" />
</div>
Проблема заключается в порядке выполнения Javascript. initPictures()
должен быть выполнен перед проверкой ширины тела. Fiddle
Различие 17px
, которое вы видите, это ширина полосы прокрутки.
Ширина документа неизвестна до тех пор, пока все активы не будут полностью загружены, поэтому он оставляет пространство для возможной полосы прокрутки. На практике это означает, что window.onLoad
будет выполняться только при загрузке всех изображений. Пока событие jQuery ready
срабатывает, как только загружается DOM.
Я создал новый скрипт (http://jsfiddle.net/u7zgz25u/3/), демонстрирующий это поведение. (Чтобы очистить изображения от кеша, просто измените 1 цветов в их URL-адресах).
При просмотре http://jsfiddle.net/o1g5x5m6/20/ (ваш пример без изображений) события ready
и window.onLoad
выполняются (почти) в то же время, до фактического рендеринга, поэтому параметры страницы известны браузеру.
PS:
Я нашел интересный скрипт, демонстрирующий ширину полосы прокрутки, учитываемую рендерингом браузера, несмотря на наличие достаточно большого количества padding-right
: http://jsfiddle.net/9pAcp/2/
В некоторых браузерах реализована задержка рендеринга (например, Документация по Firefox), следовательно, разница между начальной шириной и шириной после загрузки изображений. Если изображения загружаются до начальной задержки рендеринга или нет изображений, браузер может вычислить правильную высоту, однако, если изображения еще не загружены и у них нет известных размеров, браузеру необходимо подождать изображения для загрузки, прежде чем он сможет вычислить их размер. Следовательно, возможная разница между оцененным размером документа (с зарезервированным пространством для полосы прокрутки) и фактическим размером документа после window.onLoad
была вызвана.
Смотрите http://jsfiddle.net/u7zgz25u/4/ для демонстрации того, что происходит, когда вы определяете фиксированную высоту для изображений в HTML. Разницы в 17px больше нет.
У меня нет подтвержденного источника для этого случая, но, как я могу видеть, что какой-то эксперимент возникает проблема с отображением flex.
вы заменяете 2 изображения с реальной высотой с помощью div, которые имеют изображения в качестве backgound и поэтому он потеряет высоту.
Гибкий контейнер recalc высота этих двух разделов изображения, но с некоторыми рендерами проблема, вероятно, вызвана фактом (как пишет комментарий), что полоса прокрутки занимает некоторое пространство.
jQuery вычисляет ширину без полосы прокрутки
$(window).width()
, в то время как эффективную ширину окна просмотра можно увидеть с помощьюwindow.innerWidth
, встроенного в javascript, что на 17px больше ширины jquery.Для некоторой причины рендеринга высота jquery вычисляется с помощью видимой полосы прокрутки, как вы можете видеть в примере ниже, где я заменил ширину тела на
overflow:scroll
.
Я завершил аналогичную работу с этими изменениями, не используя flex-box:
$('.resizeMe,.cover-img').css({
'height': $('#theContainer .col-sm-6').eq(1).height(),
'transition': 'height .4s cubic-bezier(0.55, 0, 0.55, 0.2)'
});
$('.resizeMe img').each(function() {
var src = $(this).attr('src');
$('.resizeMe').append('<div class="cover-img" style="background-image: url(' + src + '); height: '+$(this).height()+'px;"' + '</div>');
$(this).remove();
});
Используя divs с высотами, эффект тот же, но без проблемы аппроксимации.
там jsfiddle с возможным решением.
другой пример без проблемы с отображением, оставляя теги img без замены их div и без вычисления высоты с помощью js: