Сделайте Iframe, чтобы соответствовать 100% оставшейся высоты контейнера - PullRequest
219 голосов
/ 28 ноября 2008

Я хочу создать веб-страницу с баннером и фреймом. Я надеюсь, что iframe может заполнить всю оставшуюся высоту страницы и будет автоматически изменен по мере изменения размера браузера. Возможно ли это сделать без написания кода Javascript, только с помощью CSS?

Я попытался установить height:100% в iframe, результат довольно близок, но iframe попытался заполнить всю высоту страницы, включая 30px высоту элемента div баннера, поэтому я получил ненужную вертикальную полосу прокрутки. Это не идеально.

Обновление примечаний : Извините, что я не очень хорошо описал вопрос, я попробовал CSS margin, padding attribute в DIV, чтобы успешно занять всю высоту напоминания веб-страницы, но уловка не сработала IFrame.

 <body>
    <div style="width:100%; height:30px; background-color:#cccccc;">Banner</div>
    <iframe src="http: //www.google.com.tw" style="width:100%; height:100%;"></iframe>
</body>

Любая идея приветствуется.

Ответы [ 26 ]

190 голосов
/ 28 ноября 2008

Обновление в 2019

TL; DR: На сегодняшний день лучший вариант ответа - последний в этом ответе - flexbox. Все это поддерживает хорошо и уже много лет. Сделай это и не оглядывайся назад. Остальная часть этого ответа оставлена ​​по историческим причинам.


Хитрость в том, чтобы понять, из чего взят 100%. В этом вам может помочь чтение спецификаций CSS.

Короче говоря, существует такая вещь, как "содержащий блок", который не является обязательным для родительского элемента. Проще говоря, это первый элемент иерархии, который имеет положение: относительное или положение: абсолютное. Или сам элемент тела, если больше ничего нет. Поэтому, когда вы говорите «width: 100%», он проверяет ширину «содержащего блока» и устанавливает ширину вашего элемента равным размеру. Если там было что-то еще, то вы могли бы получить содержимое «содержащего блока», которое больше его самого (таким образом, «переполнено»).

Высота работает так же. За одним исключением. Вы не можете получить высоту до 100% окна браузера. Элементом самого верхнего уровня, по которому можно рассчитать 100%, является элемент body (или html? Not sure), который растягивается настолько, чтобы вместить его содержимое. Указание высоты: 100% для него не будет иметь никакого эффекта, потому что у него нет «родительского элемента», для которого можно измерить 100%. Само окно не считается. ;)

Чтобы растянуть что-то точно на 100% окна, у вас есть два варианта:

  1. Использовать JavaScript
  2. Не используйте DOCTYPE. Это не очень хорошая практика, но это переводит браузеры в «режим причуд», в котором вы можете сделать height = «100%» для элементов, и он растянет их до размера окна. Обратите внимание, что остальная часть вашей страницы, вероятно, также должна быть изменена, чтобы соответствовать изменениям DOCTYPE.

Обновление: Я не уверен, не ошибся ли я уже, когда отправил это, но это, безусловно, устарело. Сегодня вы можете сделать это в своей таблице стилей: html, body { height: 100% }, и она будет фактически распространяться на всю область просмотра. Даже с DOCTYPE. min-height: 100% также может быть полезно, в зависимости от вашей ситуации.

И я больше никому не посоветовал бы сделать документ в режиме причуд , потому что это вызывает гораздо больше головных болей, чем решает их. В каждом браузере есть свой причудливый режим, поэтому заставить вашу страницу выглядеть одинаково во всех браузерах на два порядка сложнее. Используйте DOCTYPE. Всегда. Желательно HTML5 один - <!DOCTYPE html>. Это легко запомнить и работает как брелок во всех браузерах, даже 10-летних.

Единственное исключение - когда вам нужно поддерживать что-то вроде IE5 или что-то еще. Если вы там, то вы все равно сами по себе. Эти древние браузеры не похожи на современные браузеры, и небольшой совет, который здесь дан, поможет вам с ними. С другой стороны, если вы там, возможно, вам просто нужно поддерживать ОДИН вид браузера, который избавляет от проблем совместимости.

Удачи!

Обновление 2: Эй, это было давно! Спустя 6 лет появляются новые опции. Я только что провел обсуждение в комментариях ниже, вот еще несколько хитростей для вас, которые работают в современных браузерах.

Опция 1 - абсолютное позиционирование. Красиво и чисто, когда вы знаете точную высоту первой части.

body, html {width: 100%; height: 100%; margin: 0; padding: 0}
.first-row {position: absolute;top: 0; left: 0; right: 0; height: 100px; background-color: lime;}
.second-row {position: absolute; top: 100px; left: 0; right: 0; bottom: 0; background-color: red }
.second-row iframe {display: block; width: 100%; height: 100%; border: none;}
<div class="first-row">
  <p>Some text</p>
  <p>And some more text</p>
</div>
<div class="second-row">
  <iframe src="https://jsfiddle.net/about"></iframe>
</div>

Некоторые примечания - необходим контейнер second-row, потому что bottom: 0 и right: 0 по какой-то причине не работают с фреймами. Что-то связанное с тем, чтобы быть "замененным" элементом. Но width: 100% и height: 100% работает просто отлично. display: block необходим, потому что это элемент inline по умолчанию, и в противном случае пробелы начинают создавать странные переполнения.

Вариант 2 - таблицы. Работает, когда вы не знаете высоту первой части. Вы можете использовать либо фактические теги <table>, либо сделать это причудливо с помощью display: table. Я пойду за последним, потому что это, кажется, в моде в наши дни.

body, html {width: 100%; height: 100%; margin: 0; padding: 0}
.row-container {display: table; empty-cells: show; border-collapse: collapse; width: 100%; height: 100%;}
.first-row {display: table-row; overflow: auto; background-color: lime;}
.second-row {display: table-row; height: 100%; background-color: red; overflow: hidden }
.second-row iframe {width: 100%; height: 100%; border: none; margin: 0; padding: 0; display: block;}
<div class="row-container">
  <div class="first-row">
    <p>Some text</p>
    <p>And some more text</p>
  </div>
  <div class="second-row">
    <iframe src="https://jsfiddle.net/about"></iframe>
  </div>
</div>

Некоторые примечания - overflow: auto гарантирует, что строка всегда включает все ее содержимое. В противном случае плавающие элементы могут иногда переполняться. height: 100% во втором ряду гарантирует, что он расширяется настолько, насколько он может сжимать первый ряд настолько маленьким, насколько он получает.

Вариант 3 - flexbox. Самый чистый из них, но с менее чем звездной поддержкой браузера. IE10 потребуется -ms- префиксов для свойств flexbox, и все, что меньше, не будет поддерживать его вообще.

body, html {width: 100%; height: 100%; margin: 0; padding: 0}
.row-container {display: flex; width: 100%; height: 100%; flex-direction: column; background-color: blue; overflow: hidden;}
.first-row {background-color: lime; }
.second-row { flex-grow: 1; border: none; margin: 0; padding: 0; }
<div class="row-container">
  <div class="first-row">
    <p>Some text</p>
    <p>And some more text</p>
  </div>
  <iframe src="https://jsfiddle.net/about" class="second-row"></iframe>
</div>

Некоторые примечания - overflow: hidden заключается в том, что iframe по-прежнему генерирует какое-то переполнение даже в этом случае с display: block. Он не отображается в полноэкранном режиме или в редакторе фрагментов, но в небольшом окне предварительного просмотра появляется дополнительная полоса прокрутки. Понятия не имею, что это, если фреймы странные.

65 голосов
/ 01 декабря 2008

Мы используем JavaScript для решения этой проблемы; вот источник.


var buffer = 20; //scroll bar buffer
var iframe = document.getElementById('ifm');

function pageY(elem) {
    return elem.offsetParent ? (elem.offsetTop + pageY(elem.offsetParent)) : elem.offsetTop;
}

function resizeIframe() {
    var height = document.documentElement.clientHeight;
    height -= pageY(document.getElementById('ifm'))+ buffer ;
    height = (height < 0) ? 0 : height;
    document.getElementById('ifm').style.height = height + 'px';
}

// .onload doesn't work with IE8 and older.
if (iframe.attachEvent) {
    iframe.attachEvent("onload", resizeIframe);
} else {
    iframe.onload=resizeIframe;
}

window.onresize = resizeIframe;

Примечание: ifm - это идентификатор iframe

pageY() создано Джоном Резигом (автором jQuery)

45 голосов
/ 11 марта 2010

Другой способ сделать это - использовать position: fixed; на родительском узле.
Если я не ошибаюсь, position: fixed; связывает элемент с областью просмотра, поэтому, как только вы передадите этому узлу свойства width: 100%; и height: 100%;, он будет охватывать весь экран. С этого момента вы можете поместить тег <iframe> внутри него и распределить его по оставшемуся пространству (как по ширине, так и по высоте) с помощью простой width: 100%; height: 100%; инструкции CSS.

Пример кода


    body {
        margin: 0px;
        padding: 0px;
    }

    /* iframe's parent node */
    div#root {
        position: fixed;
        width: 100%;
        height: 100%;
    }

    /* iframe itself */
    div#root > iframe {
        display: block;
        width: 100%;
        height: 100%;
        border: none;
    }
   <html>
        <head>
            <title>iframe Test</title>
            <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
        </head>
        <body>
            <div id="root">
                <iframe src="http://stackoverflow.com/">
                    Your browser does not support inline frames.
                </iframe>
            </div>
        </body>
    </html>
37 голосов
/ 13 июля 2009

Вы можете сделать это с DOCTYPE, но вы должны использовать table. Проверьте это:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<style>
*{margin:0;padding:0}
html, body {height:100%;width:100%;overflow:hidden}
table {height:100%;width:100%;table-layout:static;border-collapse:collapse}
iframe {height:100%;width:100%}

.header {border-bottom:1px solid #000}
.content {height:100%}
</style>
</head>
<body>
<table>
    <tr><td class="header"><div><h1>Header</h1></div></td></tr>
    <tr><td class="content">
        <iframe src="http://google.com/" frameborder="0"></iframe></td></tr>
</table>
</body>
</html>
33 голосов
/ 13 января 2015

Вот несколько современных подходов:



  • Подход 2 - Подход Flexbox

    Пример здесь

    Установите display общего родительского элемента на flex вместе с flex-direction: column (при условии, что вы хотите, чтобы элементы располагались друг над другом). Затем установите flex-grow: 1 на дочерний элемент iframe, чтобы он заполнил оставшееся пространство.

    body {
        margin: 0;
    }
    .parent {
        display: flex;
        flex-direction: column;
        min-height: 100vh;
    }
    .parent .banner {
        background: #f00;
        width: 100%;
        height: 30px;
    }
    .parent iframe {
        background: #000;
        border: none;
        flex-grow: 1;
    }
    <div class="parent">
        <div class="banner"></div>
        <iframe></iframe>
    </div>

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

1 Хотя кажется, что он работает в Chrome / FF, он не работает в IE (первый метод работает во всех современных браузерах).

17 голосов
/ 08 июля 2010

Возможно, на этот вопрос уже был дан ответ (несколько приведенных выше «правильных» способов сделать это), но я подумал, что просто добавлю свое решение.

Наш iFrame загружен в div, поэтому мне нужно что-то еще, кроме window.height. И, видя, что наш проект уже сильно зависит от jQuery, я считаю, что это самое элегантное решение:

$("iframe").height($("#middle").height());

Где, конечно, "#middle" - это идентификатор div. Единственное, что вам нужно сделать, это вспомнить это изменение размера всякий раз, когда пользователь изменяет размер окна.

$(window).resize(function() {
    $("iframe").height($("#middle").height());
});
7 голосов
/ 28 октября 2011

Вот что я сделал. У меня была такая же проблема, и я часами искал в Интернете ресурсы.

<style type="text/css">
   html, body, div, iframe { margin:0; padding:0; height:100%; }
   iframe { position:fixed; display:block; width:100%; border:none; }
</style>

Я добавил это в раздел заголовка.

Обратите внимание, что мой iframe находится внутри средней ячейки таблицы, которая имеет 3 строки и 1 столбец.

6 голосов
/ 24 декабря 2010

Код MichAdel работает для меня, но я внес небольшую модификацию, чтобы он работал правильно.

function pageY(elem) {
    return elem.offsetParent ? (elem.offsetTop + pageY(elem.offsetParent)) : elem.offsetTop;
}
var buffer = 10; //scroll bar buffer
function resizeIframe() {
    var height = window.innerHeight || document.body.clientHeight || document.documentElement.clientHeight;
    height -= pageY(document.getElementById('ifm'))+ buffer ;
    height = (height < 0) ? 0 : height;
    document.getElementById('ifm').style.height = height + 'px';
}
window.onresize = resizeIframe;
window.onload = resizeIframe;
4 голосов
/ 11 декабря 2012

попробуйте следующее:

<iframe name="" src="" width="100%" style="height: 100em"/>

у меня это сработало

3 голосов
/ 28 ноября 2008

Правильно, вы показываете iframe со 100% высотой относительно его контейнера: body.

Попробуйте это:

<body>
  <div style="width:100%; height:30px; background-color:#cccccc;">Banner</div>
  <div style="width:100%; height:90%; background-color:transparent;">
    <iframe src="http: //www.google.com.tw" style="width:100%; height:100%;">
    </iframe> 
  </div>
</body>

Конечно, измените высоту второго div на желаемую высоту.

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