Building Pricing Tables with HTML + CSS

Building Pricing Tables with HTML + CSS

With CSS Grid, Variables, and Hovers

Jul 20, 2021ยท

6 min read

Hello ๐Ÿ‘‹ - this TinyApp is called SuperPricey. It's an example of a simple pricing table, displaying pricing plans for the random-est stuff.

Meet SuperPricey ๐Ÿค‘

Check out SuperPricey in the sandbox below. It's a website running on just HTML and CSS.

Structure Required ๐Ÿ’€

HTML is a markup language, and it provides structure to our page. As we start breaking this TinyApp down, let's start with getting the skeleton together.

Our <body> tag starts out with an <h1> for our title, and a <p> tag for a subtitle on the page. There aren't any CSS classes on either of these tags, so they're simply inheriting styles that are applied to the full body of the page.

<p>Pay money for the randomest stuff.</p>

The next piece is where we start to see some more complex nesting. The nesting starts with a <div> element.

<div class="plans-container">

There's a class called "plans-container" on this div, so already, without even looking at the CSS, we can infer that this div contains all of the plans within it.

Sure enough, the next child of this div is the whole plan. Here's the HTML for the "free" plan.

<div class="plan plan--free">
  <p class="plan-title">Free</p>
  <p class="plan-price">
    <span class="plan-price-text">$0</span>
  <div class="button">Sign Up</div>
        <li>Used socks</li>
        <li>Sweet potatoes</li>
        <li>Unpaid utility bills</li>

There seems to be a whole lot going on here, but we can break it down. If we read the tags from top to bottom, here's how it's structured.

  • Create a div with a class of plan. Add another class of plan--free to indicate this is the free class (and will need appropriately different styles). This div is the parent, holding the rest of the code within it.
  • Add the title of the plan.
  • Add the price of the plan, where text for the plan's price is in a separate span.
  • Add a "Sign Up" button
  • Create a div that contains the structure for listing out plan features.
  • Add an h4 tag that has the title of the features text. In the free plan's case, it says, "includes".
  • Create an unordered list ul and its children as list items li, listing the plan's features.

Great. Nothing too crazy, right? Let's dive into the CSS.

Let's get Griddy ๐Ÿ•บ

CSS Grid is a newer technology and an addition to CSS that makes it really easy to compose UIs and move elements around while keeping everything organized. It's outside the scope of this article to deep dive into the nitty-gritty's of CSS Grid, but check out the links in Further Reading if you're interested.

For the purposes of SuperPricey, CSS Grid helps us lay out each of the plans horizontally, organized in columns. Everything we do to make this happen is within these few lines of code.

.plans-container {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 0.8em;

Yes, that small snippet gets each of the plans to arrange themselves nicely, with an elegant gap between them too. This code can look a little magical, so it's time to demystify it.

Firstly, let's recognize that this is the plans-container class that we're looking at. There are three divs nested directly beneath this div, and each of them has a class of plan. That means that the div with plans-container is the one responsible for organizing its direct children.

Inside the class itself, we start with display: grid. This simply tells CSS that the contents of this div should be displayed and laid out with CSS Grid.

The next line is the one that sets up our columns. grid-template-columns says, "here's the template you should use to lay out the child content." In our case, we're creating three columns, each one 1fr wide. fr stands for fraction unit. An fr will fill the space, as widely as it can go. In summary, this line says, "set up three columns, and get the child contents to fill up the fully available space."

Finally, the gap property adds a little space between each of the columns. Adding ever so little space gives the grid a cleaner look.

Making things look awesome ๐ŸŒŸ

The rest of this article will be focused on the additional styling that polishes it up.

Starting with the font, I decided to use a different font than the standard serif or sans-serif. I picked up Source Sans Pro from Google Fonts. Google Fonts allows us to import a font directly into our CSS, using the import statement.

@import url("");

Next, we'll define some colors using CSS variables. Relatively new to CSS, variables allow us to define values of CSS and use them elsewhere in the stylesheet. We use the :root to make these variables accessible by classes across the rest of the stylesheet.

:root {
  --white: #fff;
  --gray: #f5f5f5;
  --green: #c5ffe4b2;
  --purple: #c5ceffb2;
  --yellow: #ffdf9bb2;
  --dark: #333;

From there, we can define the styles of the application's body in general. You'll notice that we define fonts and colors using CSS variables.

body {
  background: var(--gray);
  color: var(--dark);
  font-family: "Source Sans Pro", sans-serif;

To access a variable, we use the var() keyword, and pass in the name of the variable to use, as if it was an argument.

The next area that we use some of these color variables is for each of the plans. Each plan in our HTML has a class="plan plan--[plan-name]" where the "[plan-name]" part is the name of whatever plan is being described. The reason we add a plan--free for example, is to give us a hook in the css to change color appropriately. We can change the css like so:

.plan--free {
  background: var(--green);

.plan--pro {
  background: var(--purple);

.plan--custom {
  background: var(--yellow);

With variables and that class correctly applied, this code is quite expressive and lets us know exactly what's going on.

There are other small touches of CSS that you can check out in the styles.css file from the sandbox, but there's one last detail I'll focus on. That's the "sign up" button.

The button itself is pretty simple. It has some padding around the words so that it's not too crowded; it has a generous border-radius so that it's nice and rounded. It has centered text, a grey background, and cursor turns into a pointer when you hover over it.

.button {
  padding: 0.7em;
  border-radius: 2.5em;
  text-align: center;
  cursor: pointer;
  background: var(--gray);

What's interesting about it is that it's hoverable. This may look tricky, but CSS make it very simple. It boils down to these lines:

.button:hover {
  background-color: var(--dark);
  color: var(--white);

:hoveris considered a pseudo-class in CSS. From MDN:

"A CSS pseudo-class is a keyword added to a selector that specifies a special state of the selected element(s)."

In this case, button:hover is describing what happens when the element with this css class is hovered over. Here, the background-color changes to dark and the text color is changed to white. Hovering over these elements in the Sandbox should show how that works.

Now SuperPricey is ready. Let the random stuff be sold! See you next time!

~ Saalik

Further Reading