Ребенок с максимальной высотой: 100% переполняет родитель


139

Я пытаюсь понять то, что кажется мне неожиданным поведением:

У меня есть элемент с максимальной высотой 100% внутри контейнера, который также использует максимальную высоту, но неожиданно дочерний объект переполняет родительский:

Тестовый пример: http://jsfiddle.net/bq4Wu/16/

.container {  
    background: blue; 
    padding: 10px; 
    max-height: 200px; 
    max-width: 200px; 
}

img { 
    display: block;
    max-height: 100%; 
    max-width: 100%; 
}

Это исправлено, однако, если родителю дана явная высота:

Тестовый пример: http://jsfiddle.net/bq4Wu/17/

.container {  
    height: 200px;
}

Кто-нибудь знает, почему ребенок не соблюдает максимальную высоту своего родителя в первом примере? Почему требуется явная высота?

Ответы:


209

Когда вы указываете процент для max-heightребенка, это max-height, как ни странно, процент от фактического роста родителя, а не родителя . То же самое относится и к max-width.

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

Когда вы делаете явно указать высоту родителя, то ребенок знает , что он должен быть не более 100% от этой явной высоты. Это позволяет ему быть ограниченным ростом родителя (при сохранении пропорций).


4
Это полезное объяснение, особенно смешанное с вводом моего друга: «max-height: 100% (child) от max-height: 100% (parent) = 0 - вот почему ваш ребенок не соблюдает значение родительского элемента».
iamkeir

8
Я не уверен, какой ответ принять - этот отвечает на вопрос «почему».
iamkeir

Я только ответил «почему», потому что я не уверен, какова ваша цель, так как это явно не упомянуто. Может быть, если вы уточните это, я могу ответить.
BoltClock

Принял это, так как оно отвечает на мой актуальный вопрос, спасибо. Обратите внимание, @ ответ Даниэля ниже предлагает исправление.
iamkeir

В моем случае это display: flex; flex-direction: columnрешило проблему и добавило желаемую полосу прокрутки.
xdevs23

73

Я немного поиграл. На увеличенном изображении в Firefox я получил хороший результат, используя значение свойства наследования. Это поможет тебе?

.container {
    background: blue;
    padding: 10px;
    max-height: 100px;
    max-width: 100px;
    text-align:center;
}

img {
    max-height: inherit;
    max-width: inherit;
}

Я не уверен, какой ответ принять - этот отвечает на «исправить».
iamkeir

Принято @BoltClock за ответ на вопрос «почему», но спасибо, что предложили исправление.
iamkeir

1
В дополнение к @BoltClock мой ответ точно делает то, что он говорит. CSS просто говорит компьютеру, как обрабатывать элемент, но после вычислений он разграничит все значения до базовых необходимых значений для рендеринга, таких как высота, ширина, цвет, координаты, ... Свойство наследования сообщает img принять "вычисленное" значение родителя. Таким образом, вы получите вычисленные значения высоты и ширины в свойствах max-height и max-width css.
Даниил

2
Это не работает, когда max:height: 100%вместо фиксированной высоты: jsfiddle.net/umbreak/n6czk9xt/1
Didac Montero

2
Я не могу объявить ширину и высоту как фиксированные, потому что мой макет отзывчивый dispaly: flex;. Я открыл новый поток: я открыл свой новый поток: stackoverflow.com/questions/29732391/… Однако в худшем случае я мог бы использовать Jquery для извлечения реальной ширины и высоты img и установить их в div родительского изображения.
Дидак Монтеро

7

Я нашел решение здесь: http://www.sitepoint.com/maintain-image-aspect-ratios-responsive-web-design/

Хитрость возможна, потому что существует связь между ШИРОКОЙ и ДОБАВКОЙ ДНА элемента. Так:

родитель:

container {
  height: 0;
  padding-bottom: 66%; /* for a 4:3 container size */
  }

дочерний ( удалить все CSS, относящиеся к ширине , т.е. ширине: 100%):

img {
  max-height: 100%;
  max-width: 100%;
  position: absolute;     
  display:block;
  margin:0 auto; /* center */
  left:0;        /* center */
  right:0;       /* center */
  }

5

Вы можете использовать свойство object-fit

.cover {
    object-fit: cover;
    width: 150px;
    height: 100px;
}

Вроде предложено здесь

Полное объяснение этого свойства Криса Миллса в Dev.Opera

И еще лучше в CSS-хитрости

Это поддерживается в

  • Chrome 31+
  • Safari 7.1+
  • Firefox 36+
  • Опера 26+
  • Android 4.4.4+
  • iOS 8+

Я только что проверил, что вивальди и хром также поддерживают его (здесь нет ничего удивительного)

В настоящее время он не поддерживается в IE, но ... кого это волнует ? Кроме того, iOS поддерживает подгонку объекта, но не положение объекта, но это скоро произойдет.


Хорошая альтернатива! Я полагаю, что flex-box тоже может помочь, если допустимо постепенное ухудшение IE.
iamkeir

3

Вот решение для недавно открытого вопроса, помеченного как дубликат этого вопроса. <img>Тег превышая максимальную высоту-родителя <div>.

Сломанный: скрипка

Рабочая: скрипка

В этом случае, добавление display:flexк 2 родительским <div>тегам было ответом


3

Вместо того, чтобы использовать max-height: 100% / 100%, альтернативный подход к заполнению всего пространства будет использовать position: absoluteс top / bottom / left / right, установленным в 0.

Другими словами, HTML будет выглядеть следующим образом:

<div class="flex-content">
  <div class="scrollable-content-wrapper">
    <div class="scrollable-content">
      1, 2, 3
    </div>
   </div>
</div>
.flex-content {
  flex-grow: 1;
  position: relative;
  width: 100%;
  height: 100%;
}

.scrollable-content-wrapper {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
  overflow: auto;
}

.scrollable-content {
}

Вы можете увидеть живой пример в Codesandbox - Переполнение в CSS Flex / Grid


2

Может быть, кто-то еще может объяснить причины вашей проблемы, но вы можете решить ее, указав высоту контейнера, а затем установив высоту изображения равной 100%. Важно, widthчтобы изображение отображалось перед height.

<html>
    <head>
        <style>
            .container {  
                background: blue; 
                padding: 10px;
                height: 100%;
                max-height: 200px; 
                max-width: 300px; 
            }

            .container img {
                width: 100%;
                height: 100%
            }
        </style>
    </head>
    <body>
        <div class="container">
            <img src="http://placekitten.com/400/500" />
        </div>
    </body>
</html>

Если они хотят, чтобы контейнер стал меньше, если изображение меньше, чем 200x200, тогда да, это должно быть сделано с помощью min-height / max-height.
cimmanon

2

Наиболее близкий к этому пример:

http://jsfiddle.net/YRFJQ/1/

или

.container {  
  background: blue; 
  border: 10px solid blue; 
  max-height: 200px; 
  max-width: 200px; 
  overflow:hidden;
  box-sizing:border-box;
}

img { 
  display: block;
  max-height: 100%; 
  max-width: 100%; 
}

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

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

Не уверен, что это подойдет для того, что вам нужно, но лучшее, что я могу найти.


К сожалению, обрезка изображения не идеальна. Тем не менее, спасибо за ваш вклад.
iamkeir

1

Хорошее решение - не использовать высоту для родительского элемента и использовать его только для дочернего элемента с помощью View Port :

Пример скрипта: https://jsfiddle.net/voan3v13/1/

body, html {
  width: 100%;
  height: 100%;
}
.parent {
  width: 400px;
  background: green;
}

.child {
  max-height: 40vh;
  background: blue;
  overflow-y: scroll;
}

1

Контейнеры уже обычно хорошо оборачивают свое содержимое. Часто наоборот: дети плохо справляются со своими предками. Итак, установите значения ширины / высоты для самого внутреннего элемента, а не для самого внешнего элемента, и позвольте внешним элементам обернуть свое содержимое.

.container {
    background: blue;
    padding: 10px;
}

img {
    display: block;
    max-height: 200px;
    max-width: 200px;
}

Хороший дубль, мне это нравится.
iamkeir

0

Ваш контейнер не имеет высоты.

Добавьте высоту: 200px;

к контейнерам css и котенок останется внутри.


Спасибо за вклад, но я определил это в ОП.
iamkeir
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.