Ещё одна коллекция интересных фактов про CSS-гриды (CSS Grid Layout)

Перевод статьи Another Collection of Interesting Facts About CSS Grid с сайта css-tricks.com для CSS-live.ru, автор — Мануэль Матузович

В прошлом году я собрал коллекцию интересных фактов о CSS Grid Layout после моего мастер-класса. В этом году я работал над другим мастер-классом и узнал ещё несколько увлекательных фактов о нашей любимой спецификации раскладки.

Я не жадный, поэтому ещё раз с радостью поделюсь своими знаниями и выводами с вами, с сообществом CSS-Tricks.

Как работает сокращённая запись grid

Читать и понимать спецификацию гридов — да, впрочем, и любую другую — порой бывает крайне сложно

К примеру, я только спустя какое-то время понял, как правильно использовать сокращённую запись grid:

<‘grid-template’> | <‘grid-template-rows’> / [ auto-flow && dense? ] <‘grid-auto-columns’>? | [ auto-flow && dense? ] <‘grid-autwo-rows’>? / <‘grid-template-columns’>

Это можно понять, если специально уделить этому время или если постоянно читать спецификации. Я перебрал несколько комбинаций — и всё без толку. В итоге мне помогло примечание из спецификации.

Заметьте, что в одном объявлении grid можно указывать только свойства явного или неявного грида.

У Рэйчел Эндрю есть серия статей, которая помогает понять, как читать спецификацию на примере CSS-гридов.

Таким образом, в сокращённой записи grid можно указать множество свойств, просто не все сразу.

Использование grid вместо grid-template

Свойство grid-template — сокращённая запись для grid-template-columns, grid-template-rows и grid-template-areas в одном объявлении. Можно сделать то же самое с помощью сокращённой записи grid, которая немного короче.

grid: "one one" 200px 
      "two four" 
      "three four" 
      / 1fr 2fr;
/* сокращённая запись для */
/*
  grid-template-areas: "one one" "two four" "three four";
  grid-template-rows: 200px;
  grid-template-columns: 1fr 2fr;
*/

Эта сокращённая запись создаёт три ряда и две колонки с четырьмя именованными грид-областями. У первого ряда выставлена явная высота 200px, а у второго и третьего ряда стоит неявная высота auto. Ширина первой колонки равна 1fr, а ширина второй — 2fr.

See the Pen grid shorthand — areas, explicit rows and columns by Manuel Matuzovic (@matuzo) on CodePen.

Хотите узнать больше о разнице между явным и неявным гридом? Прочитайте мою статью, здесь на CSS-Tricks.

Нам не обязательно указывать области, если они не нужны. Можно использовать сокращённую запись grid только для определения явных рядов и колонок. Следующие два куска кода по сути делают одно и то же:

grid-template-rows: 100px 300px;
grid-template-columns: 3fr 1fr;
grid: 100px 300px / 3fr 1fr;

Управление неявными рядами и колонками

Сокращённую запись grid также можно использовать для указания grid-auto-flow, но это работает не совсем так, как ожидалось. Мы не просто добавляем ключевое слово row или column где-то в объявлении. Вместо этого нам придётся использовать ключевое слово auto-flow с правильной стороны слеша.

Находясь слева от слеша, сокращённая запись задаёт для grid-auto-flow значение row и создаёт явные колонки.

grid: auto-flow / 200px 1fr;

/* сокращённая запись для */
/*
  grid-auto-flow: row;
  grid-template-columns: 200px 1fr;
*/

Справа от слеша сокращённая запись задаёт grid-auto-flow значение column и создаёт явные ряды.

grid: 100px 300px / auto-flow;

/* сокращённая запись для */
/*
  grid-template-rows: 100px 300px;
  grid-auto-flow: column;
*/

Можно также установить размер неявных полос вместе с ключевым словом auto-flow, которое устанавливает grid-auto-rows или grid-auto-columns в указанное значение.

grid: 100px 300px / auto-flow 200px;

/* сокращённая запись для */
/*
  grid-template-rows: 100px 300px;
  grid-auto-flow: column;
  grid-auto-columns: 200px;
*/

See the Pen grid shorthand — explicit rows and implicit columns by Manuel Matuzovic (@matuzo) on CodePen.

Директива @supports в Edge

Проверка поддержки CSS Grid работает отлично с помощью директивы @supports, поскольку все браузеры с поддержкой Grid также понимают и @supports. А значит можно проверить, какую из спецификаций поддерживает браузер: новую, старую, или обе сразу. Обе? Edge 16 и выше поддерживает не только новую спецификацию, но также и старую.

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

/* Edge 16 и выше */
@supports (display: -ms-grid) and (display: grid) {
  div {
    width: auto;
  }
}

/* Edge 15 и ниже */
@supports (display: -ms-grid) and (not (display: grid)) {
  div {
    margin: 0
  }
}

Вот небольшая демонстрация, которая показывает, какая директива @supports срабатывает в браузере, в котором вы её открыли.

See the Pen display: grid support test by Manuel Matuzovic (@matuzo) on CodePen.

К слову: не стоит слишком увлекаться определением браузера через @supports, потому что писать код под конкретный браузер само по себе плохо.

Указание точного количества элементов на колонку

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

Скажем, есть список из 11 элементов, в который нужно добавить новую колонку после каждого четвёртого элемента. Первое, что нужно сделать после установки display: grid на родительском элементе — изменить работу алгоритма auto-placement. По умолчанию, он заполняет каждый ряд по очереди, добавляя новые ряды, если нужно. С grid-auto-flow: column он будет заполнять по очереди уже не ряды, а колонки. И напоследок нужно указать количество элементов на колонку. Это можно сделать, определив максимально необходимое количество рядов с помощью свойства grid-template-rows. Можно установить высоту каждому ряду явно или сделать их размером по содержимому, используя ключевое слово auto.

ul {
  display: grid;
  grid-template-rows: auto auto auto auto;

  /* или короче и легче для чтения */
  /* grid-template-rows: repeat(4, auto); */
  grid-auto-flow: column;
}

Если придётся изменить количество элементов на 5, мы просто добавим ещё одну полосу в список или воспользуемся нотацией repeat, изменив первый параметр на нужное значение (grid-template-rows: repeat(5, auto)).

See the Pen Limited number of items per column by Manuel Matuzovic (@matuzo) on CodePen.

Прижатый подвал с помощью CSS Grid

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

Возьмём «классическую» структуру страницы: шапка, основной контент и подвал.

<body>
  <header>HEADER</header>
  <main>MAIN</main>
  <footer>FOOTER</footer>
</body>

Первым делом установим высоту для html и body как минимум 100% от окна браузера, чтобы убедиться, что страница всегда занимает всю вертикальную область. Затем поделим body на три ряда с помощью grid-template-rows. Первый (шапка) и последний (подвал) ряды могут быть какого нам угодно размера. Ряд в середине (основной контент) должен всегда заполнять остальную область. Нам не придётся высчитывать высоту, поскольку это берёт на себя единица fr.

html {
  height: 100%;
}

body {
  min-height: 100%;
  display: grid;
  grid-template-rows: auto 1fr auto;
}

В результате основная область страницы растягивается, а подвал подстраивается под неё, оставаясь внизу окна браузера.

See the Pen CSS Grid Layout Sticky Footer by Manuel Matuzovic (@matuzo) on CodePen.

Автоматический минимальный размер грид-элементов

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

Исходная ситуация — трёхколоночный грид с абзацем в каждом грид-элементе.

<div class="grid">
  <div class="item">
    <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Quo ipsum exercitationem voluptate, autem veritatis enim soluta beatae odio accusamus molestiae, perspiciatis sunt maiores quam. Deserunt, aliquid inventore. Ullam, fugit dicta.
    </p>
  </div>
</div>
.grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-gap: 20px;
}

Каждый абзац должен быть однострочным и если он длинее родительского элемента, то отображать многоточие в конце. Для решения этой задачи Флориан задал white-space:nowrap, заставив текст быть однострочным, скрыл переполнение и поставил text-overflow: ellipsis.

p {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

Это отлично работало бы в блочном элементе, но в этом примере с гридом колонки растягиваются до ширины однострочного абзаца:

See the Pen Automatic minimum size of grid items by Manuel Matuzovic (@matuzo) on CodePen.

В общем, это происходит потому, что грид-элемент не может быть меньше его дочерних элементов. По умолчанию у min-width грид-элемента (или флекс-элемента) стоит auto, что согласно спецификации:

… применяет автоматический минимальный размер по указанной оси грид-элемента, у которого overflow имеет значение visible и который охватывает хотя бы одну полосу, функция минимального размера которой — auto.

Это придаёт грид- и флекс-элементам дополнительную гибкость, но не всегда желательно, чтобы контент растягивал ширину родительских элементов. Во избежание этого, можно также изменить свойство overflow грид-элемента на что-то отличное от visible или установить min-width в 0.

Чтобы лучше разобраться в механизме автоматического минимального размера грид-элементов, смотрите спецификацию по гридам:

Заключение

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

P.S. Это тоже может быть интересно:

3

Комментарии

  1. Вадим Макеев

    Матузович, всё же. Он сам так представляется.

    1. Максим Усачев (Автор записи)

      Спасибо, исправил!

  2. Petro Shkurateniuk

    Стоит обратить внимание что grid-template-areas не работает в IE Edge (совсем). Понимаю что многим не важно, но в enterprise проектах прийдется дописать еще

    -ms-grid-row: 2;
    -ms-grid-column: 3;

    для каждой area

Оставить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Ваш E-mail не будет опубликован

Получать новые комментарии по электронной почте. Вы можете подписаться без комментирования.