Flexbox не работает с элементами кнопок или элементов

Я пытаюсь центрировать внутренние элементы <button> -tag с flexbox justify-content: center. Но Safari не сосредотачивает их. Я могу применить один и тот же стиль к любым другим тегам, и он работает по назначению (см. <p> -tag). Только кнопка выровнена по левому краю.

Попробуйте Firefox или Chrome, и вы увидите разницу.

Есть ли какой-либо стиль пользовательского агента, который я должен переписать? Или любое другое решение этой проблемы?

div {
  display: flex;
  flex-direction: column;
  width: 100%;
}
button, p {
  display: flex;
  flex-direction: row;
  justify-content: center;
}
<div>
  <button>
    <span>Test</span>
    <span>Test</span>
  </button>
  <p>
    <span>Test</span>
    <span>Test</span>
  </p>
</div>

Ответ 1

Проблема

Проблема заключается в том, что некоторые браузеры еще не разработали элемент <button> в качестве гибкого (или сеточного) контейнера.

С технической точки зрения, в некоторых браузерах элемент <button> не принимает изменений в его значении display, кроме переключения с block и inline-block. Это означает, что элемент <button> также не может быть <table>.

Это поведение также может применяться к элементам <fieldset> и <legend>.

См. отчеты об ошибках ниже для получения более подробной информации.

Примечание. Хотя они не могут быть гибкими контейнерами, элементы <button> могут быть гибкими элементами.


Решение

Существует простой и удобный кросс-браузерный способ решения этой проблемы:

Оберните содержимое button в span и сделайте span гибким контейнером.

Скорректированный HTML (обернутое содержимое button в span)

<div>
    <button>
        <span><!-- using a div also works but is not valid HTML -->
            <span>Test</span>
            <span>Test</span>
        </span>
    </button>
    <p>
        <span>Test</span>
        <span>Test</span>
    </p>
</div>

Скорректированный CSS (нацелен на span)

button > span, p {
    display: flex;
    flex-direction: row;
    justify-content: center;
}

Пересмотренная демонстрация


Ссылки/Отчеты об ошибках

Flexbox на <button> блокирует содержимое, но не устанавливает контекст гибкого форматирования

Пользователь (Oriol Brufau): Дочерние элементы <button> блокируются, как того требует спецификация flexbox. Однако <button>, кажется, устанавливает контекст форматирования блока вместо гибкого.

Пользователь (Даниэль Холберт): Это именно то, чего требует спецификация HTML. Некоторые HTML-элементы-контейнеры являются "специальными" и фактически игнорируют их значение CSS display в Gecko [помимо того, является ли он внутренним уровнем или блочным уровнем]. <button> является одним из них. <fieldset> & <legend> тоже.

Добавить поддержку отображения: макет flex/grid и columnset внутри элементов <button>

User (Daniel Holbert):

<button> не может быть реализовано (браузерами) в чистом CSS, поэтому с точки зрения CSS это немного чёрный ящик. Это значит, что они не обязательно реагируют так же, как, например, <div> будет.

Это не относится к flexbox - например, мы не отрисовываем полосы прокрутки, если вы положили overflow:scroll на кнопку, и мы не отрисовываем его как стол, если вы положите display:table на него.

Отступив еще дальше, это не относится к <button>. Рассмотрим <fieldset> и <table>, которые также имеют специальный рендеринг поведение.

А старые HTML-элементы, такие как <button> и <table> и <fieldset>, просто не поддерживают пользовательские значения display, кроме в целях ответа на вопрос очень высокого уровня "это элемент уровня блока или встроенный уровень ", для передачи другого контента вокруг элемент.

Также смотрите:

Ответ 2

Вот мой самый простой хак.

button::before,
button::after {
    content: '';
    flex: 1 0 auto;
}