Halfmoon: The forgotten CSS Framework
Tags: css, webdev, html, javascript
Published: 2021-10-23 13:51:15

In this post you will learn about a very beautiful CSS framework, [halfmoon css](https://www.gethalfmoon.com/) that you will rarely see someone using but is perfect for any person who wants to use a CSS framework.

We often see people talking about [bootstrap](https://getbootstrap.com), [Tailwind CSS](https://tailwindcss.com) or [Bulma CSS](https://bulma.io) when it comes to CSS frameworks. Once I wanted to use some css framework for one of my projects, and I tried to find some new ones, and in a blog post I saw the mention of halfmoon css, I just saw it and I was really surprised, like such a beautiful framework and no one talks about, no one uses it, or only few use it, but you rarely hear or read about it! 

What I like about it is that having dark mode, a very difficult task for people who are not very good at front end, but want to develop a full stack app with a good front end having both light and dark modes! It is very easy to learn as well because its look and css classes are highly inspired from bootstrap. Its documentation as well is very easy to understand, so let's now go ahead and try to create a simple tip counter app in pure html and javascript, with a dark mode.


### Building the tip calculator

#### Full source code for this app available on Github:
{% github Darshan-Bajeja/halfmoon-tip-calculator %}

Firstly let's create an empty directory for the project, and create 2 files inside it- `index.html` and `script.js`:

![create directory](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cs3udkjzvq59hn3hmz14.png)

Let's open it up in any code editor, and as most of you would have guessed, I am going to open it up in VS Code.

Using emmet, let's add the html boiler plate code, and then link the javascript file to the html file. Also replace the title to Tip Calculator:
 
```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Tip Calculator</title>
  </head>
  <body>
    <script src="script.js"></script>
  </body>
</html>
```

Now let's add an h1 tag just for testing purpose- which says our dear old `Hello, World!`:

```html
<h1>Hello World</h1>
```

And then open the html file in a browser. I am using Live Server extension to get hot reload.

You would see and old school hello world there:

![Hello World](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o3i5l5fs0ykcwfa25fh5.png)

Now let's visit half moon css website and move to the docs page. Click on 'Download' link on the sidebar, and scroll down to cdn section. Copy the link tag and paste in the head section and add script tag above the script tag which we added before. Now your code should look like this:

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Tip Calculator</title>
    <!-- Halfmoon CSS  -->
    <link
      href="https://cdn.jsdelivr.net/npm/halfmoon@1.1.1/css/halfmoon-variables.min.css"
      rel="stylesheet"
    />
  </head>
  <body>
    <h1>Hello World</h1>

    <!-- Halfmoon JS  -->
    <script src="https://cdn.jsdelivr.net/npm/halfmoon@1.1.1/js/halfmoon.min.js"></script>
    <script src="script.js"></script>
  </body>
</html>
```

Ok so now in the browser you can see the difference in font in the html page.

![hm hello world](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5qojl67nozi497oyl9yg.png)




Ok so let's start making our tip calculator. Now I want everything to be in center, so let's create a div, which will be placed in the center of our web page, and give it the following classes:

* h-half (For giving a half height, that is 50%)
* w-half (For giving a half width, that is 50%)
* border (For giving it a border)
* rounded (For giving it border-radius)
* shadow-lg (For giving it a shadow of large size)

If you have experience with bootstrap, you can see that these classes are very similar to it.

Now to center this div, wrap it inside another div, with classes:

* h-full (To give 100% height)
* w-full (To give 100% width)
* d-flex (To give a display: flex; property)
* flex-column (To give a flex direction of cloumn)
* justify-content-center (To justify the content center vertically (note that flex column makes the justify-content and align-items opposite))
* align-items-center (To align the items center horizontally)

So now you will have this code: 
```html
<div
      class="
        h-full
        w-full
        d-flex
        flex-column
        justify-content-center
        align-items-center
      "
    >
      <div class="h-half w-half border rounded shadow-lg"></div>
    </div>
``` (Please ignore the formatting done by prettier)

and the output would be like this:

![centered divs](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2zh66fm6nmzx6qelor8l.png)
 
Now let's give a header to our centered div. So create another div element with an h1, and a button with the text- toggle dark mode.

To make this beautiful let's add some halfmoon classes. 

#### DIV:

* d-flex
* justify-content-around
* align-items-center

#### H1
* font-weight-bolder

#### BUTTON
* btn 
* btn-primary

This will give us a beautiful header with a blue button.

![header](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nv3vafh9unqlp162xaw2.png)
 
 

Now let's have another div below the header div, with classes d-flex, flex-column, h-three-quarter (for 75% height), align-items-center, justify-content-around, and add 2 input boxes, with type number, with placeholders total bill amount and tip percentage, and ids bill and percentage and a paragraph tag with the text: Tip amount is 0 and put the number '0' in a span with id of tip-amount.

Next, to give it a good style let's add some classes. To the input boxes give the classes of form-control, form-control-lg and w-three-quarter. You pretty much now understand how the class names work in halfmoon. Also add the classes: `font-size-24` and `font-weight-semi-bold` to the paragraph tag to make it look good. Now finally your code inside the body tag should look like this (excluding the script tags):

```html
    <div
      class="
        h-full
        w-full
        d-flex
        flex-column
        justify-content-center
        align-items-center
      "
    >
      <div class="h-half w-half border rounded shadow-lg">
        <div class="d-flex justify-content-around align-items-center">
          <h1 class="font-weight-bolder">Tip Calculator</h1>
          <button class="btn btn-primary">Toggle Dark Mode</button>
        </div>

        <div
          class="
            d-flex
            flex-column
            align-items-center
            h-three-quarter
            justify-content-around
          "
        >
          <input
            type="number"
            id="bill"
            placeholder="Bill amount"
            class="form-control form-control-lg w-three-quarter"
          />
          <input
            type="number"
            id="percentage"
            placeholder="Tip percentage"
            class="form-control form-control-lg w-three-quarter"
          />

          <p class="font-size-24 font-weight-semi-bold">
            Tip amount is <span id="tip-amount">0</span>
          </p>
        </div>
      </div>
    </div>
```

and the webpage should look like this:


![static output](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hwmrik8rzqju1ur19ch6.png)
 
Now we have a beautiful UI. We now have to more goals to accomplish here.

1. Make our calculator functional
2. Make the Toggle Dark Mode button to work

So let's do the first part, that is make our calculator functional,

To do that, let's go to our javascript file and grab the html elements by their ids:

```javascript
const billInput = document.querySelector("#bill");
const percentageInput = document.querySelector("#percentage");
const tipSpan = document.querySelector("#tip-amount");
```


Next, let's create a function to calculate the tip and render it in the tip-amount span.

```javascript
const calculateAndRenderTip = () => {
  const billValue = Number(billInput.value);
  const percentageValue = Number(percentageInput.value);
  const tip = (percentageValue / 100) * billValue;
  tipSpan.innerHTML = tip;
};
```

And let's add the change event listener to billInput and percentangeInput, and run the function.


```javascript
billInput.addEventListener("change", calculateAndRenderTip);
percentageInput.addEventListener("change", calculateAndRenderTip);
```

So now our calculator is functional, but note that as we have mentioned input type as number, you need to use arrow keys for incrementing and decrementing the number to trigger the change event, or if you prefer to type in the number, then you need press enter key after typing in the number to trigger the change event, otherwise browser won't detect the change event just when you type.

{% youtube iKaKvSSxXDA %}

Now the final part is to adding the darkmode toggling functionality. And in fact it is the easiest to do!

So first in the button we created for toggle darkmode, add an onclick listener for a function which you might call, suppose, toggleTheme.

```html
<button class="btn btn-primary" onclick="toggleTheme()">
            Toggle Dark Mode
</button>
```

and in javascript file, let's create this function which just uses the halfmoon variable which we get from the javascript cdn of halfmoon to call the toggleDarkMode function from it, and that's all you need to do for toggling dark mode in your website, really!

```javascript
const toggleTheme = () => halfmoon.toggleDarkMode();
```

{% youtube a8N1ZnLY-Ro %}

> To get the full source code of this app visit the github repository provided above the section where we started writing the code for this app.

So did you see how easy and cool is Halfmoon CSS. I hope you enjoyed using halfmoon and will use it in your future projects.

If you make a project using halfmoon css, be sure to link it down below in the comments of this post, I will have good time looking at them!