CSS - Высота блока относительно его ширины

Содержание:
  1. Создание блока с высотой, которая имеет определённый процент от его ширины
  2. Применение вышеприведённой технологии при создании карусели Bootstrap
  3. Комментарии

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

Создание блока с высотой, которая имеет определённый процент от его ширины

CSS - Установка высоты блоку относительно его ширины
CSS - Установка высоты блоку относительно его ширины
  1. Создать HTML структуру из 2 блоков:
    HTML
    <!-- 16:9 (отношение между шириной и высотой) -->
    <div class="item-responsive item-16by9">
      <div class="content"></div>
    </div>
    
    <!-- Блоки, имеющие другую высоту -->
    <!-- 4:3 -->
    <div class="item-responsive item-4by3">
      <div class="content"></div>
    </div>
    <!-- 2:1 -->
    <div class="item-responsive item-2by1">
      <div class="content"></div>
    </div>
    <!-- 1:1 -->
    <div class="item-responsive item-1by1">
      <div class="content"></div>
    </div>
    Первый блок имеет 2 класса. С помощью класса item-responsive установим блоку относительное позиционирование. Это необходимо выполнить для того, чтобы 2 блок (который будет иметь абсолютное позиционирование) располагался относительно него. Кроме этого данный класс также используется для того, чтобы перед содержимым соответствующих элементов (item-responsive) добавить псевдоэлемент :before. Этот элемент будет устанавливать необходимую высоту блока относительно его ширины с помощью CSS-свойства padding-top. Трюк данного метода заключается в том, что если свойству padding указывать значение не в пикселях, а в процентах, то оно будет рассчитываться браузером относительно его ширины. Таким образом, можно получить блок с необходимой высотой. Следующее действие - это указать 2 блоку абсолютное позиционирование и выровнять его по первому блоку.
  2. Добавить на страницу следующий CSS код:
    CSS
    .item-responsive {
      position: relative; /* относительное позиционирование */
    }
    .item-responsive:before {
      display: block; /* отображать элемент как блок */
      content: ""; /* содержимое псевдоэлемента */
      width: 100%; /* ширина элемента */
    }
    .item-16by9 {
      padding-top: 56,25%; /* (9:16)*100% */
    }
    .item-responsive>.content {
      position: absolute; /* абсолютное положение элемент */
      /* положение элемента */
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
    }
    
    /* При необходимости (для блоков, имеющих данные классы) */
    .item-4by3 {
      padding-top: 75%; /* (3:4)*100% */
    }
    .item-2by1 {
      padding-top: 50%; /* (1:2)*100% */
    }
    .item-1by1 {
      padding-top: 100%; /* (1:1)*100% */
    }

Применение вышеприведённой технологии при создании карусели Bootstrap

Если вы не знакомы с Bootstrap и хотите узнать что это такое, то можете воспользоваться статьёй Введение в Bootstrap.

Рассмотрим пример, в котором вышеприведённую HTML структуру и CSS код будем использовать для отображения слайдов карусели Bootstrap.

В качестве изображений будем использовать следующие файлы:

  • carousel_1.jpg (ширина = 736px, высота = 552px, соотношение сторон (высота к ширине) = 1,33);
  • carousel_2.jpg (ширина = 1155px, высота = 1280px, соотношение сторон (высота к ширине) = 0,9);
  • carousel_3.jpg (ширина = 1846px, высота = 1028px, соотношение сторон (высота к ширине) = 1,8);
  • carousel_4.jpg (ширина = 1140px, высота = 550px, соотношение сторон (высота к ширине) = 2,07);
  • carousel_5.jpg (ширина = 800px, высота = 600px, соотношение сторон (высота к ширине) = 1,33);

Изображения будем задавать как фон. Это позволит использовать в карусели Bootstrap 3 изображения с не одинаковыми соотношениями сторон.

Скриншот карусели Bootstrap 3
Скриншот карусели Bootstrap 3

Демо карусели

HTML разметка карусели:

HTML
<div id="carousel" class="carousel slide" data-ride="carousel" style="max-width: 600px; margin: 0 auto;">
  <!-- Indicators -->
  <ol class="carousel-indicators">
    <li data-target="#carousel" data-slide-to="0" class="active"></li>
    <li data-target="#carousel" data-slide-to="1"></li>
    <li data-target="#carousel" data-slide-to="2"></li>
    <li data-target="#carousel" data-slide-to="3"></li>
    <li data-target="#carousel" data-slide-to="4"></li>
  </ol>

  <!-- Wrapper for slides -->
  <div class="carousel-inner" role="listbox">
    <div class="item active">
      <div class="item-responsive item-16by9">
        <div class="content" style="background: url(assets/examples/img/carousel_1.jpg);"></div>
      </div>
      <div class="carousel-caption">
        Слайд 1
      </div>
    </div>
    <div class="item">
      <div class="item-responsive item-16by9">
        <div class="content" style="background: url(assets/examples/img/carousel_2.jpg);"></div>
      </div>
      <div class="carousel-caption">
        Слайд 2
      </div>
    </div>
    <div class="item">
      <div class="item-responsive item-16by9">
        <div class="content" style="background: url(assets/examples/img/carousel_3.jpg);"></div>
      </div>
      <div class="carousel-caption">
        Слайд 3
      </div>
    </div>
    <div class="item">
      <div class="item-responsive item-16by9">
        <div class="content" style="background: url(assets/examples/img/carousel_4.jpg);"></div>
      </div>
      <div class="carousel-caption">
        Слайд 4
      </div>
    </div>
    <div class="item">
      <div class="item-responsive item-16by9">
        <div class="content" style="background: url(assets/examples/img/carousel_5.jpg);"></div>
      </div>
      <div class="carousel-caption">
        Слайд 5
      </div>
    </div>
  </div>

  <!-- Controls -->
  <a class="left carousel-control" href="#carousel" role="button" data-slide="prev">
    <span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>
    <span class="sr-only">Previous</span>
  </a>
  <a class="right carousel-control" href="#carousel" role="button" data-slide="next">
    <span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span>
    <span class="sr-only">Next</span>
  </a>
</div>

CSS код карусели:

CSS
.item-responsive {
  position: relative; /* относительное позиционирование */
}
.item-responsive:before {
  display: block; /* отображать элемент как блок */
  content: ""; /* содержимое псевдоэлемента */
  width: 100%; /* ширина элемента */
}
.item-16by9 {
  padding-top: 56.25%; /* (9:16)*100% */
}
.item-responsive>.content {
  position: absolute; /* абсолютное положение элемент */
  /* положение элемента */
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-size: cover !important;
}

Комментарии: 9

Sergey
Sergey
Здравствуйте, Александр.

Подскажите, как быть в этом случае. Для карусели в фотошопе сделал картинки одинакового размера. При больших расширениях lg — карусель обтекается текстом. При уменьшении расширения экрана наступает момент, когда «ширина» карусели больше нежели ширина картинки (белые поля по бокам)! Далее при уменьшении — картинка в карусели начинает занимать всю ширину.
Что можно сделать, чтобы ширина карусели всегда ровнялась ширине картинки, а свободное пространство занимал текст.
Bootstar 3
часть кода
<div class="col-lg-6 text-center">
				<div id="carousel" class="carousel slide" data-ride="carousel">
			  <div class="carousel-inner">
			    <div class="item active">
			      <img class="img-responsive center-block" src="assets/images/b-room.jpg" alt="bedroom">
			    </div>
			    <div class="item">
			      <img class="img-responsive center-block" src="assets/images/kitchen.jpg" alt="kitchen">
			    </div>
			    <div class="item">
			      <img class="img-responsive center-block" src="assets/images/fireplace.jpg" alt="fireplace-room">
			    </div>
			  </div>
			  <!-- control panel -->
			  <a class="left carousel-control" href="#carousel" role="button" data-slide="prev">
			    <span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>
			    <span class="sr-only">previous</span>
			  </a>
			  <a class="right carousel-control" href="#carousel" role="button" data-slide="next">
			    <span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span>
			    <span class="sr-only">next</span>
			  </a>
			</div>
			</div><!-- col-lg-6 -->
		</div><!-- row -->
	</div><!-- container -->

и фото


Спасибо.
Sergey
Sergey
Александр, возможно существует лучший вариант, но пока что мне помогло добавление класса md…
<div class="col-lg-6 col-md-5 text-center">
				<div id="carousel" class="carousel slide" data-ride="carousel">
			  <div class="carousel-inner">
			    <div class="item active">
Играясь «ячейками», в принципе, найду подходящий вариант.
Но высота блока с текстом стает больше за карусель, которая прижата кверху!

теперь возникает иной вопрос. Как в блоке выровнять карусель по вертикали — центр (пробовал vertical-align:center;), не получилось!

Спасибо.
Sergey
Sergey
добавил класс
<div class="col-lg-6 col-md-7 text-center vcenter">
				<div id="carousel" class="carousel slide" data-ride="carousel">
и стиль
  .col-lg-6.col-md-6.text-center.vcenter {
  display: inline-block;
  float: none;
  vertical-align: middle;
}
не помогает! Возможно что-то делаю неправильно, а сам подход рабочий?!

Спасибо.
Александр Мальцев
Александр Мальцев
Подход, использованный в этой статье основан на использовании в качестве padding-top значения, установленного в процентах. В этом случае высота блока будет рассчитываться относительно его ширины. Это поведение описано в стандарте, и оно не может не работать, если только браузер работает не в соответствии с ним :)

В своих примерах вы нигде не используете padding-top? Поэтому не совсем понял как эта задача относится к тому, что описано в этой статье?

Чтобы ширина карусели не превышала ширину картинки, ей нужно задать максимальную ширину равную ширине картинки:
<div id="carousel" class="carousel slide" data-ride="carousel" style="max-width: 600px;">
Если хотите, чтобы её обтекал текст, то для этого используйте float.

Для выравнивания карусели по вертикали используйте CSS Flexbox.
<div class="col-lg-6 col-md-5 text-center" style="display: flex; align-items: center;">
  <div id="carousel" class="carousel slide" data-ride="carousel">
    ...
  </div>
</div>
Sergey
Sergey
Спасибо, Александр, за помощь. Внесу рекомендации. Собираю информацию с разных мест, когда что-то не получается — начинаю искать далее! Часто, ссылка на ваш ресурс выпадает на первой странице — тогда, знакомлюсь и, при необходимости, обращаюсь!
Спасибо!
Sergey
Sergey
Александр, ваш совет, действительно изменил к лучшему отображение карусели.
Спасибо.
Максим Хализов
Максим Хализов
Александр, этот способ не работает в FireFox там верхние и нижние падинги рассчитываются из высоты блока, а не из ширины как в хроме! Пример: допустим ширина контента в блоке 500px, высота 200px, c вашим способом получает что в Chrome padding-top 100% будет равен 500px, так как хром рассчитал падинг из ширины блока. А вот в firefox padding-top 100% будет равен 200px. Так как лиса считает падинги из высоты блока, которая равна из-за контент 200-м пикселям! В целом получаем не рабочий способ, так как ломаем верстку в FireFox
Александр Мальцев
Александр Мальцев
С чего вы это взяли?
В спецификации по CSS явно сказано, что значение padding-top и padding-bottom указанное в процентах рассчитывается относительно ширины. Слово width (ширина) подчеркнул красным цветом.

как рассчитывается значение padding-top и padding-bottom указанное в процентах
Открыл пример в Firefox 59 и не каких глюков с его стороны не заметил.
Максим Хализов
Максим Хализов
Mac OS в FireFox 59 данный урок не работает, хотя в хроме работает нормально