Настройка ширины элемента на основе высоты через CSS

У меня есть набор элементов и требуется, чтобы их минимальная ширина была равна их высоте, но высота явно не задана. В настоящее время я могу добиться этого, установив свойство css min-width через jQuery:

$(document).ready
(
    function()
    {
        $('.myClass').each
         (
             function() {$(this).css('min-width', $(this).css('height'));}
         );
    }
);  

Можно ли указать это поведение непосредственно в css?

Вот пример jsfiddle, демонстрирующий, чего я пытаюсь достичь: http://jsfiddle.net/p8PeW/

Ответ 1

Я не верю, что это возможно без JS, но, может быть, кто-то может доказать, что я неправ?

CSS не позволяет использовать динамические переменные, поэтому, если высота не установлена ​​до загрузки страницы, я не уверен, как это можно сделать.

Ответ 2

Это на самом деле возможно без JS!

Ключ заключается в том, чтобы использовать <img>, который является заменяемым элементом, и, следовательно, если вы устанавливаете только высоту, его ширина будет установлена автоматически, чтобы сохранить внутренние пропорции изображения.

Следовательно, вы можете сделать следующее:

<style>
  .container {
    position: relative;
    display: inline-block; /* shrink wrap */
    height: 50vh; /* arbitrary input height; adjust this */
  }
  .container > img {
    height: 100%; /* make the img width 100% of the height of .container */
  }
  .contents {
    /* match size of .container, without influencing it */
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
  }
</style>

<div class="container">
  <!-- transparent image with 1:1 intrinsic aspect ratio -->
  <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7">
  <div class="contents">
    Put contents here.
  </div>
</div>

Если вы хотите, чтобы .contents имел соотношение сторон 4: 3, вы бы вместо этого установили высоту img .contents 133%, поэтому ширина img и, следовательно, .contents будет равна 133% от высоты .container.

Демонстрационная версия с соотношением сторон 1: 4: https://jsbin.com/juduheq/edit (с дополнительными комментариями к коду).

Еще одно живое демо, где высота контейнера определяется количеством текста в элементе-брате: https://jsbin.com/koyuxuh/edit

Если вам интересно, URI данных img предназначен для прозрачного gif размером 1x1 px). Если изображение не имеет соотношения сторон 1:1, вам необходимо соответствующим образом отрегулировать значения высоты, которые вы установили. Вы также можете использовать элемент <canvas> или <svg> вместо <img> (спасибо Simo).

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

Ответ 3

От W3C Box Model на набивке:

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

Таким образом, вы можете получить его, используя только CSS. Посмотрите этот пример из этого поста в блоге на другую тему, не менее интересную. Хитрость в создании коэффициентов заключается в использовании чего-то вроде

element::before {
  content: '';
  display: block;
  padding-bottom: 100%;
}

Ответ 4

Существует еще одно очень простое решение css, но только для точного случая, который OP представил в его jsfiddle:

label {
  background-color: Black;
  color: White;
  padding: 1px;
  font-family: sans-serif;
  text-align: center;
  vertical-align: middle;
  display: inline-block;
  min-width: 1em; /* set width to the glyphs height */
}
<label>A</label><br/>
<label>B</label><br/>
<label>C</label><br/>
<label>D</label><br/>
<label>E</label><br/>
<label>F</label><br/>
<label>R6a</label>

Ответ 5

Если вы пытаетесь сделать квадраты, вам придется учитывать оба случая (W > H и W < H):

$('label').each(function() {
    if ($(this).height() > $(this).width()) {
        $(this).css('min-width', $(this).height());
    } else {
        $(this).css('min-height', $(this).width());
    }
});

Ответ 6

У меня было такое же требование, и я успешно использовал решение @John Melor... до тех пор, пока оно не сработало в Firefox. Я попытался воспроизвести свою конкретную проблему, протестировав различные примеры кода jsbin здесь, но не повезло. Вероятно, очень специфическая ошибка браузера, основанная на моем реальном DOM. Если у кого-то есть jsbin этой проблемы, пожалуйста, поделитесь!

Я перепробовал много комбинаций, которые не срабатывают на одном и том же: контейнер не расширяется до ширины изображения. Firefox объявляет, что у изображения есть ширина его высоты, но у родителя есть ширина 1px независимо от того, что я попробовал.

Для тех, кто оказался в такой ситуации, я использовал исправление js, которое остается локальным для элемента изображения. Если высота контейнера не указана, как в первоначальном OP-вопросе, это также может быть полезно для вас.

В JSX/ES6:

const TRANSPARENT_PIXEL = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'
const setWidthToHeight = e => { e.target.style.width = e.target.height }
const force1x1Ratio = <img src={TRANSPARENT_PIXEL} onLoad={setWidthToHeight} />

С простым старым HTML

<img 
    src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" 
    onLoad="javascript:function(e) { e.target.style.width = e.target.height + 'px' }" />