There are a number of ways to build grids with HTML and css. Let's look at a few of the most common.
We're going to build three grids, each very visually similar, but using different techniques.
However, many of the styles will be shared across all three grids, and therefore each
grid will have two classes: one that they all share (grid
) and
one that is specific to the technique (using-inline-block
,
using-flex
, or using-grid
). Pay attention to the instructions,
because some rules will be applied using the shared class, and some with the specific class!
table
element
Do not use tables to create layout grids. While the table
element
does indeed produce a grid of cells, its semantic purpose is actually to present data that
is tabular, like a spreadsheet of numbers. It is not intended to be used as
a layout tool for page content. It also handles responsiveness (the ability of
the page to adjust to the width of the window on any device) poorly.
It is possible to use the float property to create grids, and you may see some
suggestions online for doing so. Don't.
As a general rule, you should only use float
when you actually need to wrap
text or other inline elements around another element.
We've discussed how some elements are inline elements and some are
block elements.You may have figured out by now that we can control this behavior
with the display
css property. Even though a
code
element (for instance) is normally inline, we can
force it to be a block element with css like this:
code { display: block; }
.
There exists a 'hybrid' of these two behaviors: display: inline-block;
.
Elements with this rule applied will be styleable like blocks (all of the padding, margin,
etc), but will not expand automatically to fill the width of their parent.
Instead, they will only be wide enough to hold their content, and more importantly, they
will align themselves horizontally like words, fitting themselves left-to-right until
wrapping to a new line. We can use this behavior to make a grid!
Note that in this example and with others following, we'll use a
ul
element to represent the grid, and
li
elements for each cell in the grid. This is because in most
cases, a grid is conceptually a list that we're just 'presenting' in rows/columns because
it's an effective way to communicate small multiples of a thing — like portraits in a
yearbook. Semantically, those portraits are just an alphabetical list.
I've started a list below, with a single item. Let's begin by populating the HTML of our list. Don't be alarmed: The pictures are going to be huge. We'll take care of that in a minute when we add css.
li
element below to make a new
li
for eight people. You should end up with a single
ul
containing eight list items, each item with a photo and name.
Abram Siemsen
Abram Siemsen
Abram Siemsen
Abram Siemsen
Abram Siemsen
Abram Siemsen
Abram Siemsen
Abram Siemsen
Okay, let's get these images under control so we can see what we're doing.
img
elements inside
.grid
. This is the shared class, so this rule will apply to
all of the grids we build.
width: 150px;
The images are now small, but the list-items are still displaying as a bulleted list. Let's override the default list styles.
.grid
class, and add the rule
padding: 0;
. This should remove default padding on the
ul
that wraps our grid.
li
elements within
.grid
. Add the rule display: block;
.
Add a new selector for this specific grid's li. Use .using-inline-block li
.
li
elements, set
display: inline-block;
. Be sure you aren't styling using the shared
.grid li
selector!
At this point, our grid starts to look like it makes sense. But lets take a few more steps
to tidy things up. We'll apply these rules using the shared grid
class, so we
don't have to do them again for the next grid.
.grid li
, now add the
following rules:
width: 25%;
Should ensures our grid is "4-up" (25% * 4 = 100% of the
available width).
text-align: center;
Centers the image and name within each box.font-size: 0.8rem;
Makes the text a bit smaller.margin-bottom: 1rem;
Adds some space below each item.img
, change the width to
width: 90%;
. This means "be 90% the width of your parent." The parent
li
is 25% of the total page width. This ensures the image has a bit of space
on either side within its parent item, even on small devices.
This grid is shaping up fairly quickly, but there's one quirk. Our shared styles say the
li
elements should be width: 25%;
... so why aren't
they 4-up? The answer lies with a rendering detail of inline-block
elements.
Because inline-block elements wrap like words, it turns out the browser pays
attention to the space character between these elements in the HTML code —
just like it pays attention to a
The solution is some creative css!
.using-inline-block
, and set
font-size: 0;
.
We've shrunk the space between the li
elements to nothing,
so we're back to a perfect 25% × 4.
However: if we hadn't explicitly set a font-size for the
li
elements earlier (remember font-size: 0.8rem;
?),
our names would have disappeared too, because they'd have inherited
font-size: 0;
from the surrounding ul
.
Try using the inspector to 'un-check' the font-size
style rule for
.grid li
and see for yourself.
flex
Flex Layout, or flexbox, is a very powerful collection of layout tools in css.This lesson will not even attempt to get into all the intricacies of flex layout, but we can at least scratch the surface by seeing how it can be used for simple grids like ours. If you want to dig deeper, the Complete Guide to Flexbox is a fantastic resource.
To demonstrate, let's copy our grid ul
once again.
ul
grid from the previous section, and paste it
here, then change its class list to be class="grid using-flex"
.
Abram Siemsen
Abram Siemsen
Abram Siemsen
Abram Siemsen
Abram Siemsen
Abram Siemsen
Abram Siemsen
Abram Siemsen
Look, we picked up a bunch of existing styles from the shared grid
class, so
our images are already sized, the text is centered, etc. Hurray for shared classes to avoid
repetition!
display: flex;
flex-wrap: wrap;
A nice tidy grid once again! In previous methods, the critical rules for making the grid
were appled to the child elements, the li
s. This time, we're
applying a rule to the parent element, the ul
. Flex layout can feel
a little strange at first because we control children indirectly through rules applied to
the parent container, but when you're used to it, it's a very convenient and, uh, flexible
(sorry) system. (It's also the approach I normally use for grids myself.)
As with Flex layout, Grid layout is a very involved suite of tools, and we'll just use the most basic example here. For a complete reference, use the Complete Guide to Grid.
Let's copy our grid ul
a final time.
ul
grid from the previous section, and paste it
here, then change its class list to be class="grid using-grid"
.
Abram Siemsen
Abram Siemsen
Abram Siemsen
Abram Siemsen
Abram Siemsen
Abram Siemsen
Abram Siemsen
Abram Siemsen
ul
using it's specific class,
and add the following rules:
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
The fr unit stands for fraction, so the above rule is instructing our grid to have four columns, each with an equal fraction of the available space.
You'll see that our images got tiny. Oops! In this case, our shared rule setting the
li
elements to be width: 25%;
is working against us.
Since the grid column rule defines a conceptual parent 'column' in which each
li
resides, we can tell each li
to be 100%
of it's parent. We only want to do this for this grid, so we will not modify the
shared rule. Instead, we will override it.
.using-grid li
, and set width: 100%;
.
We are now back to having the images fill their column correctly, and our grid is complete!
That's the end of our grid examples (finally!), but it's worth noting that an
extremely important part of this whole lesson has been the application of a shared class, in
the grid
class. Doing so helped avoid repititious work, it also helped avoid
repetitous stylesheet code. If you find yourself copying entire blocks of css code then only
changing the selector and one tiny detail in the ruleset, you're doing it wrong. This
is a prime use-case for a shared class!