Подкаст CSS - 011: Сетка
Наиболее распространенной компоновкой в веб-дизайне является макет, состоящий из заголовка, боковой панели, основного текста и нижнего колонтитула.
На протяжении многих лет было много методов решения этой компоновки, но с CSS Grid это не только относительно просто, но и у вас есть множество вариантов. Grid исключительно полезен для объединения контроля, который обеспечивает внешний размер, с гибкостью внутреннего размера, что делает его идеальным для такого вида компоновки. Это потому, что grid — это метод компоновки, разработанный для двумерного контента. То есть, размещение вещей в строках и столбцах одновременно.
При создании макета сетки вы определяете сетку со строками и столбцами. Затем вы размещаете элементы в этой сетке или позволяете браузеру автоматически размещать их в созданных вами ячейках. Сетка — это много чего, но с обзором того, что доступно, вы сможете создавать макеты сетки в кратчайшие сроки.
Обзор
Итак, что можно сделать с помощью сетки? У макетов сетки есть следующие особенности. Вы узнаете обо всех них в этом руководстве.
- Сетку можно определить с помощью строк и столбцов. Вы можете выбрать, как задать размер этих треков строк и столбцов, или они могут реагировать на размер содержимого.
- Прямые дочерние элементы контейнера сетки будут автоматически помещены в эту сетку.
- Или вы можете разместить предметы именно в том месте, где вам удобно.
- Для облегчения размещения линий и областей на сетке можно присваивать им названия.
- Свободное пространство в сетчатом контейнере можно распределить между дорожками.
- Элементы сетки можно выравнивать в пределах своей области.
Терминология сетки
Сетка поставляется с целым рядом новых терминов, поскольку впервые в CSS появилась настоящая система компоновки.
Линии сетки
Сетка состоит из линий, которые идут горизонтально и вертикально. Если ваша сетка имеет четыре столбца, она будет иметь пять линий столбцов, включая ту, которая следует за последним столбцом.
Строки нумеруются, начиная с 1, с нумерацией, соответствующей режиму письма и направлению скрипта компонента. Это означает, что строка столбца 1 будет слева в языке с письмом слева направо, например, английском, и справа в языке с письмом справа налево, например, арабском.
Сетка дорожек
Трек — это пространство между двумя линиями сетки. Трек строки — это пространство между двумя линиями строки, а трек столбца — это пространство между двумя линиями столбца. Когда мы создаем нашу сетку, мы создаем эти треки, назначая им размер.
Ячейка сетки
Ячейка сетки — это наименьшее пространство в сетке, определяемое пересечением дорожек строк и столбцов. Это как ячейка таблицы или ячейка в электронной таблице. Если вы определяете сетку и не размещаете ни одного элемента, они будут автоматически размещены по одному элементу в каждой определенной ячейке сетки.
Площадь сетки
Несколько ячеек сетки вместе. Области сетки создаются путем размещения элемента на нескольких дорожках.
Пробелы
Желоб или аллея между дорожками. Для целей определения размера они действуют как обычная дорожка. Вы не можете поместить содержимое в зазор, но вы можете растянуть элементы сетки через него.
Сетчатый контейнер
HTML-элемент, к которому применено свойство display: grid
, и, следовательно, создающий новый контекст форматирования сетки для прямых дочерних элементов.
.container {
display: grid;
}
Элемент сетки
Элемент сетки — это элемент, который является прямым дочерним элементом контейнера сетки.
<div class="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
Строки и столбцы
Чтобы создать базовую сетку, вы можете определить сетку с тремя столбчатыми дорожками, двумя строковыми дорожками и зазором в 10 пикселей между дорожками следующим образом.
.container {
display: grid;
grid-template-columns: 5em 100px 30%;
grid-template-rows: 200px auto;
gap: 10px;
}
Эта сетка демонстрирует многие вещи, описанные в разделе терминологии. Она имеет три столбцовых трека. Каждый трек использует разные единицы длины. Она имеет два строковых трека, один из которых использует единицу длины, а другой — auto. При использовании в качестве размера трека auto можно считать, что он такой же большой, как и содержимое. По умолчанию треки имеют автоматический размер.
Если элемент с классом .container
имеет дочерние элементы, они немедленно будут выложены на этой сетке. Вы можете увидеть это в действии в следующей демонстрации:
Наложение сетки в Chrome DevTools поможет вам понять различные части сетки.
Откройте демо в Chrome. Изучите элемент с серым фоном, у которого есть идентификатор container
. Выделите сетку, выбрав значок сетки в DOM, рядом с элементом .container
. На вкладке Layout в разделе Overlay display settings выберите Show line numbers в раскрывающемся списке, чтобы увидеть номера строк в сетке.

Ключевые слова для определения внутреннего размера
В дополнение к размерам длины и процентным размерам, описанным в разделе о единицах измерения , треки сетки могут использовать внутренние ключевые слова размера. Эти ключевые слова определены в спецификации Box Sizing и добавляют дополнительные методы определения размеров блоков в CSS, а не только треки сетки.
-
min-content
-
max-content
-
fit-content()
Ключевое слово min-content
сделает трек настолько маленьким, насколько это возможно, без переполнения содержимым трека. Изменение макета сетки примера на три столбца трека, все с размером min-content
, будет означать, что они станут такими же узкими, как самое длинное слово в треке.
Ключевое слово max-content
имеет противоположный эффект. Дорожка станет достаточно широкой, чтобы все содержимое отображалось в одной длинной непрерывной строке. Это может привести к переполнению, так как строка не будет переноситься.
Функция fit-content()
сначала действует как max-content
. Однако как только трек достигает размера, который вы передаете в функцию, контент начинает переноситься. Таким образом, fit-content(10em)
создаст трек, который меньше 10em, если размер max-content
меньше 10em, но никогда не больше 10em.
В следующей демонстрации попробуйте использовать различные ключевые слова для задания внутренних размеров, изменяя размер дорожек сетки.
Единица измерения fr
У нас есть существующие размеры длины, проценты, а также эти новые ключевые слова. Также есть специальный метод определения размера, который работает только в сетке. Это единица fr
, гибкая длина, которая описывает долю доступного пространства в контейнере сетки.
Единица fr
работает аналогично использованию flex: auto
в flexbox. Она распределяет пространство после того, как элементы были выложены. Поэтому, чтобы иметь три столбца, которые все получают одинаковую долю доступного пространства:
.container {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
}
Поскольку единица fr разделяет доступное пространство, ее можно комбинировать с фиксированным размером gap или фиксированными размерами track. Чтобы иметь компонент с фиксированным размером элемента и второй track, занимающий все оставшееся пространство, вы можете использовать в качестве tracklisting grid-template-columns: 200px 1fr
.
Использование различных значений для единицы fr разделит пространство пропорционально. Большие значения получают больше свободного пространства. В следующей демонстрации измените значение третьей дорожки.
Функция minmax()
Эта функция означает, что вы можете установить минимальный и максимальный размер для трека. Это может быть весьма полезно. Если мы возьмем предыдущий пример единицы fr
, которая распределяет оставшееся пространство, его можно записать с помощью minmax()
как minmax(auto, 1fr)
. Сетка смотрит на внутренний размер контента, затем распределяет доступное пространство после предоставления контенту достаточного места. Это означает, что вы можете не получить треки, у каждого из которых будет равная доля всего доступного пространства в контейнере сетки.
Чтобы заставить трек занять равную долю пространства в контейнере сетки за вычетом зазоров, используйте minmax. Замените 1fr
в качестве размера трека на minmax(0, 1fr)
. Это сделает минимальный размер трека 0, а не размер min-content. Затем Grid возьмет весь доступный размер в контейнере, вычтет размер, необходимый для любых зазоров, и распределит остаток в соответствии с вашими единицами fr.
repeat()
нотацию
Если вы хотите создать сетку из 12 одинаковых столбцов, вы можете использовать следующий CSS.
.container {
display: grid;
grid-template-columns:
minmax(0,1fr),
minmax(0,1fr),
minmax(0,1fr),
minmax(0,1fr),
minmax(0,1fr),
minmax(0,1fr),
minmax(0,1fr),
minmax(0,1fr),
minmax(0,1fr),
minmax(0,1fr),
minmax(0,1fr),
minmax(0,1fr);
}
Или вы можете записать это с помощью repeat()
:
.container {
display: grid;
grid-template-columns: repeat(12, minmax(0,1fr));
}
Функция repeat()
может использоваться для повторения любого раздела вашего списка треков. Например, вы можете повторить шаблон треков. Вы также можете иметь несколько обычных треков и повторяющийся раздел.
.container {
display: grid;
grid-template-columns: 200px repeat(2, 1fr 2fr) 200px; /*creates 6 tracks*/
}
auto-fill
и auto-fit
Вы можете объединить все, что вы узнали о размерах дорожек, minmax()
и повторении, чтобы создать полезный шаблон с сеткой. Возможно, вы не хотите указывать количество дорожек столбцов, а вместо этого хотите создать столько, сколько поместится в вашем контейнере.
Вы можете добиться этого с помощью repeat()
и ключевых слов auto-fill
или auto-fit
. В следующем демо сетка создаст столько дорожек по 200 пикселей, сколько поместится в контейнере. Откройте демо в новом окне и посмотрите, как сетка изменится при изменении размера области просмотра.
В демо мы получаем столько дорожек, сколько поместится. Однако дорожки не являются гибкими. У вас будет зазор в конце, пока не будет достаточно места для еще одной дорожки размером 200 пикселей. Если вы добавите функцию minmax()
, вы можете запросить столько дорожек, сколько поместится, с минимальным размером 200 пикселей и максимальным 1fr. Затем Grid выкладывает дорожки размером 200 пикселей, и все оставшееся пространство распределяется между ними поровну.
Это создает двухмерный адаптивный макет без необходимости использования каких-либо медиа-запросов.
Между auto-fill
и auto-fit
есть тонкая разница. В следующем демо поиграйте с макетом сетки, используя синтаксис, описанный ранее, но только с двумя элементами сетки в контейнере сетки. Используя ключевое слово auto-fill
вы можете увидеть, что были созданы пустые дорожки. Измените ключевое слово на auto-fit
, и дорожки схлопнутся до размера 0. Это означает, что гибкие дорожки теперь увеличиваются, поглощая пространство.
В остальном ключевые слова auto-fill
и auto-fit
действуют точно так же. Между ними нет никакой разницы, как только заполнен первый трек.
Авторазмещение
Вы уже видели, как работает автоматическое размещение сетки в демонстрационных версиях. Элементы размещаются на сетке по одному на ячейку в том порядке, в котором они появляются в источнике. Для многих макетов этого может быть достаточно. Если вам нужно больше контроля, то есть пара вещей, которые вы, возможно, захотите сделать. Первое — настроить макет автоматического размещения.
Размещение элементов в столбцах
Поведение по умолчанию для макета сетки — размещать элементы вдоль строк. Вместо этого вы можете разместить элементы в столбцах с помощью grid-auto-flow: column
. Вам необходимо определить треки строк, иначе элементы создадут внутренние треки столбцов и разместят все в одной длинной строке.
Эти значения относятся к режиму письма документа. Строка всегда идет в том же направлении, в котором идет предложение в режиме письма документа или компонента. В следующей демонстрации вы можете изменить mode, значение grid-auto-flow
и свойство writing-mode
.
Охватывающие пути
Вы можете сделать так, чтобы некоторые или все элементы в автоматически размещенном макете охватывали более одной дорожки. Используйте ключевое слово span
и количество строк для охвата в качестве значения для grid-column-end
или grid-row-end
.
.item {
grid-column-end: span 2; /* will span two lines, therefore covering two tracks */
}
Поскольку вы не указали grid-column-start
, это использует начальное значение auto
и размещается в соответствии с правилами auto-placement. Вы также можете указать то же самое, используя сокращенную запись grid-column
:
.item {
grid-column: auto / span 2;
}
Заполнение пробелов
Автоматически размещенный макет с некоторыми элементами, охватывающими несколько дорожек, может привести к созданию сетки с некоторыми незаполненными ячейками. Поведение по умолчанию для макета сетки с полностью автоматически размещенным макетом — всегда продвигаться вперед. Элементы будут размещены в соответствии с порядком, в котором они находятся в источнике, или любым изменением свойства order
. Если места для размещения элемента недостаточно, сетка оставит зазор и перейдет на следующую дорожку.
Следующая демонстрация демонстрирует это поведение. Флажок применит режим плотной упаковки. Это включается путем присвоения grid-auto-flow
значения dense
. При наличии этого значения grid будет брать элементы позже в макете и использовать их для заполнения пробелов. Это может означать, что отображение отсоединится от логического порядка.
Размещение предметов
У вас уже есть много функциональности от CSS Grid. Теперь взгляните, как позиционировать элементы в созданной нами сетке.
Первое, что нужно запомнить, это то, что CSS Grid Layout основан на сетке из пронумерованных линий. Самый простой способ разместить элементы на сетке — разместить их с одной линии на другой. В этом руководстве вы найдете другие способы размещения элементов, но у вас всегда будет доступ к этим пронумерованным линиям.
Свойства, которые можно использовать для размещения элементов по номеру строки:
У них есть сокращения, которые позволяют вам задать как начальную, так и конечную строку одновременно:
Чтобы разместить элемент, задайте начальную и конечную линии области сетки, в которую он должен быть помещен.
.container {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: repeat(2, 200px 100px);
}
.item {
grid-column-start: 1; /* start at column line 1 */
grid-column-end: 4; /* end at column line 4 */
grid-row-start: 2; /*start at row line 2 */
grid-row-end: 4; /* end at row line 4 */
}
Chrome DevTools может предоставить вам визуальное руководство по линиям, чтобы вы могли проверить, где находится ваш элемент.
Нумерация строк соответствует режиму и направлению написания компонента. В следующей демонстрации измените режим или направление написания, чтобы увидеть, как размещение элементов остается согласованным с тем, как течет текст.
Укладка предметов
Используя позиционирование на основе линий, вы можете размещать элементы в одной и той же ячейке сетки. Это означает, что вы можете складывать элементы друг на друга или заставлять один элемент частично перекрывать другой. Элементы, которые идут позже в источнике, будут отображаться поверх элементов, которые идут раньше. Вы можете изменить этот порядок размещения с помощью z-index
как и в случае с позиционированными элементами.
Отрицательные номера строк
Когда вы создаете сетку с помощью grid-template-rows
и grid-template-columns
вы создаете то, что известно как явная сетка . Это сетка, которую вы определили и задали размер дорожкам.
Иногда у вас будут элементы, которые отображаются за пределами этой явной сетки. Например, вы можете определить треки столбцов, а затем добавить несколько строк элементов сетки, не определяя треки строк. Размер треков будет автоматически изменен по умолчанию. Вы также можете разместить элемент с помощью grid-column-end
, который находится за пределами явной сетки. В обоих этих случаях grid создаст треки, чтобы макет работал, и эти треки называются неявной сеткой .
В большинстве случаев не имеет значения, работаете ли вы с неявной или явной сеткой. Однако при размещении на основе линий вы можете столкнуться с основным различием между ними.
Используя отрицательные номера строк, вы можете размещать элементы с конечной строки явной сетки. Это может быть полезно, если вы хотите, чтобы элемент охватывал от первой до последней строки столбца. В этом случае вы можете использовать grid-column: 1 / -1
. Элемент будет растянут прямо по явной сетке.
Однако это работает только для явной сетки. Возьмите макет из трех рядов автоматически размещенных элементов, где вы хотите, чтобы самый первый элемент охватывал конечную линию сетки.
Вы можете подумать, что можете дать этому элементу grid-row: 1 / -1
. В следующем демо вы можете увидеть, что это не работает. Треки создаются в неявной сетке, нет способа достичь конца сетки с помощью -1
.
Определение размера неявных треков
Треки, созданные в неявной сетке, будут автоматически изменять размер по умолчанию. Однако, если вы хотите контролировать размер строк, используйте свойство grid-auto-rows
, а для столбцов grid-auto-columns
.
Чтобы создать все неявные строки с минимальным размером 10em
и максимальным размером auto
:
.container {
display: grid;
grid-auto-rows: minmax(10em, auto);
}
Для создания неявных столбцов с шаблоном шириной дорожек 100px и 200px. В этом случае первый неявный столбец будет 100px, второй 200px, третий 100px и т. д.
.container {
display: grid;
grid-auto-columns: 100px 200px;
}
Именованные линии сетки
Это может облегчить размещение элементов в макете, если у линий есть имя, а не номер. Вы можете дать имя любой линии в сетке, добавив имя по вашему выбору в квадратных скобках. Можно добавить несколько имен, разделенных пробелом внутри тех же скобок. После того, как вы дали линиям имена, их можно использовать вместо номеров.
.container {
display: grid;
grid-template-columns:
[main-start aside-start] 1fr
[aside-end content-start] 2fr
[content-end main-end]; /* a two column layout */
}
.sidebar {
grid-column: aside-start / aside-end;
/* placed between line 1 and 2*/
}
footer {
grid-column: main-start / main-end;
/* right across the layout from line 1 to line 3*/
}
Шаблоны сеток областей
Вы также можете называть области сетки и размещать элементы в этих названных областях. Это прекрасная техника, поскольку она позволяет вам видеть, как выглядит ваш компонент прямо там, в CSS.
Для начала дайте прямым дочерним элементам контейнера сетки имя, используя свойство grid-area
:
header {
grid-area: header;
}
.sidebar {
grid-area: sidebar;
}
.content {
grid-area: content;
}
footer {
grid-area: footer;
}
Имя может быть любым, кроме ключевых слов auto
и span
. После того, как все ваши элементы будут названы, используйте свойство grid-template-areas
чтобы определить, какие ячейки сетки будет охватывать каждый элемент. Каждая строка определяется в кавычках.
.container {
display: grid;
grid-template-columns: repeat(4,1fr);
grid-template-areas:
"header header header header"
"sidebar content content content"
"sidebar footer footer footer";
}
При использовании grid-template-areas
существует несколько правил.
- Значение должно представлять собой полную сетку без пустых ячеек.
- Чтобы охватить несколько дорожек, повторите название.
- Области, созданные путем повторения имени, должны быть прямоугольными и не могут быть разъединены.
Если вы нарушите любое из предыдущих правил, значение будет считаться недействительным и отбрасываться.
Чтобы оставить пробелы в сетке, используйте .
или несколько без пробелов между ними. Например, чтобы оставить самую первую ячейку в сетке пустой, я могу добавить ряд символов .
:
.container {
display: grid;
grid-template-columns: repeat(4,1fr);
grid-template-areas:
"....... header header header"
"sidebar content content content"
"sidebar footer footer footer";
}
Поскольку весь ваш макет определен в одном месте, это упрощает переопределение макета с помощью медиазапросов. В следующем примере я создал макет из двух столбцов, который переходит в три столбца, переопределяя значения grid-template-columns
и grid-template-areas
. Откройте пример в новом окне, чтобы поиграть с размером области просмотра и увидеть изменение макета.
Вы также можете увидеть, как свойство grid-template-areas
связано с writing-mode
, как и в других методах сетки.
Сокращенные свойства
Есть два сокращенных свойства, которые позволяют вам устанавливать многие свойства сетки за один раз. Они могут выглядеть немного запутанными, пока вы не разберете, как именно они работают вместе. Хотите ли вы использовать их или предпочитаете использовать длинные записи, решать вам.
grid-template
Свойство grid-template
является сокращением для grid-template-rows
, grid-template-columns
и grid-template-areas
. Сначала определяются строки вместе со значением grid-template-areas
. Размер столбца добавляется после /
.
.container {
display: grid;
grid-template:
"head head head" minmax(150px, auto)
"sidebar content content" auto
"sidebar footer footer" auto / 1fr 1fr 1fr;
}
свойство grid
Сокращение grid
может использоваться точно так же, как сокращение grid-template
. При таком использовании оно сбросит другие свойства сетки, которые оно принимает, на их начальные значения. Полный набор:
-
grid-template-rows
-
grid-template-columns
-
grid-template-areas
-
grid-auto-rows
-
grid-auto-columns
-
grid-auto-flow
Вы также можете использовать это сокращение для определения поведения неявной сетки, например:
.container {
display: grid;
grid: repeat(2, 80px) / auto-flow 120px;
}
Подсетка
Любой элемент сетки также может стать собственным контейнером сетки, если добавить display: grid
. По умолчанию эта вложенная сетка имеет свой собственный размер дорожек, отдельный от родительской сетки. Используя subgrid, ваш дочерний контейнер сетки унаследует размер дорожек, имена линий и зазор от родительской сетки, что упрощает выравнивание элементов с помощью общих линий сетки.
Чтобы использовать столбцы родительской сетки во вложенной сетке, установите grid-template-columns: subgrid
. Чтобы использовать строки родительской сетки во вложенной сетке, установите grid-template-rows: subgrid
. Вы также можете использовать subgrid
как для строк, так и для столбцов.
В следующем демо есть сетка с классом gallery
, которая имеет несколько гибких столбцов. Поскольку у нее нет определения grid-template-rows
, размер строки берется из содержимого. Элементы сетки в галерее также являются контейнерами сетки, которые устанавливаются так, чтобы начинаться со следующей доступной строки ( auto
) и охватывать две дорожки. Наконец, subgrid используется для свойства grid-template-rows
, которое позволяет отдельным сеткам gallery-item
использовать один и тот же размер дорожки сетки. Если вы закомментируете эту строку, вы увидите, что подписи больше не выровнены.
Применение подсетки к столбцам и строкам
При применении подсетки к строке и столбцу подсетка использует родительские треки сетки в обоих измерениях. В следующем фрагменте кода есть явная сетка с четырьмя столбцами и четырьмя строками с разными размерами треков.
.container {
display: grid;
gap: 1em;
grid-template-columns: auto 2fr 1fr auto;
grid-template-rows: 5fr 1fr 2fr 1fr;
}
Один из элементов сетки также имеет display: grid
и настроен на охват двух столбцов и трех строк родительской сетки. До добавления значения subgrid
элементы во вложенной сетке не выстраиваются в линию с элементами сетки в родительской сетке.
.subgrid-container {
display: grid;
grid-column: auto / span 2;
grid-row: auto / span 3;
}
Выравнивание
Сетка макета использует те же свойства выравнивания, о которых вы узнали в руководстве по flexbox . В сетке свойства, которые начинаются с justify-
всегда используются на встроенной оси, направлении, в котором предложения располагаются в вашем режиме письма.
Свойства, начинающиеся с align-
используются на оси блока, направлении, в котором блоки располагаются в режиме письма.
-
justify-content
иalign-content
: распределяют дополнительное пространство в контейнере сетки вокруг дорожек или между ними. -
justify-self
иalign-self
: применяются к элементу сетки для его перемещения внутри области сетки, в которой он находится. -
justify-items
иalign-items
: применяются к контейнеру сетки для установки всех свойствjustify-self
для элементов.
Распределение дополнительного пространства
В этой демонстрации сетка больше, чем пространство, необходимое для размещения дорожек фиксированной ширины. Это означает, что у нас есть место как в линейных, так и в блочных размерах сетки. Попробуйте разные значения align-content
и justify-content
чтобы увидеть, как ведут себя дорожки.
Обратите внимание, как зазоры увеличиваются при использовании таких значений, как space-between
, и любой элемент сетки, охватывающий две дорожки, также увеличивается, чтобы поглотить дополнительное пространство, добавленное к зазору.
Перемещение контента
Элементы с фоновым цветом кажутся полностью заполняющими область сетки, в которую они помещены, поскольку начальное значение justify-self
и align-self
равно stretch
.
В демо измените значения justify-items
и align-items
чтобы увидеть, как это изменит макет. Область сетки не меняет размер, вместо этого элементы перемещаются внутри определенной области.
Проверьте свое понимание
Проверьте свои знания сетки
Какие из перечисленных ниже терминов относятся к сетке CSS?
main { display: grid; }
Каково направление компоновки сетки по умолчанию?
grid-auto-flow: column
то сетка была бы размещена в виде столбцов. В чем разница между auto-fit
и auto-fill
?
auto-fit
растянет ячейки, чтобы они вписались в контейнер, а auto-fill
этого не сделает.auto-fill
помещает в шаблон как можно больше элементов, не растягивая их. Подгонка делает их подходящими.auto-fit
растянет контейнер, чтобы вместить дочерние элементы, тогда как auto-fill
подгонит дочерние элементы под размер контейнера. Что такое min-content
?
min-content
— относительно слов и изображений в блоке.min-content
.min-content
. Что такое max-content
?
max-content
не имеет в виду буквы.min-content
.Что такое автоматическое размещение?
grid-area
, и они размещены в этой ячейке.Ресурсы
Это руководство дало вам обзор различных частей спецификации макета сетки. Чтобы узнать больше, взгляните на следующие ресурсы.