Grid system
The grid system in Halfmoon is a flexbox based, 12-column system, that can be used to quickly (and easily) build websites and pages which look good on all screen sizes.
Commenting
|
New message!
Jane Doe just sent you a new message.
|
The grid system in Halfmoon is a flexbox based, 12-column system, that can be used to quickly (and easily) build websites and pages which look good on all screen sizes.
<div class="container-fluid">
<div class="row">
<div class="col-sm">First column</div>
<div class="col-sm">Second column</div>
<div class="col-sm">Third column</div>
</div>
</div>
Here's a list of things to understand about the grid system in Halfmoon.
The following table explains how the grid system works for the different breakpoints.
All
(Incl. <= 576px) |
Small and up
(> 576px) |
Medium and up
(> 768px) |
Large and up
(> 992px) |
Extra large
(> 1200px) |
|
---|---|---|---|---|---|
Class prefix | .col- | .col-sm- | .col-md- | .col-lg- | .col-xl- |
No. of columns | 12 | 12 | 12 | 12 | 12 |
Gutters | None | None | None | None | None |
With all that said, let's take a look at another example.
<div class="container-fluid">
<div class="row">
<div class="col-1">1</div>
<div class="col-11">11</div>
</div>
<div class="row">
<div class="col-2">2</div>
<div class="col-10">10</div>
</div>
...
<div class="row">
<div class="col-6">6</div>
<div class="col-6">6</div>
</div>
...
<div class="row">
<div class="col-10">10</div>
<div class="col-2">2</div>
</div>
<div class="row">
<div class="col-11">11</div>
<div class="col-1">1</div>
</div>
</div>
Thanks to flexbox, width of the columns can be set automatically. A few things to note about auto-layout columns:
<div class="container-fluid">
<!-- First row -->
<div class="row">
<div class="col">.col</div>
<div class="col">.col</div>
<div class="col">.col</div>
</div>
<!-- Second row -->
<div class="row">
<div class="col">.col</div>
<div class="col-6">.col-6</div>
<div class="col">.col</div>
</div>
<!-- Third row -->
<div class="row">
<div class="col-auto">
<div class="w-150"> <!-- w-150 = width: 15rem (150px) -->
.col-auto (150px)
</div>
</div>
<div class="col">.col</div>
</div>
</div>
Columns can be made to take up different widths depending on screen sizes using the different class prefixes. Multiple column classes can be used together. This is the best way of making websites responsive.
<div class="container-fluid">
<!-- First row -->
<div class="row">
<div class="col-xl-6">
...
</div>
<div class="col-xl-6">
...
</div>
</div>
<!-- Second row -->
<div class="row">
<div class="col-md-6">
...
</div>
<div class="col-md-6">
...
</div>
</div>
<!-- Third row -->
<div class="row">
<div class="col-6 col-sm-5 col-md-4 col-lg-3">
...
</div>
<div class="col-6 col-sm-5 col-md-4 col-lg-3">
...
</div>
</div>
<!-- Fourth row -->
<div class="row">
<div class="col-6 col-sm-5 col-md-4 col-lg-3">
...
</div>
<div class="col-6 col-sm-5 col-md-4 col-lg-3">
...
</div>
<div class="col-6 col-sm-5 col-md-4 col-lg-3">
...
</div>
<div class="col-6 col-sm-5 col-md-4 col-lg-3">
...
</div>
</div>
</div>
Here's a list of things to understand about responsive columns in Halfmoon.
As mentioned above, columns have no margins or padding by default. In practice, we recommend always using content containers (.content) and cards (.card) inside columns for framing, since they are the main tools for framing content in the main section of the page (opens in new tab).
The weather forecast didn't say that, but the steel plate in his hip did. He had learned over the years to trust his hip over the weatherman. It was going to rain, so he better get outside and prepare.
The weather forecast didn't say that, but the steel plate in his hip did. He had learned over the years to trust his hip over the weatherman. It was going to rain, so he better get outside and prepare.
<div class="container-fluid">
<div class="row">
<!-- First column -->
<div class="col-sm-6">
<div class="content">
<h2 class="content-title">
It was going to rain
</h2>
<p>
The weather forecast didn't say that, but the steel plate in his hip did. He had learned over the years to trust his hip over the weatherman. It was going to rain, so he better get outside and prepare.
</p>
</div>
</div>
<!-- Second column -->
<div class="col-sm-6">
<div class="content">
<h2 class="content-title">
It was going to rain
</h2>
<p>
The weather forecast didn't say that, but the steel plate in his hip did. He had learned over the years to trust his hip over the weatherman. It was going to rain, so he better get outside and prepare.
</p>
</div>
</div>
</div>
</div>
<div class="container-fluid">
<!-- First row -->
<div class="row">
<div class="col-6">
<div class="card">
...
</div>
</div>
<div class="col-6">
<div class="card">
...
</div>
</div>
</div>
<!-- Second row -->
<div class="row">
<div class="col-6">
<div class="card">
...
</div>
</div>
<div class="col-6">
<div class="card">
...
</div>
</div>
</div>
</div>
In the previous example with the cards, you may have noticed that the spacing between the cards looks a bit off. This is because the margins between the cards stack up. The in-between spacing can be made equal by adding the .row-eq-spacing (or .row-eq-spacing-{breakpoint} for particular screen sizes) to the rows. The following table explains how it works.
Breakpoint |
All
(Incl. <= 576px) |
Small and up
(> 576px) |
Medium and up
(> 768px) |
Large and up
(> 992px) |
Extra large
(> 1200px) |
---|---|---|---|---|---|
Class | .row-eq-spacing | .row-eq-spacing-sm | .row-eq-spacing-md | .row-eq-spacing-lg | .row-eq-spacing-xl |
Now, let's fix the last example with the cards using the .row-eq-spacing class.
<!-- Equal in-between spacing with cards -->
<div class="container-fluid">
<!-- First row -->
<div class="row row-eq-spacing">
<div class="col-6">
<div class="card">
...
</div>
</div>
<div class="col-6">
<div class="card">
...
</div>
</div>
</div>
<!-- Second row -->
<div class="row row-eq-spacing">
<div class="col-6">
<div class="card">
...
</div>
</div>
<div class="col-6">
<div class="card">
...
</div>
</div>
</div>
</div>
It is important to remember that equal in-between spacing only works with cards (.card) and content containers (.content) placed directly inside the columns.
Equal in-between spacing works with content containers (.content), therefore, everything can be equally spaced. For instance, in the next example, four alert boxes are placed inside columns with equal in-between spacing. The alerts themselves are placed inside content containers (.content). Here, the .row-eq-spacing-md class is used because we want equal spacing only on medium screens and above, since below this, the columns will "collapse" and take up the full width of their parent container.
<!-- Equal in-between spacing with content -->
<div class="container-fluid">
<!-- First row -->
<div class="row row-eq-spacing-md">
<div class="col-md-6">
<div class="content">
<div class="alert alert-primary" role="alert">
<h4 class="alert-heading">Primary alert</h4>
Contextual alert box with some placeholder content and <a href="#" class="alert-link">a link</a>.
</div>
</div>
</div>
<div class="col-md-6">
<div class="content">
<div class="alert alert-success" role="alert">
<h4 class="alert-heading">Success alert</h4>
Contextual alert box with some placeholder content and <a href="#" class="alert-link">a link</a>.
</div>
</div>
</div>
</div>
<!-- Second row -->
<div class="row row-eq-spacing-md">
<div class="col-md-6">
<div class="content">
<div class="alert alert-secondary" role="alert">
<h4 class="alert-heading">Secondary alert</h4>
Contextual alert box with some placeholder content and <a href="#" class="alert-link">a link</a>.
</div>
</div>
</div>
<div class="col-md-6">
<div class="content">
<div class="alert alert-danger" role="alert">
<h4 class="alert-heading">Danger alert</h4>
Contextual alert box with some placeholder content and <a href="#" class="alert-link">a link</a>.
</div>
</div>
</div>
</div>
</div>
Here's a list of a few more things worth noting about equal in-between spacing:
<div class="container-fluid">
<!-- First row -->
<div class="row row-eq-spacing-sm justify-content-center"> <!-- justify-content-center = justify-content: center -->
<div class="col-sm-6 col-md-5 col-lg-4">
<div class="card">
...
</div>
</div>
<div class="col-sm-6 col-md-5 col-lg-4">
<div class="card">
...
</div>
</div>
</div>
<!-- Second row -->
<div class="row row-eq-spacing-sm justify-content-center"> <!-- justify-content-center = justify-content: center -->
<div class="col-sm-6 col-md-5 col-lg-4">
<div class="card">
...
</div>
</div>
<div class="col-sm-6 col-md-5 col-lg-4">
<div class="card">
...
</div>
</div>
</div>
<!-- Third row -->
<div class="row row-eq-spacing">
<!-- First column -->
<div class="col-6 col-lg-3">
<div class="card">
...
</div>
</div>
<!-- Second column -->
<div class="col-6 col-lg-3">
<div class="card">
...
</div>
</div>
<!-- Overflow occurs here on medium screens and down, so vertical spacer is added -->
<div class="v-spacer d-lg-none"></div> <!-- d-lg-none = display: none only on large screens and up (> 992px) -->
<!-- Third column -->
<div class="col-6 col-lg-3">
<div class="card">
...
</div>
</div>
<!-- Fourth column -->
<div class="col-6 col-lg-3">
<div class="card">
...
</div>
</div>
</div>
</div>
Columns can be vertically aligned using flex utilities (opens in new tab).
<div class="container-fluid">
<!-- Row with items aligned at the start -->
<div class="row align-items-start h-100"> <!-- align-items-start = align-items: flex-start, h-100 = height: 10rem (100px) -->
<div class="col">.col (1 of 3)</div>
<div class="col">.col (2 of 3)</div>
<div class="col">.col (3 of 3)</div>
</div>
<!-- Row with items aligned at the center -->
<div class="row align-items-center h-100"> <!-- align-items-center = align-items: center, h-100 = height: 10rem (100px) -->
<div class="col">.col (1 of 3)</div>
<div class="col">.col (2 of 3)</div>
<div class="col">.col (3 of 3)</div>
</div>
<!-- Row with items aligned at the end -->
<div class="row align-items-end h-100"> <!-- align-items-end = align-items: flex-end, h-100 = height: 10rem (100px) -->
<div class="col">.col (1 of 3)</div>
<div class="col">.col (2 of 3)</div>
<div class="col">.col (3 of 3)</div>
</div>
<!-- Row with items aligned individually -->
<div class="row h-100"> <!-- h-100 = height: 10rem (100px) -->
<div class="col align-self-start">.col (1 of 3)</div> <!-- align-self-start = align-self: flex-start -->
<div class="col align-self-center">.col (2 of 3)</div> <!-- align-self-center = align-self: center -->
<div class="col align-self-end">.col (3 of 3)</div> <!-- align-self-end = align-self: flex-end -->
</div>
</div>
Similarly, columns can be horizontally aligned using flex utilities (opens in new tab).
<div class="container-fluid">
<!-- Row with items justified at the start -->
<div class="row justify-content-start"> <!-- justify-content-start = justify-content: flex-start -->
<div class="col-4">.col-4</div>
<div class="col-4">.col-4</div>
</div>
<!-- Row with items justified at the center -->
<div class="row justify-content-center"> <!-- justify-content-center = justify-content: center -->
<div class="col-4">.col-4</div>
<div class="col-4">.col-4</div>
</div>
<!-- Row with items justified at the end -->
<div class="row justify-content-end"> <!-- justify-content-end = justify-content: flex-end -->
<div class="col-4">.col-4</div>
<div class="col-4">.col-4</div>
</div>
<!-- Row with items justified around -->
<div class="row justify-content-around"> <!-- justify-content-around = justify-content: space-around -->
<div class="col-4">.col-4</div>
<div class="col-4">.col-4</div>
</div>
<!-- Row with items justified between -->
<div class="row justify-content-between"> <!-- justify-content-between = justify-content: space-between -->
<div class="col-4">.col-4</div>
<div class="col-4">.col-4</div>
</div>
</div>
Columns can be easily nested by placing rows inside of columns. No additional classes are required for this.
<div class="container-fluid">
<div class="row">
<!-- First column -->
<div class="col-5">
.col-5
<!-- Nested -->
<div class="row">
<div class="col-6">.col-6</div>
<div class="col-6">.col-6</div>
</div>
</div>
<!-- Second column -->
<div class="col-7">
.col-7
<!-- Nested -->
<div class="row">
<div class="col-4">.col-4</div>
<div class="col-4">.col-4</div>
<div class="col-4">.col-4</div>
</div>
</div>
</div>
</div>
Columns can be offset using .offset-* or .offset-{breakpoint}-*, where * is the left margin of the column (and it can have any value between 0 and 11). For example, the class .offset-md-4 adds a margin to the left of the column equal to the width of .col-md-4.
<!-- Rows with column offsets -->
<div class="container-fluid">
<!-- First row -->
<div class="row">
<div class="col-6 offset-3">.col-6</div> <!-- With offset -->
</div>
<!-- Second row -->
<div class="row">
<div class="col-5">.col-5</div>
<div class="col-5 offset-2">.col-5</div> <!-- With offset -->
</div>
<!-- Third row -->
<div class="row">
<div class="col-sm-6 col-md-5 col-lg-4">
...
</div>
<div class="col-sm-6 col-md-5 col-lg-4 offset-md-2 offset-lg-4"> <!-- With offset -->
...
</div>
</div>
<!-- Fourth row -->
<div class="row">
<div class="col-md-4 col-lg-6">
...
</div>
<div class="col-md-4 col-lg-6 offset-md-4 offset-lg-0"> <!-- With offset and reset -->
...
</div>
</div>
</div>
Please note that you may need to reset the offset in some cases using .offset-{breakpoint}-0. For example, this is done in the fourth row above to prevent overflow on large screens (and up).
The visual order of the columns can be controlled using the following classes:
<!-- Rows with ordering -->
<div class="container-fluid">
<!-- First row -->
<div class="row">
<div class="col">First (unordered)</div>
<div class="col order-12">Second, but last</div>
<div class="col order-1">Third, but first</div>
</div>
<!-- Second row -->
<div class="row">
<div class="col order-md-12">First, but last (When screen > 768px)</div>
<div class="col order-md-1">Second, but first (When screen > 768px)</div>
</div>
<!-- Third row -->
<div class="row">
<div class="col order-last">First, but last</div>
<div class="col">Second (unordered)</div>
<div class="col order-first">Third, but first</div>
</div>
</div>
There are two types of rows in Halfmoon:
Due to there being two types of rows, only four combinations of adjacent rows are possible in a layout:
For combinations 1, 2 and 4, the content-containers (.content) and cards (.card) of the normal rows need to be given the utility classes .mt-0 and/or .mb-0 depending on what comes before and/or after. This is so that everything is properly aligned and spaced vertically.
However, the easier thing to do is to simply add the .row-eq-spacing/.row-eq-spacing-{breakpoint} classes to all the rows. This will automatically fix the spacing and alignment. For instance, in the next example, a fairly complex grid layout (with multiple adjacent rows) is created with ease using these classes.
<!-- Adjacent rows inside the container-fluid -->
<div class="container-fluid">
<!-- First row (equally spaced on small screens and up) -->
<div class="row row-eq-spacing-sm">
<div class="col-sm-6">
<div class="content">
...
</div>
</div>
<div class="col-sm-6">
<div class="content">
...
</div>
</div>
</div>
<!-- Second row (equally spaced on small screens and up) -->
<div class="row row-eq-spacing-sm">
<div class="col-sm-10">
<div class="content">
...
</div>
</div>
<div class="col-sm-2">
<div class="content">
...
</div>
</div>
</div>
<!-- Third row (equally spaced) -->
<div class="row row-eq-spacing">
<div class="col-6">
<div class="card">
...
</div>
</div>
<div class="col-6">
<div class="card">
...
</div>
</div>
</div>
<!-- Fourth row (equally spaced on large screens and up) -->
<div class="row row-eq-spacing-lg">
<div class="col-lg-8">
<div class="content">
...
</div>
<div class="card">
...
</div>
<div class="content">
...
</div>
</div>
<div class="col-lg-4">
<div class="card">
...
</div>
</div>
</div>
</div>
We built a page in the content and cards section (opens in new tab). Lets improve that page using the grid system to add some content to the side.
<body>
<!-- Page wrapper with content-wrapper inside -->
<div class="page-wrapper">
<div class="content-wrapper">
<!-- Container-fluid -->
<div class="container-fluid">
<div class="row">
<!-- Column with the main content -->
<div class="col-lg-9">
<div class="content">
<h1 class="content-title font-size-22"> <!-- font-size-22 = font-size: 2.2rem (22px) -->
Page title
</h1>
...
</div>
<div class="card">
<h2 class="card-title">Card title</h2>
...
</div>
<div class="content">
<h2 class="content-title">Content title <a href="#">#</a></h2>
...
</div>
<div class="card">
<h2 class="card-title">Card title</h2>
...
</div>
<div class="content">
...
</div>
</div>
<!-- Column with the side content -->
<div class="col-lg-3 d-none d-lg-block"> <!-- d-none = display: none, d-lg-block = display: block only on large screens and up (> 992px) -->
<div class="content">
<h2 class="content-title font-size-16">On this page</h2> <!-- font-size-16 = font-size: 1.6rem (16px) -->
...
</div>
</div>
</div>
</div>
</div>
</div>
</body>
In the above example, there is only one row, so there is no point in making it equally spaced using .row-eq-spacing-lg. Moreover, it is strongly recommended that the page wrapper (.page-wrapper), along with the content wrapper (.content-wrapper), is always used to build pages. You can learn more about this in the page building section (opens in new tab) of the docs.
On this section, let's build a dashboard using the things described above (along with some utility classes). The page below is very similar to ones found in real-life dashboards of applications.
<body>
<!-- Page wrapper with content-wrapper inside -->
<div class="page-wrapper">
<div class="content-wrapper">
<!-- Container-fluid -->
<div class="container-fluid">
<!-- First comes a content container with the main title -->
<div class="content">
<h1 class="content-title font-size-22"> <!-- font-size-22 = font-size: 2.2rem (22px) -->
Dashboard
</h1>
...
</div>
<!-- First row (equally spaced) -->
<div class="row row-eq-spacing">
<div class="col-6 col-xl-3">
<div class="card">
<h2 class="card-title">Orders</h2>
...
</div>
</div>
<div class="col-6 col-xl-3">
<div class="card">
<h2 class="card-title">Sales</h2>
...
</div>
</div>
<!-- Overflow occurs here on large screens (and down) -->
<!-- Therefore, a v-spacer is added at this point -->
<div class="v-spacer d-xl-none"></div> <!-- d-xl-none = display: none only on extra large screens (> 1200px) -->
<div class="col-6 col-xl-3">
<div class="card">
<h2 class="card-title">Costs</h2>
...
</div>
</div>
<div class="col-6 col-xl-3">
<div class="card">
<h2 class="card-title">Profits</h2>
...
</div>
</div>
</div>
<!-- Second row (equally spaced on large screens and up) -->
<div class="row row-eq-spacing-lg">
<div class="col-lg-8">
<div class="card h-lg-250 overflow-y-lg-auto"> <!-- h-lg-250 = height = 25rem (250px) only on large screens and up (> 992px), overflow-y-lg-auto = overflow-y: auto only on large screens and up (> 992px) -->
<h2 class="card-title">Customers</h2>
...
</div>
</div>
<div class="col-lg-4">
<div class="card h-lg-250 overflow-y-lg-auto"> <!-- h-lg-250 = height = 25rem (250px) only on large screens and up (> 992px), overflow-y-lg-auto = overflow-y: auto only on large screens and up (> 992px) -->
<h2 class="card-title">Breakdown</h2>
...
</div>
</div>
</div>
<!-- Third row (equally spaced on large screens and up) -->
<div class="row row-eq-spacing-lg">
<div class="col-lg-8">
<div class="content">
<h2 class="content-title">Customer stories <a href="#">#</a></h2>
...
</div>
<div class="card">
<h2 class="card-title">Transactions</h2>
...
</div>
<div class="content">
...
</div>
</div>
<div class="col-lg-4">
<div class="content">
<h2 class="content-title">Activity log <a href="#">#</a></h2>
...
</div>
</div>
</div>
</div>
</div>
</div>
</body>
In the above example, a .v-spacer is used in the first row to adjust for the overflow of columns. Also, in the row with the Customers and Breakdown cards, the height of the cards are fixed and the overflow-y is set to auto for large screens and up. This is because the Customers card can have varying content, and ideally, the two cards side by side should have the same height to look good.
It is worth repeating that it is strongly recommended that the page wrapper (.page-wrapper), along with the content wrapper (.content-wrapper), is always used to build pages. Again, you can learn more about this in the page building section (opens in new tab) of the docs.
The grid system in Halfmoon is almost identical to the one found in Bootstrap (with a few changes). Therefore, huge credits (and special thanks) must be given to the Bootstrap team and contributors. The appropriate copyright notice can be found in the CSS files.
Our goal is to make Halfmoon the go-to framework for building dashboards and tools on the web. We are already working on things like a form validator, number input, datepicker, multi-select (think Select2 without jQuery), tabs component, JSX docs, and so much more. You can learn more in the project roadmap.
However, we need your help to grow. So if you truly believe in our goal, please consider supporting us through Patreon.
The following is the highest tier, with a maximum of 1 sponsor.
(Also seen at the top of the page)
The following is the normal tier, with a maximum of 10 sponsors.
AYCD
Automation Done Right
Sponsor (9 available)
Halfmoon needs your support! Become a sponsor to place an image and description of your product here. Click here
The following people have generously decided to support Halfmoon.
Become a backer on Patreon .