A ready-to-use pricing table is one of those resources to have in our toolbox. They are not particular challenging in terms of design and user experience, yet they represent a key section of our web page: it's where the potential client takes action.
We put together an easy-to-customise pricing table, in 3 different styles. Besides we integrated our popular Bouncy Content Filter as transition while switching from one plan to another.
On small devices we took a new approach: instead of listing all the features vertically - which would force the user to scroll a lot to go past the pricing section, we listed them horizontally. This way we save a lot of space; users can compare all the prices at a glance, and they can dive deeper into the features if interested.
Creating the structure
The HTML is structured in 2 blocks: a div.cd-pricing-switcher
containing the filter, and a ul.cd-pricing-list
, containing the pricing tables. Inside each list item of the .cd-pricing-list
we nested a second ul
element (the one which rotates) containing the pricing tables as list items.
Each pricing table is made up of a .cd-pricing-header
(containing plan title and price), a .cd-pricing-body
(containing plan features) and a .cd-pricing-footer
(containing the action button).
<div class="cd-pricing-container">
<div class="cd-pricing-switcher">
<p class="fieldset">
<input type="radio" name="duration" value="monthly" id="monthly" checked>
<label for="monthly">Monthly</label>
<input type="radio" name="duration" value="yearly" id="yearly">
<label for="yearly">Yearly</label>
<span class="cd-switch"></span>
</p>
</div> <!-- .cd-pricing-switcher -->
<ul class="cd-pricing-list">
<li>
<ul class="cd-pricing-wrapper">
<li data-type="monthly" class="is-visible">
<header class="cd-pricing-header">
<h2>Basic</h2>
<div class="cd-price">
<span class="cd-currency">$</span>
<span class="cd-value">30</span>
<span class="cd-duration">mo</span>
</div>
</header> <!-- .cd-pricing-header -->
<div class="cd-pricing-body">
<ul class="cd-pricing-features">
<li><em>256MB</em> Memory</li>
<!-- other features here -->
</ul>
</div> <!-- .cd-pricing-body -->
<footer class="cd-pricing-footer">
<a class="cd-select" href="http://codyhouse.co">Select</a>
</footer> <!-- .cd-pricing-footer -->
</li>
<li data-type="yearly" class="is-hidden">
<!-- pricing table content here -->
</li>
</ul> <!-- .cd-pricing-wrapper -->
</li>
<li class="cd-popular">
<ul class="cd-pricing-wrapper">
<li data-type="monthly" class="is-visible">
<!-- pricing table content here -->
</li>
<li data-type="yearly" class="is-hidden">
<!-- pricing table content here -->
</li>
</ul>
</li> <!-- .cd-pricing-wrapper -->
<li>
<ul class="cd-pricing-wrapper">
<li data-type="monthly" class="is-visible">
<!-- pricing table content here -->
</li>
<li data-type="yearly" class="is-hidden">
<!-- pricing table content here -->
</li>
</ul> <!-- .cd-pricing-wrapper -->
</li>
</ul> <!-- .cd-pricing-list -->
</div> <!-- .cd-pricing-container -->
Adding style
On small devices, the .cd-pricing-footer
is in position: absolute
and placed over the .cd-pricing-header
to cover it (we assigned the same height to both elements). The action button has a display: block
and height: 100%
so that it has the same dimension of the table footer (the pointer-events: none
assigned to the .cd-pricing-header
assures that the button is clickable).
The .cd-pricing-body
has overflow-x: auto
to hide part of the ul.cd-pricing-features
element - whose width could be higher.
.cd-pricing-header {
height: 80px;
pointer-events: none;
}
.cd-pricing-body {
overflow-x: auto;
/* smooth scrolling on touch devices */
-webkit-overflow-scrolling: touch;
}
.cd-pricing-footer {
position: absolute;
top: 0;
left: 0;
height: 80px;
width: 100%;
}
.cd-select {
display: block;
height: 100%;
/* hide button text on mobile */
overflow: hidden;
text-indent: 100%;
white-space: nowrap;
color: transparent;
}
On desktop devices (viewport width more than 1170px), the css is pretty straightforward (you can find additional comments in the scss/css file for the tricky parts).
One important note : we created 3 classes to customise the pricing tables (all classes have to be applied to the .cd-pricing-container
element):
cd-full-width
- set width: 100% to the.cd-pricing-container
, with max-width: none (as default, we set width: 90% and max-width: 1170px);cd-tables-have-margin
- add a right margin to the pricing tables;cd-secondary-theme
- different color theme combination;
In our demo we created 3 different table styles: the first is the default one, the second is obtained adding to the .cd-pricing-container
both .cd-full-width
and .cd-second-theme
classes, and the last adding the .cd-tables-have-margin
class.
One important note: the styles associated to these 3 classes differ on desktop devices only.
Additional note on the bouncy animation: as pointed out in the comments, if you have only 2 switching options (in our demo 'Monthly' and 'Yearly'), it feels more natural to invert the rotation direction while switching from one option to the other. For this reason, we created the .cd-bounce-invert
class to be added to the ul.cd-pricing-list
. If you have more than 2 options, just remove this class and the rotation will preserve the direction.
Events handling
For the pricing table rotation, you can check what we did for the Bouncy Content Filter.
Besides, we used jQuery to remove the subtle gradient on the right side of the pricing table body (mobile version only) – that we added to indicate that there’s more content – at the end of the scrolling.