CSS 100% высота с отступом / полем

Это сводило меня с ума уже пару дней, но на самом деле это проблема, с которой я сталкивался последние несколько лет: с помощью HTML/CSS я могу создать элемент с шириной и / или высота, которая составляет 100% его родительского элемента и все еще имеет надлежащие отступы или поля?

Под "правильным" я подразумеваю, что если мой родительский элемент 200px высокий и я уточняю height = 100% с padding = 5px Я ожидаю, что я должен получить 190px высокий элемент с border = 5px со всех сторон, красиво по центру родительского элемента.

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

#myDiv {
    width: 100%
    height: 100%;
    padding: 5px;
}

Но мне кажется, что должен быть НЕКОТОРЫЙ способ надежного создания этого эффекта для родителя произвольного размера. Кто-нибудь знает способ выполнения этой (казалось бы простой) задачи?

Да, и для записи, я не очень заинтересован в совместимости с IE, так что это должно (надеюсь) немного упростить ситуацию.

РЕДАКТИРОВАТЬ: так как пример был запрошен, вот самый простой, который я могу придумать:

<html style="height: 100%">
    <body style="height: 100%">
        <div style="background-color: black; height: 100%; padding: 25px"></div>
    </body>
</html>

Задача состоит в том, чтобы черный ящик отображался с отступом 25 пикселей по всем краям, при этом страница не становилась достаточно большой, чтобы требовать полосы прокрутки.

13 ответов

Решение

Я научился делать такие вещи, читая " PRO HTML и CSS Design Patterns ". display:block значение по умолчанию для div, но я хотел бы сделать это явным. Контейнер должен быть правильного типа; position атрибут fixed, relative, или же absolute,

.stretchedToMargin {
  display: block;
  position:absolute;
  height:auto;
  bottom:0;
  top:0;
  left:0;
  right:0;
  margin-top:20px;
  margin-bottom:20px;
  margin-right:80px;
  margin-left:80px;
  background-color: green;
}
<div class="stretchedToMargin">
  Hello, world
</div>

Скрипка от комментария Ноошу

В CSS3 есть новое свойство, которое вы можете использовать для изменения способа, которым блочная модель рассчитывает ширину / высоту, оно называется box-sizing.

Устанавливая это свойство значением "border-box", оно делает любой элемент, к которому вы применяете, не растягивать при добавлении отступа или границы. Если вы определите что-то с шириной 100px и отступом 10px, оно все равно будет иметь ширину 100px.

box-sizing: border-box;

Смотрите здесь для поддержки браузера. Он не работает для IE7 и ниже, однако, я считаю, что IE7.js Дина Эдварда добавляет поддержку для него. Наслаждаться:)

Решение - НЕ использовать высоту и ширину! Прикрепите внутреннюю коробку, используя верхнюю, левую, правую, нижнюю, а затем добавьте поля.

.box {margin:8px; position:absolute; top:0; left:0; right:0; bottom:0}
<div class="box" style="background:black">
  <div class="box" style="background:green">
    <div class="box" style="background:lightblue">
      This will show three nested boxes. Try resizing browser to see they remain nested properly.
    </div>
  </div>
</div>

Лучше всего использовать свойство calc(). Таким образом, ваш случай будет выглядеть так:

#myDiv {
    width: calc(100% - 5px);
    height: calc(100% - 5px);
    padding: 5px;
}

Просто, чисто, обходных путей нет. Просто убедитесь, что вы не забыли пробел между значениями и оператором (например, (100%-5px), который нарушит синтаксис. Наслаждайтесь!

Согласно спецификации w3c высота относится к высоте видимой области, например, на мониторе с разрешением 1280x1024 пикселей, высота 100% = 1024 пикселей.

min-height относится к общей высоте страницы, включая контент, поэтому на странице, где контент больше 1024px min-height:100% растянется, чтобы включить весь контент.

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

min-height: 100%;
padding: 5px; 

Это на самом деле даст вам 100% + 5px + 5px для высоты. Чтобы обойти это, вам нужен контейнер-обертка.

<style>
    .FullHeight { 
       height: auto !important; /* ie 6 will ignore this */
       height: 100%;            /* ie 6 will use this instead of min-height */
       min-height: 100%;        /* ie 6 will ignore this */
    }

    .Padded {
       padding: 5px;
    }
</style>

<div class="FullHeight">
   <div class="Padded">
      Hello i am padded.
   </div
</div>

1. Полная высота с padding

body {
  margin: 0;
}
.container {
  min-height: 100vh;
  padding: 50px;
  box-sizing: border-box;
  background: silver;
}
<div class="container">Hello world.</div>

2. Полная высота с margin

body {
  margin: 0;
}
.container {
  min-height: calc(100vh - 100px);
  margin: 50px;
  background: silver;
}
<div class="container">Hello world.</div>

3. Полная высота с border

body {
  margin: 0;
}
.container {
  min-height: 100vh;
  border: 50px solid pink;
  box-sizing: border-box;
  background: silver;
}
<div class="container">Hello world.</div>

Это одна из явных идиотий CSS - мне еще предстоит понять причину (если кто-то знает, пожалуйста, объясните).

100% означает 100% высоты контейнера, к которой добавляются любые поля, границы и отступы. Таким образом, фактически невозможно получить контейнер, который заполняет его родительский объект и у которого есть поля, границы или отступы.

Также обратите внимание, что установка высоты, как известно, несовместима и между браузерами.


Еще одна вещь, которую я узнал после публикации, - это то, что процент является относительным к длине контейнера, то есть его ширине, что делает процент еще более бесполезным для высоты.

В настоящее время блоки просмотра vh и vw более полезны, но все же не особенно полезны для чего-либо, кроме контейнеров верхнего уровня.

Другое решение заключается в использовании display:table, который имеет другое поведение блочной модели.

Вы можете установить высоту и ширину родительского элемента и добавить отступы, не расширяя его. У ребенка 100% высота и ширина минус отступы.

JSBIN

Другим вариантом будет использование свойства размера ящика. Единственная проблема с обоими - они не работают в IE7.

Другое решение: Вы можете использовать процентные единицы для полей и размеров. Например:

.fullWidthPlusMargin {
    width: 98%;
    margin: 1%;
}

Основной проблемой здесь является то, что поля будут немного увеличиваться / уменьшаться с размером родительского элемента. Предположительно, функциональность, которую вы бы предпочли, заключается в том, чтобы поля оставались постоянными, а дочерний элемент увеличивался / уменьшался для заполнения изменений в интервале. Таким образом, в зависимости от того, насколько плотно вам нужен дисплей, это может быть проблематично. (Я бы также пошел на меньшую маржу, например, 0,3%).

Сейчас 2018 год, здесь следует упомянуть новое горячее дерьмо, так как этот вопрос постоянно всплывает в Google.

Решение с flexbox (работает на IE11): ( или посмотреть на jsfiddle)

<html>
  <style>
    html, body {
      height: 100%; /* fix for IE11, not needed for chrome/ff */
      margin: 0; /* CSS-reset for chrome */
    }
  </style>
  <body style="display: flex;">
    <div style="background-color: black; flex: 1; margin: 25px;"></div>
  </body>
</html>

( Сброс CSS не обязательно важен для реальной проблемы.)

Важная часть flex: 1 (В комбинации с display: flex у родителя). Как ни странно, самое правдоподобное объяснение того, как работает свойство Flex, я знаю из реактивной документации, поэтому я все равно на нее ссылаюсь.

Было бы более уместно добавить -webkit и -moz

-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;

Пример Фрэнка меня немного смутил - в моем случае это не сработало, потому что я еще недостаточно хорошо разбирался в позиционировании. Важно отметить, что родительский элемент контейнера должен иметь нестатическую позицию (он упоминал об этом, но я упустил это из виду, и это не было в его примере).

Вот пример, где дочерний элемент - заданный отступ и граница - использует абсолютное позиционирование, чтобы заполнить родительский элемент на 100%. Родитель использует относительное расположение, чтобы обеспечить точку отсчета для позиции дочернего элемента, оставаясь при этом в обычном потоке - на следующий элемент "more-content" это не влияет:

#box {
    position: relative;
    height: 300px;
    width: 600px;
}

#box p {
    position: absolute;
    border-style: dashed;
    padding: 1em;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
}
<div id="box">
  <p>100% height and width!</p>
</div>
<div id="more-content">
</div>

Полезная ссылка для быстрого изучения позиционирования CSS

Это поведение по умолчанию display: block Самый быстрый способ исправить это в 2020 году - установить display: 'flex' родительского элемента и отступа, например, 20 пикселей, тогда все его дочерние элементы будут иметь высоту 100% относительно его высоты.

Граница вокруг div, а не поля страницы

Другое решение - я просто хотел простую рамку по краю моей страницы и 100% высоты, когда содержимое было меньше этого.

Граница не работала, и фиксированное положение казалось неправильным для такой простой необходимости.

Я закончил тем, что добавил контейнер в свой контейнер, вместо того, чтобы полагаться на поля тела страницы - это выглядит так:

body, html {
    height: 100%;
    margin: 0;
}

.container {
    width: 100%;
    min-height: 100%;
    border: 8px solid #564333;
}
  <style type="text/css">
.stretchedToMargin {
    position:absolute;
    width:100%;
    height:100%;

}
</style>
Другие вопросы по тегам