Firefox: элемент внутри контейнера flexbox не сохраняет соотношение сторон

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

+-----+-----------------+
|     |                 |
|  c  |c   +------+     |
|  o  |o   | item |     |
|  l  |l   |      |     |
|     |    +------+     |
|  1  |2                |
+-----------------------+

col 1 и col 2 создаются с помощью CSS Grid. Теперь я пытаюсь центрировать item (как по горизонтали, так и по вертикали) внутри col 2.

#content {
  display: grid;
  grid-template-columns: minmax(13rem, 15%) minmax(85%, 100%);
  
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  width: 100%;
  height: 100%;
}

#circle {
  background: #7FFF00;
  
  width: 9%;
  padding-top: 9%;
  border-radius: 50%;
  
  margin: auto;
}

.menu {
  background: #D2691E;
  
  grid-row-start: 1;
  grid-row-end: 1;
}

.circle-area {
  background: #191970;
  
  grid-row-start: 1;
  grid-row-end: 1;
  grid-column-start: auto;
  grid-column-end: span 2;
  
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
}
<body>
<div id='content'>
<div class='menu'></div>
<div class='circle-area'>
<div id='circle'></div>
</div>
</div>
</body>

Приведенный выше код для JSFiddle

Мой код работает так, как я ожидал (item сохраняет соотношение сторон и центрируется по вертикали и горизонтали) при тестировании в Chrome 62.0 и Safari 11.0. Хотя, когда я добрался до Firefox (56.0) - соотношение сторон меняется при изменении размера окна. Я попробовал другой метод центрирования, используя сетка (JSFiddle) (результат тот же, что Firefox не сохранит соотношение сторон).

Теперь комментируем (JSFiddle) гибкую часть из css, заставит Firefox сохранить соотношение сторон, хотя элемент больше не центрируется по вертикали.

Мои вопросы:

  1. Это известная проблема (ошибка) в Firefox или что-то не так с моим кодом?
  2. Каково правильное исправление/обходной путь для центрирования item по вертикали и горизонтали внутри col 2 с сохранением соотношения сторон (предпочтительно с использованием flex)?

person Community    schedule 20.10.2017    source источник
comment
@LGSon вопрос, который связан как дублирующийся, не затрагивает другой браузер поведение/реализация 'процентных полей и отступов в элементах сетки' явно (хотя сама проблема аналогична здесь). Так что этот вопрос не кажется мне дубликатом. Я что-то упускаю?   -  person    schedule 23.10.2017
comment
Вы пропустили, что это дубликат, так как его ответ решает ваш вопрос, и он делает это, регулируя поведение различных браузеров, используя проценты для псевдоэлемента, который не является частью Flexbox и, следовательно, не страдает от него.   -  person Ason    schedule 23.10.2017
comment
Обратите внимание, дубликат не означает, что оба вопроса одинаковы, это означает, что ответ в одном решает оба   -  person Ason    schedule 23.10.2017
comment
JSFiddle из комментария @LGSon выше (первоначально jsfiddle.net/67uz5j3p/9) был перемещен в другую скрипку< /а>   -  person    schedule 14.04.2020


Ответы (1)


Кратко о поведении браузера при вертикальных полях/отступах в процентах

Это не ошибка сама по себе, но, вероятно, из-за другой реализации браузера, как вертикальные интервалы в процентах (верхние и нижние поля/отступы) должны рассчитываться в flex или grid:

Процентные поля и отступы в элементах сетки могут быть разрешены:

  • их собственная ось (левый/правый процент разрешается по ширине, верхний/нижний разрешается по высоте), или,
  • встроенная ось (левый/правый/верхний/нижний процент разрешается в зависимости от ширины)

Пользовательский агент должен выбрать одно из этих двух действий.

Нет непоследовательности в выборе какой-либо стратегии разрешения: как видите, Chrome и Safari выберут стратегию №2, а IE, Edge и Firefox выберут стратегию №1 (что объясняет вашу ошибку). . W3C также отметил, что:

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

Авторам следует полностью избегать использования процентов в отступах или полях элементов сетки, поскольку они будут вести себя по-разному в разных браузерах.


Решение

Что вы можете сделать, так это просто определить сам круг как псевдоэлемент. В этом подходе:

  • внешний элемент #circle имеет ширину 9%, но больше ничего
  • псевдоэлемент ::before будет иметь ширину 100% и верхний отступ 100%, это заставит его иметь соотношение сторон 1: 1 по желанию.

Ваш обновленный CSS будет выглядеть так:

#circle {
  width: 9%;
  margin: auto;
}

#circle::before {
  background: #7FFF00;
  border-radius: 50%;
  width: 100%;
  height: 0;
  padding-top: 100%;
  content: '';
  display: block;
}

См. доказательство концепции ниже (или в этой скрипке):

#content {
  display: grid;
  grid-template-columns: minmax(13rem, 15%) minmax(85%, 100%);
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  width: 100%;
  height: 100%;
}

#circle {
  width: 9%;
  margin: auto;
}

#circle::before {
  background: #7FFF00;
  border-radius: 50%;
  width: 100%;
  height: 0;
  padding-top: 100%;
  content: '';
  display: block;
}

.menu {
  background: #D2691E;
  grid-row-start: 1;
  grid-row-end: 1;
}

.circle-area {
  background: #191970;
  grid-row-start: 1;
  grid-row-end: 1;
  grid-column-start: auto;
  grid-column-end: span 2;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
}
<body>
  <div id='content'>
    <div class='menu'></div>
    <div class='circle-area'>
      <div id='circle'></div>
    </div>
  </div>
</body>

person Terry    schedule 20.10.2017
comment
Есть ли причина, по которой вы добавили height: 0 к #circle::before. Я не заметил никаких изменений после его удаления, поэтому мне интересно, должно ли оно быть вообще? - person ; 21.10.2017
comment
@ФилиппВ. Это просто защита от контента внутри элемента, поэтому вы можете безопасно удалить его, если знаете, что всегда объявляете пустой атрибут контента. - person Terry; 21.10.2017