- CSS margin:auto — Как это работает?
- «auto» — занять все доступное пространство
- Имитация плавающего поведения через распределение доступного пространства
- «auto» — задать 0 пикселей
- Что происходит с вертикальными отступами со значением auto?
- Центрирование абсолютно позиционированных элементов
- Заключение
- Почему «margin: auto» не центрирует элемент по вертикали?
- 5 ответов
- Центрирование горизонтальное и вертикальное
- Горизонтальное
- text-align
- margin: auto
- Вертикальное
- position:absolute + margin
- Одна строка: line-height
- Таблица с vertical-align
- Центрирование в строке с vertical-align
- Центрирование с vertical-align без таблиц
- Центрирование с использованием модели flexbox
- Итого
CSS margin:auto — Как это работает?
Использование margin:auto , чтобы отцентрировать блочный элемент по горизонтали, это хорошо известный способ. Но задумывались ли вы, как это работает?
Результат действия значения auto зависит типа элемента и контекста. Для отступов сверху CSS auto может означать одно из двух: занять все свободное пространство или 0 пикселей. В зависимости от этого будет задаваться различная структура.
«auto» — занять все доступное пространство
Это наиболее распространенный способ использования auto для отступов. Если мы задаем auto для левого и правого отступов одного элемента, они равномерно займут все доступное в контейнере по горизонтали пространство. Таким образом элемент расположится по центру.
Это работает только для горизонтальных отступов. Но не будет работать для плавающих и строчных элементов. А также для абсолютно и фиксировано позиционированных элементов.
Имитация плавающего поведения через распределение доступного пространства
auto поровну распределяет все свободное пространство между правым и левым отступами. Но что произойдет, если мы зададим это значение только для одного из отступов? Тогда он займет все доступное пространство, и элемент будет смещен к правому или левому краю.
«auto» — задать 0 пикселей
Как упоминалось выше, auto не работает для плавающих, строчных и абсолютно позиционированных элементов. Для них уже определена структура, так что в использовании margin auto нет смысла.
Это будет только нарушать изначальную структуру. В том числе и для отступа текста сверху CSS . Следовательно, auto будет задавать значение 0 пикселей для отступов этих элементов.
auto также не будет работать для стандартного блочного элемента, если для него не задана ширина. Во всех примерах, приведенных мной, для элементов была задана ширина.
Значение auto будет определять отступ в 0 пикселей, когда для блочного элемента задана ширина auto или 100% . Обычно он занимает всю ширину контейнера, следовательно, на ширину отступа останется 0 пикселей.
Что происходит с вертикальными отступами со значением auto?
auto и для отступа сверху CSS , и для нижнего отступа всегда вычисляется как 0 пикселей ( за исключением абсолютно позиционированных элементов ). В спецификации W3C указано следующее:
«Если для “margin-top” или “margin-bottom” задано «auto», для них используется значение, равное 0″.
Это связано с тем, что на веб-странице все элементы чаще всего распределяются вертикально. Поэтому, отцентрировав элемент по высоте в контейнере, мы не добьемся того, что он будет отображаться вертикально по центру относительно самой страницы, как это происходит с центрированием по горизонтали.
А может быть связано с той же причиной, по которой они решили добавить исключение для абсолютно позиционированных элементов, которые можно расположить по центру вертикально относительно общей высоты страницы.
Или из-за эффекта объединения отступов ( слияния отступов соседних элементов ). Это еще одно исключение из данного правила определения вертикальных отступов.
Центрирование абсолютно позиционированных элементов
Так как для абсолютно позиционированных элементов введено исключение, можно использовать значение auto , чтобы выровнять их по центру вертикально и горизонтально. Но сначала нужно выяснить, когда margin:auto будет работать именно так для отступа сверху CSS .
В другой спецификации W3C сказано:
«Если для всех трех позиций (“left”, “width” и “right”) задано значение «auto», сначала установите 0 для “margin-left” и “margin-right…»
» Если «auto» задано только для “margin-left” и “margin-right», тогда решите уравнение с дополнительным условием, чтобы для обоих отступов была задана одинаковая ширина».
Здесь довольно подробно описана ситуация, касающаяся значения auto для горизонтальных отступов. Чтобы эти отступы имели одинаковый размер, для left , width и right не должно задаваться значение auto ( их значение по умолчанию ). Чтобы отцентрировать элемент по горизонтали, нужно задать определенное значение для ширины абсолютно позиционируемого элемента, а left и right при этом должны иметь равные значения.
В спецификации также упоминается что-то подобное и для отступов сверху CSS div.
«Если для «top», «height» и «bottom» задано значение «auto» , установите для «top» позицию static…»
«Если для одной из трех позиций не установлено значение «auto»: если для «top» и «bottom» установлено значение «auto», решите уравнение с дополнительным условием, чтобы задать для этих отступов одинаковые значения».
Следовательно, чтобы отцентрировать по вертикали абсолютно позиционируемый элемент top , height и bottom не должны иметь значение auto .
Теперь, объединив все это, мы получим следующее:
Заключение
Если вам требуется сместить элемент на странице вправо или влево без контейнерных элементов ( например, как в случае с float ), помните, что есть возможность использовать для отступов значение auto .
Преобразование элемента в абсолютно позиционируемый только для того, чтобы отцентрировать его по вертикали ( отступы сверху CSS ), не лучшая идея. Существуют и другие варианты, такие как flexbox и CSS transform , которые больше подходят для этого.
Пожалуйста, оставляйте ваши комментарии по текущей теме материала. Мы очень благодарим вас за ваши комментарии, лайки, отклики, дизлайки, подписки!
Пожалуйста, оставляйте свои отзывы по текущей теме материала. За комментарии, дизлайки, лайки, подписки, отклики огромное вам спасибо!
Источник
Почему «margin: auto» не центрирует элемент по вертикали?
Как вы можете видеть в демонстрации ниже, margin: auto; центрирует синий div по горизонтали, но не по вертикали. Почему нет?
Мой вопрос не требует обходных путей.
5 ответов
Блок-боксы укладываются вертикально сверху вниз в нормальном потоке. Кроме того, вертикальные поля могут сжиматься, и только при определенных обстоятельства (в вашей демонстрации граница родительского элемента не позволит любым полям дочернего элемента сворачиваться вместе с собственными). Если у вас есть только один такой блок, а высота содержащего блока установлена автоматически, то его верхнее и нижнее поля в любом случае будут нулевыми. Но если у вас есть более одного блока блоков в одном потоке или даже блоки вне потока, влияющие на компоновку блоков входящего потока (в случае зазор, например), как вы ожидаете, что автоматические поля будут разрешены для этих входных боксов?
Вот почему автоматические левые и правые поля также обнуляются для встроенных элементов (включая атомарные встроенные элементы) и плавающих элементов (хотя горизонтальные поля никогда не сжимаются). Блоки встроенного уровня расположены вдоль линейных блоков, а также плавают. подчиняться уникальным правилам макета.
Абсолютно расположенные боксы — это совсем другая история: поскольку они никогда не знают о каких-либо других блоках в том же контексте позиционирования, что и они сами, auto верхнее и нижнее поля можно рассчитать для них относительно содержащихся в них блоков, не беспокоясь о том, что какие-либо другие блоки когда-либо будут мешать.
Flexbox — это также другая история: что отличает гибкую компоновку от блочной компоновки, так это то, что гибкие элементы по определению всегда осведомлены о других гибких элементах в том же контексте форматирования гибкости, включая тот факт, что их нет. В частности, ни поплавки не могут вторгаться в гибкий контейнер, ни вы не можете плавать элементы гибкости, чтобы подорвать это (хотя вы все равно можете полностью удалить дочерний элемент из гибкого макета с помощью абсолютное позиционирование). Отчасти из-за этого поля ведут себя по-разному у гибких элементов. См. Разделы 4.2, 9,5 и 9.6.
Почему margin:auto не работает вертикально?
На самом деле это так — но не для каждого значения display .
Если display равно flex , margin: auto центрируется как по вертикали, так и по горизонтали.
То же самое относится к display: inline-flex , display: grid и display: inline-grid .
Это из-за реальной возможности узнать истинную высоту элемента, в котором вы хотите центрировать по вертикали. Чтобы понять это, сначала подумайте о том, как работает автоматическое горизонтальное центрирование. У вас есть div, которому вы присвоили ширину (фиксированную или процентную). Ширину можно до определенной степени рассчитать. Если это фиксированная ширина, отлично. Если он гибкий или отзывчивый (в процентах), по крайней мере, у вас есть диапазон, который будет охватывать ширина до того, как достигнет следующей точки останова. Вы берете эту ширину за вычетом того, что находится внутри, и разделяете оставшуюся часть с обеих сторон.
Теперь, имея эту информацию, как браузер может вычислить бесконечное количество вариантов, в которых ваш div будет расти по вертикали? Имейте в виду, что размер элемента, перенос текста, отступы и отзывчивость также изменят ширину и заставят текст переноситься дальше, и дальше, и дальше.
Это невыполнимая задача? Не совсем так, CSS потратил время и силы на это? Думаю, не стоит их времени.
И это в основном ответ, который я говорю своим ученикам.
Но . не волнуйтесь! В альфа-версии Bootstrap v4 реализовано вертикальное центрирование!
ИЗМЕНИТЬ
Извините, что редактирую так поздно, но я подумал, что вы можете рассмотреть эти решения для вертикального центрирования, и это довольно просто, используя функцию calc
Он не центрирует элемент по вертикали, потому что это элемент блочного уровня в нормальном потоке. Таким образом, применяется следующее правило:
Если margin-top или margin-bottom равны auto , их используемое значение равно 0.
Также стоит отметить, что приведенное выше правило также применяется к следующим элементам: (см. Пункты 10.6.2 и 10.6.3 для получения дополнительной информации и условий) .
- Встроенные заменяемые элементы
- Замещенные элементы на уровне блока в нормальном потоке
- inline-block заменили элементы в нормальном потоке
- Плавающие заменяемые элементы
- Незамещаемые элементы уровня блока в нормальном потоке, когда overflow вычисляет visible
При этом абсолютно позиционированные незамещенные элементы, не имеющие значений top , height и bottom auto , являются исключением из этого правила. Следующее применяется из пункта 10.6.4:
Если ни один из трех top , height и bottom не является auto и если оба margin-top и margin-bottom равны auto , решите уравнение с дополнительным ограничением, что два поля имеют равные значения .
См. Пример ниже, демонстрирующий, как абсолютно позиционированный элемент центрируется по вертикали с помощью margin: auto . Это работает, потому что ни одно из трех свойств top , height и bottom не имеет значения auto :
Кроме того, вероятно, стоит указать на следующее правило:
Если один из margin-top или margin-bottom равен auto , решите уравнение для этого значения. Если значения чрезмерно ограничены, игнорируйте значение для bottom и решайте для этого значения.
Это означает, что если абсолютно позиционированный элемент имеет значение margin-top , равное auto , и значение margin-bottom , равное 0 (т. Е. margin: auto auto 0 ), элемент будет абсолютно расположен внизу относительно родителя, как в примере ниже:
Если «margin-top» или «margin-bottom» имеют значение «auto», их используемое значение равно 0.
Что касается фактического «почему» . вопрос действительно должен быть адресован там.
Источник
Центрирование горизонтальное и вертикальное
В CSS есть всего несколько техник центрирования элементов. Если их знать, то большинство задач решаются просто.
Горизонтальное
text-align
Для центрирования инлайновых элементов – достаточно поставить родителю text-align: center :
Для центрирования блока это уже не подойдёт, свойство просто не подействует. Например:
margin: auto
Блок по горизонтали центрируется margin: auto :
В отличие от width/height , значение auto для margin само не появляется. Обычно margin равно конкретной величине для элемента, например 0 для DIV . Нужно поставить его явно.
Значение margin-left:auto/margin-right:auto заставляет браузер выделять под margin всё доступное сбоку пространство. А если и то и другое auto , то слева и справа будет одинаковый отступ, таким образом элемент окажется в середине. Детали вычислений описаны в разделе спецификации Calculating widths and margins.
Вертикальное
Для горизонтального центрирования всё просто. Вертикальное же изначально не было предусмотрено в спецификации CSS и по сей день вызывает ряд проблем.
Есть три основных решения.
position:absolute + margin
Центрируемый элемент позиционируем абсолютно и опускаем до середины по вертикали при помощи top:50% :
Это, конечно, не совсем центр. По центру находится верхняя граница. Нужно ещё приподнять элемент на половину своей высоты.
Высота центрируемого элемента должна быть известна. Родитель может иметь любую высоту.
Если мы знаем, что это ровно одна строка, то её высота равна line-height .
Приподнимем элемент на пол-высоты при помощи margin-top :
При стандартных настройках браузера высота строки line-height: 1.25 , если поделить на два 1.25em / 2 = 0.625em .
Конечно, высота может быть и другой, главное чтобы мы её знали заранее.
Можно аналогично центрировать и по горизонтали, если известен горизонтальный размер, при помощи left:50% и отрицательного margin-left .
Одна строка: line-height
Вертикально отцентрировать одну строку в элементе с известной высотой height можно, указав эту высоту в свойстве line-height :
Это работает, но лишь до тех пор, пока строка одна, а если содержимое вдруг переносится на другую строку, то начинает выглядеть довольно уродливо.
Таблица с vertical-align
У свойства vertical-align, которое управляет вертикальным расположением элемента, есть два режима работы.
В таблицах свойство vertical-align указывает расположение содержимого ячейки.
Его возможные значения:
baseline Значение по умолчанию. middle , top , bottom Располагать содержимое посередине, вверху, внизу ячейки.
Например, ниже есть таблица со всеми 3-мя значениями:
Обратим внимание, что в ячейке с vertical-align: middle содержимое находится по центру. Таким образом, можно обернуть нужный элемент в таблицу размера width:100%;height:100% с одной ячейкой, у которой указать vertical-align:middle , и он будет отцентрирован.
Но мы рассмотрим более красивый способ, который поддерживается во всех современных браузерах, и в IE8+. В них не обязательно делать таблицу, так как доступно значение display:table-cell . Для элемента с таким display используются те же алгоритмы вычисления ширины и центрирования, что и в TD . И, в том числе, работает vertical-align :
Этот способ замечателен тем, что он не требует знания высоты элементов.
Однако у него есть особенность. Вместе с vertical-align родительский блок получает табличный алгоритм вычисления ширины и начинает подстраиваться под содержимое. Это не всегда желательно.
Чтобы его растянуть, нужно указать width явно, например: 300px :
Можно и в процентах, но в примере выше они не сработают, потому что структура таблицы «сломана» – ячейка есть, а собственно таблицы-то нет.
Это можно починить, завернув «псевдоячейку» в элемент с display:table , которому и поставим ширину:
Если дополнительно нужно горизонтальное центрирование – оно обеспечивается другими средствами, например margin: 0 auto для блочных элементов или text-align:center на родителе – для других.
Центрирование в строке с vertical-align
Для инлайновых элементов ( display:inline/inline-block ), включая картинки, свойство vertical-align центрирует сам инлайн-элемент в окружающем его тексте.
В этом случае набор значений несколько другой:
Это можно использовать и для центрирования, если высота родителя известна, а центрируемого элемента – нет.
Допустим, высота внешнего элемента 120px . Укажем её в свойстве line-height :
Работает во всех браузерах и IE8+.
Свойство line-height наследуется, поэтому надо знать «правильную» высоту строки и переопределять её для inner .
Центрирование с vertical-align без таблиц
Если центрирование должно работать для любой высоты родителя и центрируемого элемента, то обычно используют таблицы или display:table-cell с vertical-align .
Если центрируются не-блочные элементы, например inline или inline-block , то vertical-align может решить задачу без всяких таблиц. Правда, понадобится вспомогательный элемент (можно через :before ).
- Перед центрируемым элементом помещается вспомогательный инлайн-блок before , занимающий всю возможную высоту.
- Центрируемый блок выровнен по его середине.
Для всех современных браузеров и IE8 можно добавить вспомогательный элемент через :before :
В пример выше добавлено также горизонтальное центрирование text-align: center . Но вы можете видеть, что на самом деле внутренний элемент не центрирован горизонтально, он немного сдвинут вправо.
Это происходит потому, что центрируется весь текст, а перед inner находится пробел, который занимает место.
- Убрать лишний пробел между div и началом inner , будет
Центрирование с использованием модели flexbox
Данный метод поддерживается всеми современными браузерами.
- Не требуется знания высоты центрируемого элемента.
- CSS чистый, короткий и не требует дополнительных элементов.
- Не поддерживается IE9-, IE10 поддерживает предыдущую версию flexbox.
Итого
Обобщим решения, которые обсуждались в этой статье.
Для горизонтального центрирования:
- text-align: center – центрирует инлайн-элементы в блоке.
- margin: 0 auto – центрирует блок внутри родителя. У блока должна быть указана ширина.
Для вертикального центрирования одного блока внутри другого:
Если размер центрируемого элемента известен, а родителя – нет
Родителю position:relative , потомку position:absolute; top:50% и margin-top:- . Аналогично можно отцентрировать и по горизонтали.
Если нужно отцентрировать одну строку в блоке, высота которого известна
Поставить блоку line-height: . Нужны конкретные единицы высоты ( px , em …). Значение line-height:100% не будет работать, т.к. проценты берутся не от высоты блока, а от текущей line-height .
Высота родителя известна, а центрируемого элемента – нет.
Поставить line-height родителю во всю его высоту, а потомку поставить display:inline-block .
Высота обоих элементов неизвестна.
- Сделать элемент-родитель ячейкой таблицы при помощи display:table-cell (IE8) или реальной таблицы, и поставить ему vertical-align:middle . Отлично работает, но мы имеем дело с таблицей вместо обычного блока.
- Решение со вспомогательным элементом outer:before и инлайн-блоками. Вполне универсально и не создаёт таблицу.
- Решение с использованием flexbox.
Источник