company_banner

Всё о ключевом слове auto в CSS

Автор оригинала: Ahmad Shadeed
  • Перевод
В CSS есть ключевое слово auto, которое можно использовать при работе с различными свойствами элементов. Это — свойства, влияющие на позицию, высоту, ширину элементов. Это — свойства, предназначенные для настройки отступов элементов и других их характеристик. У меня появилось желание где-нибудь записать всё то, что я знаю об auto. Например — оформить это всё в виде материала, который мог бы стать справочником для тех, кто интересуется тонкостями использования этого ключевого слова.

Ключевое слово auto имеет особый смысл при использовании его с различными CSS-свойствами. Мы разберём особенности auto, касающиеся применения этого значения к различным свойствам.



Здесь, в первую очередь, нас будут интересовать технические детали работы auto. Поговорим мы и о том, как извлечь максимум пользы из применения этого свойства. Тут вы найдёте и заметки о сценариях использования auto, и примеры.

Свойство width: auto


Исходной шириной блочных элементов, таких, как <div> или <p>, является значение auto. Это приводит к тому, что такие элементы занимают всё горизонтальное пространство содержащего их блока.

«Ширина блока, содержащего элемент» — это, в соответствии со спецификацией CSS, значение, вычисляемое по следующей формуле:

‘margin-left’ + ‘border-left-width’ + ‘padding-left’ + ‘width’ + ‘padding-right’ + ‘border-right-width’ + ‘margin-right’

Когда ширина элемента задана значением auto, у него могут быть настроены такие свойства, как margin, padding, border, и он, при этом, не будет больше своего родительского элемента. Шириной блока, ограничивающего содержимое блочного элемента, будет размер содержимого за вычетом ширины его частей, задаваемых свойствами margin (поле, внешний отступ), padding (внутренний отступ) и border (граница).


Сравнение width: auto и width: 100%

Рассмотрим, в качестве примера, особенности устройства вышеприведённых макетов.

Вот HTML-разметка:

<div class="wrapper">
  <div class="item"></div>
</div>

Вот CSS-код:

* {
    box-sizing: border-box;
}

.wrapper {
      max-width: 600px;
      margin: 2rem auto 0;
      padding: 1rem;
}

.item {
      padding: 1rem;
      margin: 0 50px;
      border: 15px solid #1f2e17;
}

Тут всё выглядит как надо, содержимое ограничено родительским элементом.


Элемент находится в пределах родительского элемента

А что произойдёт в том случае, если указать, что ширина элемента (width) должна быть задана не в виде значения auto, а как 100%? При таком подходе элемент займёт 100% ширины родительского элемента, к которой будет добавлено пространство, отводимое на правое и левое поля. Вот соответствующий стиль:

.item {
      width: 100%;
      padding: 1rem;
      margin: 0 50px;
      border: 15px solid #1f2e17;
}

А вот что получится после его применения к элементу.


Элемент выходит за пределы родительского элемента (направление текста — ltr)

Ширина элемента составляет 568px. Она вычисляется так:

‘border-left-width’ + ‘padding-left’ + ‘width’ + ‘padding-right’ + ‘border-right-width’ = 15 + 16 + 506 + 16 + 15 = 568px

Если свойство direction установлено в значение ltr, то значение margin-right будет полностью игнорироваться. В нашем случае именно это и происходит. Однако если в direction записано rtl, игнорироваться будет margin-left.


Элемент выходит за пределы родительского элемента (направление текста — rtl)

Здесь можно поэкспериментировать с кодом примера.

▍Сценарии использования width: auto


Для того чтобы как следует разобраться со значением auto, недостаточно рассказа об основах. Поэтому я провёл некоторые изыскания, направленные на то, чтобы показать сценарии практического использования свойства width: auto.

Разная ширина элементов в мобильной и настольной версиях страницы



Мобильный и настольный варианты приложения

Имеется группа кнопок. Нужно, чтобы в мобильной версии приложения они были бы расположены рядом друг с другом (элемент, заключающий в себе кнопку, должен занимать 50% родительского элемента). В настольной версии приложения каждая кнопка должна занимать всю ширину контейнера-родителя. Как это сделать?

Вот HTML-разметка:

<div class="group">
    <div class="group__item">
        <button class="c-button">Sign In</button>
    </div>
    <div class="group__item">
        <button class="c-button c-button--ghost">Register</button>
    </div>
</div>

Для того чтобы разместить кнопки рядом друг с другом в мобильном варианте страницы, я воспользовался flexbox-макетом. Вот соответствующий CSS:

.group {
    display: flex;
}

.group__item {
    width: 50%;
}

В настольной версии мне нужно, чтобы кнопки занимали бы всю ширину родительского элемента. Тут может возникнуть соблазн использовать конструкцию width: 100%. Правда? Но есть и более удачное решение:

@media (min-width: 800px) {
    /* Преобразуем обёртку из flexbox-элемента в блочный элемент */
    .group {
        display: block;
    }

    .group__item {
        width: auto;
    }
}

Так как .group__item — это блочный элемент, использование width: auto приводит к тому, что этот элемент отлично заполняет собой место, доступное в его родительском элементе.

Вот рабочий вариант этого примера.

Свойство height: auto


Если рассматривать работу со свойством height, задающим высоту элементов, то всё выглядит иначе. Высота элемента, при применении значения auto, соответствует высоте содержимого элемента.

Рассмотрим следующий пример:

<div class="wrapper">
  <div class="item">What's my height?</div>
</div>

Для того чтобы элемент с классом .item занял бы всю высоту контейнера, можно воспользоваться одним из следующих приёмов:

  1. Можно задать элементу с классом .wrapper фиксированную высоту, а затем добавить к стилю элемента .item свойство height: 100%.
  2. Можно воспользоваться для элемента .wrapper flexbox-макетом, благодаря чему дочерний элемент .item будет, по умолчанию, растянут до размеров родительского элемента.

Вот CSS-код:

.wrapper {
    height: 200px;
}

.item {
    height: 100%;
}


Родительский и дочерний элементы

Поля и ключевое слово auto


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

Рассмотрим пример.


Элемент, который надо выровнять по центру

Синий прямоугольник нуждается в горизонтальном выравнивании по центру. Для этой цели можно воспользоваться следующим стилем:

.element {
    margin-left: auto;
    margin-right: auto;
}

Обратимся к спецификации CSS:

Если свойства ‘margin-left’ и ‘margin-right’ установлены в значение ‘auto’, ширина полей оказывается одинаковой. Это приводит к горизонтальной центровке элемента относительно краёв включающего его в себя блока.


Поля элемента имеют одинаковую ширину

Вот демонстрация этого примера.

▍Использование свойства margin: auto для абсолютно позиционированных элементов



Центрованный элемент

Ещё один, менее распространённый, сценарий применения значения auto заключается в центровке абсолютно позиционированных элементов с использованием конструкции margin: auto. Если имеется элемент, который нужно отцентровать внутри родительского элемента и по горизонтали, и по вертикали, может показаться, что для этого надо воспользоваться свойством translateX или translateY.

Для того чтобы свойство margin: auto позволило бы нам соответствующим образом выровнять элемент, нужно, чтобы были бы выполнены следующие условия:

  1. Заданы ширина и высота элемента.
  2. Задано свойство элемента position: absolute.

Вот HTML-разметка:

<div class="wrapper">
  <div class="item">I am centered.</div>
</div>

Вот код стилей:

.wrapper {
    position: relative;
}

.item {
    width: 200px;
    height: 100px;
    position: absolute;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    margin: auto;
}

Вот демонстрация этой методики выравнивания элементов.

Flexbox-макеты и автоматическая настройка полей


Использование автоматически настраиваемых полей может, в некоторых случаях, оказаться весьма полезным приёмом. Если дочерний элемент имеет поле, размеры которого заданы с использованием значения auto, он, в родительском элементе, будет максимально смещён в сторону, противоположную настроенному полю. Например, если flex-элементу назначено свойство margin-left: auto, он будет максимально смещён вправо.

Посмотрим на следующий макет. Тут есть два прямоугольных дочерних элемента, находящихся в родительском flexbox-элементе.


Пара элементов во flexbox-контейнере

Нам нужно, чтобы элемент №2 был бы перемещён к правой границе контейнера. Для этого отлично подходит использование значения auto для свойства margin-left:

.wrapper {
    display: flex;
}

.item-2 {
    margin-left: auto;
}

Вот что получилось после применения такого стиля.


Элемент №2 перемещён к правому краю контейнера

Надо отметить, что этот приём работает и при вертикальном выравнивании элементов. Применим в данном примере следующий стиль элемента №2:

.item-2 {
    margin-top: auto;
}

Вот что получится.


Элемент №2 перемещён к нижнему краю контейнера

Кроме того, если имеется лишь один дочерний элемент, то для того, чтобы выровнять его и по горизонтали, и по вертикали, можно воспользоваться свойством margin: auto. Предположим, в контейнере имеется лишь элемент №1, который нужно выровнять именно так. Для этого воспользуемся таким стилем:

.item-1 {
    margin: auto;
}

Этого достаточно для центровки элемента.


Элемент №1 выровнен по центру контейнера

▍Свойство flex и значение auto


При разработке flexbox-макетов можно пользоваться, для дочерних элементов, свойством flex: auto. Что означает подобная конструкция? Дело в том, что когда у дочернего элемента имеется свойство flex: auto, это равносильно тому, что элементу назначен стиль flex: 1 1 auto, аналогичный следующей конструкции:

    .item {
        flex-grow: 1;
        flex-shrink: 1;
        flex-basis: auto;
    }

Вот что об этом сказано на MDN: «Размеры элемента определяются в соответствии с его свойствами width и height, но элемент может растягивается, занимая дополнительное свободное пространство, доступное во flex-контейнере. Элемент, для того, чтобы поместиться в контейнер, может и сжимается до своего минимального размера. Это аналогично установке стиля flex: 1 1 auto».

Другими словами, размер элемента со свойством flex: auto будет задан, основываясь на его ширине и высоте. Но этот элемент может растягиваться или сжиматься в зависимости от того, какое пространство доступно ему в контейнере. Я об этом не знал до тех пор, пока не занялся исследованиями для этой статьи.

Как обычно, рассмотрим пример.

Вот разметка:

<div class="wrapper">
  <div class="item item-1">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
</div>

Вот стили:

.wrapper {
    display: flex;
    flex-wrap: wrap;
}

.item {
    width: 120px;
    height: 500px;
}

.item-1 {
    flex: auto;
}

А вот — результат.


Использование flex: auto

Вот рабочий вариант этого примера.

Grid-макеты и значение auto


▍Использование значения auto при настройке столбцов



Использование стиля grid-template-columns: auto 1fr 1fr

При разработке Grid-макетов можно использовать значение auto при настройке столбцов. Это будет означать, что ширина столбцов будет зависеть от размеров их содержимого. Вот что я имею в виду:

.wrapper {
    display: grid;
    grid-template-columns: auto 1fr 1fr;
}

▍Grid-макеты и использование значения auto для настройки полей


При использовании Grid-макетов значение auto может быть использовано для настройки полей элементов. Делается это для получения результатов, похожих на те, что достигались при использовании auto во Flexbox-макетах. Если мы работаем с Grid-макетом, и один из элементов сетки имеет, например, стиль margin-left: auto, он будет перемещён в правую часть макета, а его ширина будет подобрана на основе размеров его содержимого.

Рассмотрим следующий пример.


Grid-макет

Нам нужно, чтобы ширина элемента Item 1 зависела бы от его содержимого, а не от доступного ему пространства сетки. Для этого мы можем воспользоваться следующим стилем:

    .item-1 {
        margin-left: auto;
    }

Вот результат применения этого стиля.


Ширина элемента зависит от его содержимого

▍RTL-макеты


Стоит отметить, что использование свойств margin-left: auto или margin-right: auto хорошо показывает себя для LTR-макетов (для макетов, в которых содержимое расположено слева направо), например, для таких, которые используются для вывода текстов, написанных на английском. Но знайте о том, что на многоязычных сайтах эти значения меняются местами. Ещё лучше, и я бы порекомендовал поступать именно так, пользоваться в таких макетах Flexbox- или Grid-свойствами, делая это в тех случаях, когда поставленной цели можно достичь с их помощью. Если этого с помощью таких свойств добиться нельзя, прибегайте к настройке margin-свойств с использованием auto только в крайнем случае. Вместо них лучше применять логические свойства CSS.

Свойство overflow


Работая с элементами веб-страниц, нам нужно знать о размерах содержимого, которое способны вмещать эти элементы. Если содержимое оказывается больше того, что способен вместить элемент, нужно, для работы с таким содержимым, показать полосу прокрутки.

Для решения этой задачи можно попытаться воспользоваться следующим стилем:

.element {
    overflow-y: scroll;
}

Но при таком подходе полоса прокрутки может появиться даже в том случае, если в элементе выводится содержимое, размер которого не превышает размеров элемента. Вот пример.


Элемент, которому назначен стиль overflow-y: scroll

В браузере Chrome на платформе Windows полоса прокрутки выводится всегда. Это — пример неправильного поведения элемента, которое способно запутать пользователя.

Использование вместо этого значения auto позволяет добиться того, что полоса прокрутки будет выводиться лишь в тех случаях, когда высота содержимого превышает высоту контейнера.

На MDN об этом сказано следующее: «Зависит от пользовательского агента. Если содержимое помещается в область элемента, соответствующую внутреннему пространству элемента, оно выглядит так же, как содержимое, выводимое в режиме visible, но при этом создаётся новый блочный контекст форматирования. Настольные браузеры выводят полосы прокрутки в том случае, если размеры содержимого превышают размеры элемента».

Свойства, отвечающие за позиционирование элементов


CSS-свойства, отвечающие за позиционирование элементов, такие, как top, right, bottom и left, поддерживают значение auto. То, о чём я хочу сейчас рассказать, я узнал в ходе написания этой статьи.

Рассмотрим следующий макет.


Демонстрационный макет

Здесь имеется родительский элемент с настроенным свойством padding, задающим внутренний отступ. В этом элементе расположен ещё один элемент, дочерний. Дочерний элемент позиционирован абсолютно, но его свойства, отвечающие за позиционирование, не настроены. Вот стили:

.wrapper {
    position: relative;
    padding: 16px;
}

.item {
    position: absolute;
    width: 100px;
    height: 100px;
}

Дело в том, что в CSS у каждого свойства имеется некое исходное значение (значение, задаваемое по умолчанию). Если исследовать дочерний элемент и взглянуть на вычисленные стили, то каким будет значение его свойства left?


Исследование вычисленных стилей дочернего элемента

Значение, задаваемое по умолчанию для свойства left — это 16px. Откуда оно взялось, если мы его даже не задавали? Причина этого заключается в том, что свойства абсолютно позиционированного элемента согласуются с его ближайшем родителем, у которого задано свойство position: relative. У родительского элемента есть свойство padding: 16px. Это приводит к тому, что дочерний элемент размещается в 16 пикселях от верхней и левой сторон родительского элемента. Интересно, правда?

Теперь у вас может появиться вопрос о том, какая нам от этого польза. Предлагаю с этим разобраться.

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

Вот стиль, подходящий для маленьких экранов:

.wrapper {
    position: relative;
}

.item {
    position: absolute;
    left: 100px;
    width: 100px;
    height: 100px;
}

Как сбросить значение свойства left при просмотре страницы на больших экранах? Причём, значение left: 0 тут использовать нельзя, так как это приведёт к тому, что дочерний элемент прижмётся к краю родительского элемента, а нам это не нужно. Взгляните на макет страницы, показанный ниже. Он разъясняет мою мысль.


Дочерний элемент ведёт себя неправильно

Для сброса свойств позиционирования дочернего элемента следует использовать конструкцию left: auto. На MDN об этом говорится следующее: «Элемент размещается по горизонтали так, как он должен был бы быть позиционирован в том случае, если бы был статическим элементом».

Это означает, что при размещении элемента будет учитываться свойство padding родительского элемента, и будет обеспечиваться то, что дочерний элемент не «прилипнет» к краю родительского элемента.

Вот CSS-код:

.item {
    position: absolute;
    left: 100px;
    width: 100px;
    height: 100px;
}

@media (min-width: 800px) {
    .item {
        /* Это - эквивалент left: 16px */
        left: auto;
    }
}

То же самое применимо и к свойству top. Вычисленные значения свойств right и bottom, задаваемые по умолчанию, эквивалентны, соответственно, ширине и высоте элемента.

Вот демонстрационный проект к этому разделу.

Примеры использования значения auto


Сразу скажу, что приведённые здесь примеры не охватывают всех возможностей значения auto, но я надеюсь, что то, о чём я расскажу, вам пригодится.

▍Стрелка всплывающей подсказки


При создании всплывающих подсказок нужно, чтобы у них была бы стрелка, указывающая на тот объект, к которому относится подсказка. Так эти подсказки оказываются более понятными. В том случае, если мы занимаемся разработкой дизайн-системы, нам нужно предусмотреть разные состояния подсказок. Например, подсказки со стрелкой, указывающей налево, и со стрелкой, указывающей направо.


Стрелки подсказок, направленные в разных направлениях

.tooltip:before {
    /* Код стрелки */
    position: absolute;
    left: -15px;
}

/* Версия подсказки со стрелкой, направленной вправо */
.tooltip.to-right:before {
    /* Код стрелки */
    position: absolute;
    left: auto;
    right: -15px;
}

Обратите внимание на то, что я воспользовался свойством left: auto для переопределения свойства left: -15px в исходной реализации. И, чтобы вы знали, подобное используется весьма часто. Поэтому я порекомендовал бы вместо вышеописанного подхода пользоваться следующим:

.tooltip:before {
    position: absolute;
    right: 100%;
}

.tooltip.to-right:before {
    /* Код стрелки */
    position: absolute;
    right: auto;
    left: 100%;
}

Используя значение 100%, мы уходим от применения жёстко заданного значения (ширины стрелки), которое может привести к неправильной работе системы в том случае, если изменится размер стрелки. Это решение лучше приспособлено к возможным будущим изменениям.

▍Компонент-карточка


Возможно, в вашем проекте имеется компонент-карточка, на котором, в левом верхнем углу расположен какой-нибудь значок. Он может играть декоративную роль, а может представлять собой кнопку для выполнения некоего действия. Вне зависимости от роли значка компонент нужно проектировать так, чтобы значок можно было бы расположить и в его левом верхнем углу, и в его правом верхнем углу. Вот как это выглядит.


Компонент-карточка со значком, который расположен в разных углах

Используя свойство left: auto можно легко сбросить значение свойства, заданного в его базовой реализации. Вот CSS-код:

.card .icon {
    position: absolute;
    left: 15px;
    top: 15px;
}

.card.is-right .icon {
    left: auto;
    right: 15px;
}

▍Flexbox-макеты и значение auto свойства margin


Flexbox-макеты дают веб-разработчику поистине безграничные возможности. Комбинируя возможности таких макетов с полями, при настройке которых используется значение auto, мы можем создавать весьма мощные макеты.

Рассмотрим следующий пример.


Автоматическая настройка полей элементов

Тут имеется вертикальный контейнер, содержащий заголовок элемента, его описание и кнопку, расположенную справа. Нам нужно, чтобы кнопка была бы привязана к правой части контейнера.

Вот разметка:

<div class="item">
    <div class="item-group">
        <!-- Заголовок и описание -->
    </div>
    <button class="item__action">Confirm</button>
</div>

Вот стили:

    .item {
        display: flex;
        flex-wrap: wrap;
        justify-content: space-between;
    }

    .item__action {
        margin-left: auto;
    }

Готово! Использование свойства margin-left: auto позволяет поместить кнопку в правом верхнем углу элемента. А ещё приятнее то, что мы можем воспользоваться логическими CSS-свойствами в том случае, если разрабатываем многоязычный сайт. CSS-код будет примерно таким:

.item__action {
    margin-inline-start: auto;
}

Если вы хотите больше узнать о RTL-стилизации — вот полезный ресурс, посвящённый этой теме.

▍Grid-макеты и значение auto свойства margin


Настраивая поля Grid-элементов, можно задавать фиксированные и процентные значения, а также — можно пользоваться значением auto. Меня особенно интересует значение auto. Взгляните на следующий макет.


Grid-макет

Вот фрагмент разметки:

<p class="input-group">
    <label for="">Full Name</label>
    <input type="email" name="" id="">
</p>

Вот — стили:

.input-group {
  display: grid;
  grid-template-columns: 1fr;
  grid-gap: 1rem;

  @media (min-width: 700px) {
    grid-template-columns: 0.7fr 2fr;
  }
}

Мне хотелось бы выровнять подписи, элементы label, по левому краю полей для ввода данных (элементов input). Для того чтобы это сделать, нужно применить следующий стиль:

.input-group label {
    margin-left: auto;
}

Применение этого стиля приведёт к результату, показанному на следующем рисунке.


Выравнивание подписей по левому краю полей для ввода данных

▍Проектирование модальных окон



Модальное окно

Работая над дизайном модальных окон важно учитывать то, что содержимое, которое понадобится отобразить в окне, может целиком в него не поместиться. Для того чтобы окно нормально работало бы в такой ситуации, можно воспользоваться следующим стилем:

.modal-body {
    overflow-y: auto;
}

Благодаря такому стилю полоса прокрутки появится только в том случае, если содержимое окна окажется достаточно большим.

Итоги


В этом материале мы рассмотрели особенности применения ключевого слова auto в CSS. Надеемся, вам пригодится то, о чём вы сегодня прочли.

Уважаемые читатели! В каких ситуациях вы пользуетесь значением auto в CSS?

RUVDS.com
VDS/VPS-хостинг. Скидка 10% по коду HABR

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

    +1
    Удивительно сколько нюансов в себе содержит, как казалось бы, простое задание ширины объекта. Отличная статья. Спасибо за перевод.
      +1
      Мне понравилось. По крайней мере все аккуратно по полочкам и с примерами из жизни
        0
        Товарищи, подскажите зачем в последнее время заголовки имеют вид «Всё о ...» или «Всё, что вам нужно знать о ...», ведь всё сказать или знать не возможно. Какой смысл слова «всё» в подобных заголовках? Например в этой статье сказано не всё, например не о всех возможных свойствах со значением auto, и не обо всех нюансах значения auto.
          0
          Очень часто так свои материалы называют сами авторы. Но спасибо за фидбек, учтем.

        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

        Самое читаемое