✨ Get all templates and new upcoming releases for just $89. Limited time offer ✨

Building a Mobile-Friendly Pricing Table with Tailwind CSS

Preview of the pricing table inspired to DigitalOcean

There’s no doubt, tables are a true nightmare when it comes to responsive layouts. They often need a lot of space horizontally, which is a problem on phones and tablets where space is limited.

Usually, we end up making the table scroll horizontally. It works, but it’s not the best experience for the user. Making tables work well on small screens is tough. The best solutions are those that reorganize the content specifically for smaller screens, but this is a real challenge when using tables.

However, we recently came across a smart solution from DigitalOcean. They have a pricing table that looks great on any device. We liked it so much that we wanted to make our own mobile-friendly pricing table with Tailwind CSS.

The trick is to make the rows turn into columns on small screens. That way, you can view the content of a single row without having to scroll. We still keep the horizontal scrolling, but we make it better with:

  • Sticky headers: These stay fixed at the left while you scroll, so you always know what each column is about
  • CSS scroll snapping to create a controlled scroll experience by declaring specific snapp positions

The result is excellent, and focuses on what truly matters: the content. Users can easily compare different plans and make informed decisions. It’s a great example of how to make a table responsive and user-friendly.

Code

<table class="
    table-auto
    md:w-full
    text-sm
    snap-x
    scroll-pl-4
    max-md:grid
    max-md:gap-x-12
    max-md:overflow-x-scroll
    max-md:-mx-4
    max-md:px-4
    [&_thead]:bg-slate-50
    max-md:[&_thead]:contents
    max-md:[&_tbody]:contents
    [&_tbody_tr]:border-b
    [&_tbody_tr]:border-slate-100                
    max-md:[&_tr]:contents
    [&_th]:text-slate-900
    [&_th]:font-semibold
    [&_td]:text-slate-600
    [&_th]:py-3
    md:[&_th]:first:pl-3
    [md:&_th]:last:pr-3
    [&_td]:pb-3
    md:[&_td]:pt-3
    md:[&_td]:first:pl-3
    md:[&_td]:last:pr-3
    [&_tr_td:first-child]:font-medium
    [&_tr_td:first-child]:text-slate-900
    [&_th]:whitespace-nowrap
    [&_td]:whitespace-nowrap
    max-md:[&_th]:min-w-[60vw]
    max-md:[&_td]:min-w-[60vw]
    max-md:[&_tr:last-child_td]:min-w-[calc(100vw-2rem)]
    [&_th]:text-left
    [&_th]:group-last:text-right
    [&_td]:text-left
    md:[&_td:last-of-type]:text-right
    max-md:[&_th]:sticky
    max-md:[&_th]:left-0
    [&_td]:snap-start
    max-md:[&_td]:border-b
    max-md:[&_td:last-of-type]:border-none
    [&_td]:border-slate-100
">
    <thead>
        <tr>
            <th class="max-md:row-start-1 max-md:col-start-1">Plan</th>
            <th class="max-md:row-start-3 max-md:col-start-1">Storage</th>
            <th class="max-md:row-start-5 max-md:col-start-1">Bandwidth</th>
            <th class="max-md:row-start-7 max-md:col-start-1">Emails</th>
            <th class="max-md:row-start-9 max-md:col-start-1">SSD</th>
            <th class="max-md:row-start-11 max-md:col-start-1">$/hr</th>
            <th class="max-md:row-start-13 max-md:col-start-1">$/mo</th>
            <th class="max-md:row-start-[15] max-md:col-start-1"><span class="sr-only">Buy</span></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td class="max-md:row-start-2 max-md:col-start-1">Basic</td>
            <td class="max-md:row-start-4 max-md:col-start-1">20GB</td>
            <td class="max-md:row-start-6 max-md:col-start-1">1TB</td>
            <td class="max-md:row-start-8 max-md:col-start-1">10</td>
            <td class="max-md:row-start-10 max-md:col-start-1">
                <span class="h-5 w-5 flex items-center">
                    <svg class="shrink-0 fill-slate-400 mr-3" xmlns="http://www.w3.org/2000/svg" width="12" height="12">
                        <rect width="12" height="2" y="5" rx="1"/>
                    </svg>                            
                </span>
            </td>
            <td class="max-md:row-start-12 max-md:col-start-1">0.015</td>
            <td class="max-md:row-start-[14] max-md:col-start-1">10</td>
            <td class="max-md:row-start-[16] max-md:col-start-1">
                <a class="inline-flex justify-center rounded-lg bg-indigo-500 px-2.5 py-1.5 text-sm font-medium text-white shadow-sm shadow-indigo-950/10 hover:bg-indigo-600 focus-visible:outline-none focus-visible:ring focus-visible:ring-indigo-300 dark:focus-visible:ring-slate-600 transition-colors duration-150 group" href="#0">
                    <span class="md:sr-only">Get Started</span>
                    <span class="tracking-normal text-indigo-300 md:text-white group-hover:translate-x-0.5 transition-transform duration-150 ease-in-out max-md:ml-1">-&gt;</span>
                </a>                            
            </td>
        </tr>
        <tr>
            <td class="max-md:row-start-2 max-md:col-start-2">Silver</td>
            <td class="max-md:row-start-4 max-md:col-start-2">40GB</td>
            <td class="max-md:row-start-6 max-md:col-start-2">2TB</td>
            <td class="max-md:row-start-8 max-md:col-start-2">20</td>
            <td class="max-md:row-start-10 max-md:col-start-2">
                <span class="h-5 w-5 flex items-center">
                    <svg class="shrink-0 fill-emerald-500 mr-3" xmlns="http://www.w3.org/2000/svg" width="12" height="9">
                        <path d="M10.28.28 3.989 6.575 1.695 4.28A1 1 0 0 0 .28 5.695l3 3a1 1 0 0 0 1.414 0l7-7A1 1 0 0 0 10.28.28Z"></path>
                    </svg>                            
                </span>
            </td>
            <td class="max-md:row-start-12 max-md:col-start-2">0.03</td>
            <td class="max-md:row-start-[14] max-md:col-start-2">20</td>
            <td class="max-md:row-start-[16] max-md:col-start-2">
                <a class="inline-flex justify-center rounded-lg bg-indigo-500 px-2.5 py-1.5 text-sm font-medium text-white shadow-sm shadow-indigo-950/10 hover:bg-indigo-600 focus-visible:outline-none focus-visible:ring focus-visible:ring-indigo-300 dark:focus-visible:ring-slate-600 transition-colors duration-150 group" href="#0">
                    <span class="md:sr-only">Get Started</span>
                    <span class="tracking-normal text-indigo-300 md:text-white group-hover:translate-x-0.5 transition-transform duration-150 ease-in-out max-md:ml-1">-&gt;</span>
                </a>                            
            </td>
        </tr>
        <tr>
            <td class="max-md:row-start-2 max-md:col-start-3">Gold</td>
            <td class="max-md:row-start-4 max-md:col-start-3">80GB</td>
            <td class="max-md:row-start-6 max-md:col-start-3">4TB</td>
            <td class="max-md:row-start-8 max-md:col-start-3">40</td>
            <td class="max-md:row-start-10 max-md:col-start-3">
                <span class="h-5 w-5 flex items-center">
                    <svg class="shrink-0 fill-emerald-500 mr-3" xmlns="http://www.w3.org/2000/svg" width="12" height="9">
                        <path d="M10.28.28 3.989 6.575 1.695 4.28A1 1 0 0 0 .28 5.695l3 3a1 1 0 0 0 1.414 0l7-7A1 1 0 0 0 10.28.28Z"></path>
                    </svg>                            
                </span>
            </td>
            <td class="max-md:row-start-12 max-md:col-start-3">0.06</td>
            <td class="max-md:row-start-[14] max-md:col-start-3">40</td>
            <td class="max-md:row-start-[16] max-md:col-start-3">
                <a class="inline-flex justify-center rounded-lg bg-indigo-500 px-2.5 py-1.5 text-sm font-medium text-white shadow-sm shadow-indigo-950/10 hover:bg-indigo-600 focus-visible:outline-none focus-visible:ring focus-visible:ring-indigo-300 dark:focus-visible:ring-slate-600 transition-colors duration-150 group" href="#0">
                    <span class="md:sr-only">Get Started</span>
                    <span class="tracking-normal text-indigo-300 md:text-white group-hover:translate-x-0.5 transition-transform duration-150 ease-in-out max-md:ml-1">-&gt;</span>
                </a>                            
            </td>
        </tr>
        <tr>
            <td class="max-md:row-start-2 max-md:col-start-4">Platinum</td>
            <td class="max-md:row-start-4 max-md:col-start-4">160GB</td>
            <td class="max-md:row-start-6 max-md:col-start-4">8TB</td>
            <td class="max-md:row-start-8 max-md:col-start-4">80</td>
            <td class="max-md:row-start-10 max-md:col-start-4">
                <span class="h-5 w-5 flex items-center">
                    <svg class="shrink-0 fill-emerald-500 mr-3" xmlns="http://www.w3.org/2000/svg" width="12" height="9">
                        <path d="M10.28.28 3.989 6.575 1.695 4.28A1 1 0 0 0 .28 5.695l3 3a1 1 0 0 0 1.414 0l7-7A1 1 0 0 0 10.28.28Z"></path>
                    </svg>                            
                </span>
            </td>
            <td class="max-md:row-start-[12] max-md:col-start-4">0.12</td>
            <td class="max-md:row-start-[14] max-md:col-start-4">80</td>
            <td class="max-md:row-start-[16] max-md:col-start-4">
                <a class="inline-flex justify-center rounded-lg bg-indigo-500 px-2.5 py-1.5 text-sm font-medium text-white shadow-sm shadow-indigo-950/10 hover:bg-indigo-600 focus-visible:outline-none focus-visible:ring focus-visible:ring-indigo-300 dark:focus-visible:ring-slate-600 transition-colors duration-150 group" href="#0">
                    <span class="md:sr-only">Get Started</span>
                    <span class="tracking-normal text-indigo-300 md:text-white group-hover:translate-x-0.5 transition-transform duration-150 ease-in-out max-md:ml-1">-&gt;</span>
                </a>                            
            </td>
        </tr>
    </tbody>
</table>