DEV Community

Emmanuel Okiche
Emmanuel Okiche

Posted on

The NotSoDailyUI #002 - Credit Card Checkout (CSS GRID Goodness!)

Welcome to the second part of this series. In case you missed the first part, here's the link: part 1

In this one, we'll be coding the UI for a Credit Card Checkout page.
Here's a look at the finished product:

Just like i stated in the first part, since this is a code tutorial, i would be focusing on the code and not designing the UI from scratch. I got the inspiration of this design from this behance post by Andrea Pilutti.

Ok let's code.

The Markup

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Credit Card Checkout</title>
    <link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400,600" rel="stylesheet">
    <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.2.0/css/all.css" integrity="sha384-hWVjflwFxL6sNzntih27bfxkr27PmbbK/iSvJ+a4+0owXq79v+lsFkW54bOGbiDQ"
        crossorigin="anonymous">
    <link rel="stylesheet" href="style.css">
</head>

<body>
    <div class="container">
        <div class="checkout-flow">
            <div class="checkout-nav">
                <a href="#">Delivery & Pickup Options</a>
                <a href="#">Shipping Address</a>
                <a href="#" class="active">Payment</a>
            </div>

            <div class="checkout">
                <div class="product">
                    <img src="https://raw.githubusercontent.com/fleepgeek/dailyui/master/002-checkout/images/beats.png" alt="product">
                    <div class="info">
                        <p class="name">Beats by Dr.Dre</p>
                        <p class="type">Studio Wireless</p>
                        <h2 class="price">$375</h2>
                    </div>
                </div>

                <div class="form-wrapper">
                    <h2>Credit Card Checkout</h2>
                    <form class="payment-form">

                        <div class="input-control">
                            <label for="cardholder">Cardholder's Name</label>
                            <input type="text" name="cardholder" id="cardholder">
                        </div>

                        <div class="input-control">
                            <label for="cardholder">Card Number</label>
                            <div class="icon-input">
                                <input type="number" name="cardnumber" id="cardnumber">
                                <i class="fab fa-cc-mastercard"></i>
                            </div>
                        </div>

                        <div class="control-group">
                            <div class="input-control">
                                <label for="cardholder">Expiration Date</label>
                                <div class="icon-input">
                                    <input type="text" name="expiration" id="expiration" placeholder="MM/YY">
                                    <i class="far fa-calendar"></i>
                                </div>
                            </div>

                            <div class="input-control">
                                <label for="cardholder">Cvc code</label>
                                <input type="text" name="cardholder" id="cardholder">
                            </div>
                        </div>

                        <input type="submit" class="btn-order" value="Place Order">
                    </form>
                </div><!-- end form-wrapper -->

            </div><!-- end checkout -->
        </div><!-- end checkout-flow -->
    </div><!-- end container -->
</body>

</html>
Enter fullscreen mode Exit fullscreen mode

The html markup is pretty straightforward but there are a few things to note in the structure here. The wrapping div's of allinput has the class of input-control excluding the input type of submit. This class is used to style our inputs.

The CSS (style.css)

We are going to style the page using the Mobile-First approach. This simply means that we would first style the page for mobile devices then use media queries to style it for larger screens. Also, we would be using css grid to position our layouts.

global styles

Just like we did in the first part, we first set our css variables:

/*-- Variables --*/

:root {
    --bg-color: #25263B;
    --light-blue: rgb(53, 98, 220);
    --grey: grey;
    --light-grey:#E9E8ED;
    --green: rgb(19, 170, 70);
}
Enter fullscreen mode Exit fullscreen mode

Next, we set our global styles for our elements:

/*---- Global ----*/
* {
    margin: 0;
    padding: 0;
    border: 0;
    outline: 0;
    font-family: 'Open Sans', sans-serif;
    font-size: 100%;
    vertical-align: bottom;
    text-decoration: none;
    box-sizing: border-box;
}

html, body { 
    height: 100%;
    width: 100%;
    background-color: var(--bg-color);
}

a {
    color: var(--grey);
    text-transform: uppercase;
    font-size: 12px;
    font-weight: 700;
}

a.active {
    color: #ffffff;
}

label {
    font-size: 12px;
    font-weight: 600;
    text-transform: uppercase;
    color: var(--grey);
    display: block;
    margin-bottom: 5px;
}

input {
    padding: 10px;
    border: 2px solid var(--light-grey);
    width: 100%;
    font-weight: 600;
    border-radius: 3px;
}

input:focus {
    border-color: var(--green);
}
Enter fullscreen mode Exit fullscreen mode

Let me explain some parts. We just gave all our input a grey border of 2px and when it is focused, we change the border color to green. Also, we gave all elements some defaults using the * selector.

main styles

/* main */

.container {
    display: grid;
    grid-template-columns: .25fr 4fr .25fr;
    grid-template-areas: ". m .";
    width: 100%;
    padding: 40px 0;
}

.checkout-flow {
    grid-area: m;
    width: 100%;
}

Enter fullscreen mode Exit fullscreen mode

This where the css grid goodness comes in. We give .container a display: grid which tells the browser that this container is going to be a grid (Yeah Yeah, i know that's very obvious). Unlike the flex system which focuses on arranging items in one dimension (either row or column depending on the flex-direction property), the grid layout comes with the power of controlling the arrangement of items in two dimensions (rows and columns).

We define the columns using grid-template-columns. Here we define three columns of .25fr, 4fr and .25fr. fr simple means a fractional unit of the available space. Using fr divides the available space into fractions (Lol!! at those of you that skipped maths class in high school). So, 4fr means: take up 4 parts of the available space. .25fr means: take up 1/4 part of the available space.
Next, we define the areas we want these columns to take up using grid-template-areas: ". m .". Here m is a name (we could use any word or letter). m signifies the middle coulumn which is 4fr. The dots signifies unnamed columns (you'll understand this soon).

To make everything we just explained useful, we have to assign elements to these defined areas. We do that for .checkout-flow by giving the rule: grid-area: m. This tells the grid system that this element should take up the area of m in the grid system. The remaining areas marked with dots would serve as empty spaces or if you prefer you could call them margins.

**All this stress just to position a div in the center with equal margins?
Just calm down. We could do something like this: margin: 0 auto (auto margin on its left and right) on .container. Now, what if we want to make .checkout-flow cover the whole width (that is 100%). We would have to give checkout-flow negative margins to force it cover the width but with css grid we just do: grid-area: m m m and that's it. This is just a new option and could be beneficial in some design scenarios. Just use the one that best works for you in your given scenario.

I know, that was a lot, right? I could do a full tutorial on css grid if this looks overwhelming for beginners. Let me know in the comments section.

checkout-nav

This style applies to the steps navigation at the top of the screen:

.checkout-nav  {
    display: flex;
    justify-content: space-between;
    flex-direction: column;
    margin: 30px 0;
    height: 70px;
}
Enter fullscreen mode Exit fullscreen mode

checkout

These are the styles for the main checkout container that contains the product and the form-wrapper.


.checkout {
    background-color: #fff;
    border-radius: 3px;
    width: 100%;
    min-height: 550px;
    display: grid;
    grid-template-columns: repeat(12, 1fr);
    grid-template-areas: "p p p p p p p p p p p p"
                         "f f f f f f f f f f f f";
}

.product {
    grid-area: p;
    position: relative;
    min-height: 350px;
}

.form-wrapper {
    grid-area: f;
    padding: 40px;
    background-color: var(--light-grey);
}
Enter fullscreen mode Exit fullscreen mode

Using the same principle as we just learned, we define columns and areas on the parent div which has the class of checkout.
Instead of defining our columns manually, we make use of the repeat function which create 12 columns with each column taking up one part of the available space. In simpler terms, we just created a 12 column grid.
Next, we assign the areas we just created to .product and .form-wrapper. Remember, css grid has the power of two dimensions so just defined a grid of 12 columns and 2 rows.

The product would be on the top of the form wrapper in the mobile view (later, we would control the area for larger screen using media queries).
Head over to your browser and see your progress.

product

Let's continue styling our product section.

.product img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    padding-bottom: 40px;
}

.product .info {
    position: absolute;
    bottom: 0;
    padding: 30px;
}

.product .info .name {
    color: var(--grey);
    font-weight: 700;
    font-size: 20px;
}

.product .info .type {
    font-size: 25px;
}

.product .info .price {
    font-size: 36px;
    font-weight: 300;
    margin-top: 10px;
}

Enter fullscreen mode Exit fullscreen mode

form

.form-wrapper {
    grid-area: f;
    padding: 40px;
    background-color: var(--light-grey);
}

.form-wrapper h2 {
    font-size: 24px;
    font-weight: 300;
    color: var(--light-blue);
    margin-bottom: 40px;
}

.input-control {
    margin-bottom: 20px;
}

.icon-input {
    position: relative;
}

.icon-input input {
    padding-right: 40px;
}

.icon-input > i {
    position: absolute;
    bottom: 0;
    right: 0;
    padding: 15px;
    font-size: 20px;
    color: var(--grey);
}

.btn-order {
    border: none;
    background-color: var(--green);
    color: #ffffff;
    text-transform: uppercase;
    margin-top: 20px;
}
Enter fullscreen mode Exit fullscreen mode

If you read part 1 of this series, you'll see that nothing is new here in my approach to styling form elements. Errmmm except for the lovely font-awesome icons placed on some form inputs. OK, let's break that down but first let's take a look at one of the html markup for that element as a quick reminder:

<div class="input-control">
    <label for="cardholder">Card Number</label>
    <div class="icon-input">
        <input type="number" name="cardnumber" id="cardnumber">
        <i class="fab fa-cc-mastercard"></i>
    </div>
</div>
Enter fullscreen mode Exit fullscreen mode

We had a special class for inputs with icons called icon-input. In this style, we set position: relative so that we can give the icon element: position: absolute and place it at the right corner of the input. Also, we give the input a right padding so that its text wont cover the icon.

Your page should be looking great now. Go ahead and check it. We just need to add media queries for larger screens and that's what we'll do next.

media queries for larger screens

@media (min-width: 1024px) {
    .container {
        display: grid;
        grid-template-columns: .5fr 2fr .5fr;
        grid-template-areas: ". m .";
    }
    .checkout {
        grid-template-areas: "p p p p p f f f f f f f";
    }
    .checkout-nav {
        flex-direction: row;
        justify-content: space-evenly;
        height: 20px;
    }
    .control-group {
        display: flex;
        justify-content: space-between;
    }
    .control-group .input-control {
        flex: 0 0 48%;
    }
}
Enter fullscreen mode Exit fullscreen mode

For the .checkout class, we rearranged the grid-template-areas to layout the p and f side by side. With this rearrangement, the product and the form-wrapper would be side by side on large screens.
Next, we changed the flex direction of the .checkout-nav to row and spaced it evenly so that the links appear on one horizontal line.
We gave the .control-group a display of flex so the inputs(expiration date and cvc code) would be positioned on the same horizontal line.

Conclusion

That's it people. Here's the link to my dailyui github repo.
Stayed tuned for the next part!!

Top comments (0)