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

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

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

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

CSS - Установка высоты блоку относительно его ширины
CSS - Установка высоты блоку относительно его ширины
  1. Создать HTML структуру из 2 блоков:
    <!-- 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 код:
    .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 разметка карусели:

<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 код карусели:

.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;
}  

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

  1. Sergey
    21 февраля 2020, 18:55
    Здравствуйте, Александр.

    Подскажите, как быть в этом случае. Для карусели в фотошопе сделал картинки одинакового размера. При больших расширениях 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 -->
    

    и фото


    Спасибо.
    1. Sergey
      21 февраля 2020, 19:22
      Александр, возможно существует лучший вариант, но пока что мне помогло добавление класса 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;), не получилось!

      Спасибо.
      1. Sergey
        21 февраля 2020, 19:50
        добавил класс
        <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;
        }
        
        не помогает! Возможно что-то делаю неправильно, а сам подход рабочий?!

        Спасибо.
        1. Александр Мальцев
          24 февраля 2020, 15:00
          Подход, использованный в этой статье основан на использовании в качестве 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>
          
          1. Sergey
            24 февраля 2020, 18:26
            Спасибо, Александр, за помощь. Внесу рекомендации. Собираю информацию с разных мест, когда что-то не получается — начинаю искать далее! Часто, ссылка на ваш ресурс выпадает на первой странице — тогда, знакомлюсь и, при необходимости, обращаюсь!
            Спасибо!
            1. Sergey
              24 февраля 2020, 18:51
              Александр, ваш совет, действительно изменил к лучшему отображение карусели.
              Спасибо.
    2. Максим Хализов
      09 апреля 2018, 13:06
      Александр, этот способ не работает в FireFox там верхние и нижние падинги рассчитываются из высоты блока, а не из ширины как в хроме! Пример: допустим ширина контента в блоке 500px, высота 200px, c вашим способом получает что в Chrome padding-top 100% будет равен 500px, так как хром рассчитал падинг из ширины блока. А вот в firefox padding-top 100% будет равен 200px. Так как лиса считает падинги из высоты блока, которая равна из-за контент 200-м пикселям! В целом получаем не рабочий способ, так как ломаем верстку в FireFox
      1. Александр Мальцев
        09 апреля 2018, 13:48
        С чего вы это взяли?
        В спецификации по CSS явно сказано, что значение padding-top и padding-bottom указанное в процентах рассчитывается относительно ширины. Слово width (ширина) подчеркнул красным цветом.

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