The CSS gap
attribute isn't new, but last year it got a big new feature: Now it works not only for CSS Grid, but also for Flexbox. Given that, and I think the property is more complex than it seems, I want to review and explain exactly how it works.
Let's take a closer look at gap
and their related properties and understand how and where they work.
First, let's review all gap
-related CSS properties. There are six in total:
grid-row-gap
grid-column-gap
grid-gap
row-gap
column-gap
gap
From this list, we can ignore the first three properties. grid-*
attribute was added early in drafting the CSS Grid specification and was later deprecated when gap
became more general. Browsers still support these deprecated grid-*
properties (as of this writing) and only treat them as non- grid-
prefixes. Therefore, grid-gap
is the same as gap
, grid-column-gap
is the same as column-gap
, grid-row-gap
is the same as row-gap
.
As for the other three properties, considering gap
is an abbreviation that allows you to specify the other two properties, we really only need to know what row-gap
and column-gap
do.
Our understanding of these properties depends on the type of CSS layout we use. Let's first look at these options.
If you're like me, you've used gap
in grid layouts, but now it can also be used in Flexbox as well as multi-column layouts. Let's review each situation.
All browsers support gap
in grid layouts, and they are very easy to understand in this context.
row-gap
introduces space between row trackscolumn-gap
introduces space between column orbitsLet's create a grid with three columns and two rows:
<code>.container { display: grid; grid-template-columns: 200px 100px 300px; grid-template-rows: 100px 100px; }</code>
This will give us the following grid:
The lines in the figure above are called grid lines , which separate the tracks (rows and columns) of the grid. These lines don't really exist in the grid - they are invisible, have no thickness, and are usually what DevTools display when we enable the grid inspector (in Safari, Firefox, Edge, or Chrome).
However, if we start adding gaps to the grid, it will work just like these lines start to get thickness.
Let's add a 20px gap:
<code>.container { display: grid; grid-template-columns: 200px 100px 300px; grid-template-rows: 100px 100px; gap: 20px; }</code>
Now the lines between our tracks are 20px thick, so pushing the grid project further.
It is worth noting that the tracks still have the same size (defined by grid-template-*
property); therefore, the grid is wider and larger than without gaps.
In a grid, row-gap
is always applied between row tracks. So if we replace gap
with row-gap
in the example above, we will get:
And column-gap
is always applied between column tracks, so replacing gap
with column-gap
will produce the following results:
The grid is simple because by default, the columns are vertical and the rows are horizontal, just like in a table. Therefore, it is easy to remember where column-gap
and row-gap
applications are.
Now things get a little more complicated when using writing-mode
. The default writing mode on the network is the horizontal mode from left to right, but there is also a vertical writing mode, when this happens, the columns become horizontal and the rows become vertical. Always pay attention to writing-mode
as it may make it less intuitive as it is usually.
This is a good transition to the next section, as columns and rows get new meanings in Flexbox.
Let's talk about gaps in the Flexbox layout, where things get a little bit more complicated. We will use the following example:
<code>.container { display: flex; }</code>
By default, this will give us a row Flex container, which means that items inside the container are stacked on the same horizontal line from left to right.
In this case, column-gap
is applied between projects, and row-gap
has no effect. This is because there is only one line (or line). But now let's add some gaps between projects:
<code>.container { display: flex; column-gap: 10px; }</code>
Now let's switch flex-direction
of the container to a column, which stacks the items vertically from top to bottom, using the following code:
<code>.container { display: flex; flex-direction: column; column-gap: 10px; }</code>
What happens next:
The gap disappeared. Even though column-gap
does add space between items when the container is in row direction, it no longer works in column direction.
We need to use row-gap
to retrieve it. Alternatively, we can use a gap
abbreviation with a value that will apply the same gap in both directions, so it works in both cases.
<code>.container { display: flex; flex-direction: column; gap: 10px; }</code>
So, all in all, column-gap
always works vertically (assuming the default writing-mode
), row-gap
always works horizontally. This does not depend on the orientation of the Flex container.
But now look at the examples involving line breaks:
<code>.container { display: flex; flex-wrap: wrap; column-gap: 40px; row-gap: 10px; justify-content: center; }</code>
Here, if the space is not enough to hold everything in one line, we allow the project to wrap lines on multiple lines using flex-wrap: wrap
.
In this case, column-gap
is still applied vertically between projects and row-gap
is applied horizontally between two Flex rows.
There is an interesting difference between this and the grid. Column gaps do not necessarily align across Flex rows. This is because justify-content: center
centers the project within its Flex line. This way, we can see that each Flex row is a separate layout with gaps applied independently of other rows.
Multicolumns are a layout type that makes it very easy for content to flow automatically between multiple columns, as you would expect in traditional newspaper articles. We set the number of columns and set the size for each column.
The gaps in a multi-column layout do not work much the same as a grid or Flexbox. There are three notable differences:
row-gap
has no effect.column-gap
has a default value that is not 0, Let's break it down one by one. First, row-gap
has no effect. In a multi-column layout, no rows need to be separated. This means that only column-gap
is related (and gap
abbreviation).
Second, unlike grid and Flexbox, the default value of column-gap
in multi-column layout is 1em (rather than 0). Therefore, even if there is no gap specified at all, the content columns are still visually separate. Of course, it can be overridden by default, but this is a good default.
Here is the code on which the example is based:
<code>.container { column-count: 3; padding: 1em; }</code>
Finally, we can style the space between columns in a multi-column layout. We use column-rule
property, which works similar to border
:
<code>.container { column-count: 3; column-gap: 12px; column-rule: 4px solid red; padding: 12px; }</code>
gap
has been well supported in all aspects. There is more information on caniuse, but in short:
gap
is supported anywhere except Internet Explorer (about to be eliminated), Opera Mini and UC Browser for Android. caniuse has a global support rate of 87.31%. So overall, gap
property is well supported and in most cases no workaround is needed.
It will be very useful to style the gap between Flexbox and CSS Grid. Unfortunately, it is not supported anywhere today. But the good news is that it may be realized in the near future. This has been discussed in the CSS Working Group and is being developed in Firefox. Once we have effective implementations and specification proposals in Firefox, it may drive implementations in other browsers.
Meanwhile, there are some solutions.
One way is to give the background color to the grid container, then give the project a different color, and finally leave a gap to make the container color appear.
While this works, it means we can't use gaps to introduce space between projects. The gap here acts as the border width. So, to visually separate items more clearly, we need to use padding or margins on the items, which is not ideal… as we will see in the next section.
Yes, in most cases we can also use margin
(and/or padding
) to add visual space between layout elements. But gap
has several advantages.
First, the gap is defined at the container level . This means we define them once for the entire layout and they are always applied consistently in the layout. Use margins need to be declared on each item. This can become complicated when the project is of different nature or comes from different reusable components.
The most important thing is that gap
only requires a single line of code to perform the correct operation by default. For example, if we try to introduce some space between Flex projects instead of surrounding them, margins need special circumstances to remove the extra margin before the first project and the extra margin after the last project. Using gaps, we don't need to do this.
Using margin: 0 20px
on each Flex project, we will get:
However, using gap: 40px
on the container, we will get:
Also in grid layouts, defining gaps at the container level is much simpler and better than having to define margins on each item and consider margins applied to grid edges.
Use margin: 20px
on each grid project:
Instead, use gap: 40px
on grid container:
Based on everything said so far, margin
and gap
don't have to be mutually exclusive. In fact, there are many ways to separate the layout's projects further, and they all work well together.
gap
property is just a part of the empty space created between boxes in the layout container. margin
, padding
and alignment may all increase gap
defined space.
Let's consider an example where we build a simple Flex layout using a given width, some gap, some content distribution (using justify-content
), and some margins and padding:
<code>.container { display: flex; gap: 40px; width: 900px; justify-content: space-around; } .item { padding: 20px; margin: 0 20px; }</code>
Let's assume this code produces the following results:
Now let's take a look at exactly how the blank space between projects is created:
As we can see, there are four different types of blank space between two consecutive Flex projects:
space-around
value.Let's end with a topic that is very close to me: DevTools' support for debug gaps. There will always be errors, and it is very gratifying to know that DevTools can support us, but we do need to know which tools can help us.
For gap
, I can think of two specific features that may be very useful.
Unless we misspel gap
or provide an invalid value, this property will always be applied to the page. For example, this is correct:
<code>.some-class { display: block; gap: 3em; }</code>
It won't do anything, but it's valid CSS and the browser doesn't mind gap
doesn't work with block layouts. However, Firefox has a feature called "Inactive CSS" that does this: It cares about effective CSS applied to things that make sense. In this case, Firefox DevTools displays a warning in the inspector.
Chrome and Microsoft Edge also have a very useful debugging gap feature. It was added through a collaboration between Microsoft and Google, with the goal of building layout debugging tools in Chromium, an open source project that supports both browsers and other browsers. In these browsers, you can hover over various properties in the Styles panel and see how they affect the page.
That's it. I hope this article helps understand some of the details of how the mid-gaps work in CSS.
The above is the detailed content of Minding the 'gap'. For more information, please follow other related articles on the PHP Chinese website!