Подтвердить что ты не робот

CSS vh единиц внутри iframe

Я пытаюсь использовать единицы CSS vh внутри iframe. Я обнаружил, что они каким-то образом масштабируются до размера iframe. Другими словами, 100vh не является окном. Он установлен на высоту iframe.

Правильно ли это?

Есть ли способ обхода?

4b9b3361

Ответ 1

Я знаю, что это старый вопрос, но по мере продвижения людей к vh подразделению этот вопрос станет гораздо более распространенным.

Чтобы уточнить, вот пример проблемы. У нас есть HTML файл, который загружает iframe:

<!DOCTYPE html>
<html>
<head></head>
<style>
iframe {
    height: 50vh;
    width: 100%;
}
</style>
<body>
    <iframe src="iframe.html"/>
</body>
</html>

И его iframe:

<!DOCTYPE html>
<html>
<head></head>
<style>
div {
    height: 50vh;
    width: 100%;
    background: blue;
}
</style>
<body>
    <div></div>
</body>
</html>

Здесь важно отметить, что и iframe и div элемент iframe's имеют высоту 50vh. Предполагаемое поведение может заключаться в том, что iframe учитывает высоту или ширину области просмотра родительского контекста. Вместо этого результат выглядит так:

enter image description here

То есть высота синего элемента составляет ~ 25% от окна браузера, вместо ожидаемых 50% (100% от iframe). Хотя мы можем пожелать, чтобы iframe уважал область просмотра своего родителя, этот пример хорошо иллюстрирует, насколько это может быть не интуитивно понятно, хотя, безусловно, это сделает единицы v* более ценными для содержания, в котором находится iframe. Проблема заключается в том, что делать с тем, как определяется высота области просмотра.

Из спецификации:

Длина области просмотра в процентах относится к размеру исходного содержащего блока. Когда высота или ширина исходного содержащего блока изменяется, они масштабируются соответственно.

И iframe и окно браузера могут быть начальным содержащим блоком, поскольку они оба являются действительными окнами просмотра. Окно просмотра не ограничивается окном браузера, а определяется как окно или другая область просмотра на экране, через которую пользователи обращаются к документу.

При вставке в документ iframe создает вложенный контекст просмотра и, таким образом, имеет собственный видовой экран.

Так что да, это предполагаемое поведение - и, к сожалению, нет чистого обходного пути CSS - однако, www139 предоставил пример того, как это можно сделать с помощью JavaScript. Проблема с этим начинается, когда размер многих элементов контролируется с помощью единиц v*.

Ответ 2

Это отличный вопрос. К сожалению, мне не удалось найти решение в CSS, но я смог найти решение в JavaScript, которое я считаю вашим лучшим выбором на данный момент. Помните, что фреймы должны быть в одном домене, чтобы это работало.

Надеюсь это поможет. Если этот ответ нуждается в улучшении, пожалуйста, прокомментируйте ниже :-)

Решение в теории (не может использоваться здесь на SO из-за проблемы происхождения фрейма):

window.addEventListener('load',function(){
    initializeV();
    function initializeV(){
            //1% of the parent viewport width (same as 1vw):
            var vw = window.parent.innerWidth/100;
            //1% of the viewport height (same as 1vh):
            var vh = window.parent.innerHeight/100;

            //assign width and height to your v unit elements here
    }

    window.parent.addEventListener('resize',function(){
          //when the browser window is resized; recalculate
          initializeV();
    });
});

Изменить (декабрь 2018): В комментариях меня попросили привести пример. Я не могу сделать точный пример, потому что codepens на Stackoverflow загружают по другому источнику кадра, чем страница. Тем не менее, я могу имитировать эффект. Для практического применения, пожалуйста, обратитесь к фрагменту кода выше. Этот фрагмент предназначен только для иллюстрации того, как он работает.

Практическое применение. Использует концепцию, объясненную выше, но без ссылки на кадр.

window.addEventListener('load',function(){
        initializeV();
        function initializeV(){
                //note: I can't use window.parent becuase the code snippet loads on a different frame than the parent page. See the other snippet for a practical example. This snippet is meant to merely illustrate the effect.
                //1% of the parent viewport width (same as 1vw):
            	var vw = window.innerWidth/100;
                //1% of the viewport height (same as 1vh):
            	var vh = window.innerHeight/100;
        
              //this is where the magic happens. Simply set width/height/whatever to a multiple of vw/vh and add 'px'. Dimensions must be in pixels since the vw/vh measurement is based on pixels.
              document.getElementById('test').style.width = 30*vw+'px';
              document.getElementById('test').style.height = 50*vh+'px';
                //assign width and height to your v unit elements here
        }
        
        window.addEventListener('resize',function(){
              //when the browser window is resized; recalculate
              initializeV();
        });
    });
#test{
background:red;
}
<div id="test"></div>