Marc Audet Marc Audet - 11 months ago 162
CSS Question

Styling a funnel stack layout using native CSS and HTML

I want to show the data like funnel stack as illustrated below.

enter image description here

I was able to create the taper using borders, for example:

<div class="taper"></div>

and using the following CSS:

.taper {
width: 200px;
height: 0px;
border-color: lightgray transparent;
border-style: solid;
border-width: 50px 25px 0 25px;

Of course, the idea would be to wrap this
in a container, add other elements and position them as needed, a bit of work but doable.

However, I don't necessarily know how many lines (levels, 7 in this example) will be needed and I don't really want to do a lot of math to determine the width of each taper and so on.

If there a more bullet-proof way of doing this?

I don't want a JavaScript/jQuery based solution (trying to keep this lightweight) and would prefer to avoid background images (I may want to skin/customize the colors later and don't want to bother with image files).

Fiddle reference:

Browser support: modern browsers are fine, legacy support, as long as it degrades nicely.

Answer Source

TL;DR : see the example at

A way to create a funnel stack is with pseudoelements: with this basic markup

    <li>1,234,567,890 <span>Tooltip: 0</span></li>
    <li>234,567,890 <span>Tooltip: 0</span></li>    
    <li>2,345,678 <span>Tooltip: 0</span></li>    
    <li>23,567  <span>Tooltip: 0</span></li>
    <li>4,567<span>Tooltip: 0</span></li>    
    <li>23 <span>Tooltip: 0</span></li>
    <li>4 <span>Tooltip: 0</span></li>    

we could create the funnel using borders, so we can draw a kind of trapezoid as a background in this way:

ul { 
    position: relative; 
    overflow: hidden; 
    font: 14px Arial; 
    margin: 0; padding: 0; 
    list-style: none; 
    text-align: center; 

ul:before { 
    content: "";
    position: absolute;
    z-index: -1;
    left: 50%;
    margin-left: -120px;
    width: 0;
    border-top: 800px solid #ccc;
    border-left: 120px solid #fff;
    border-right: 120px solid #fff;

The <ul> is 100% wide, so we could give it a text-align: center and all the amounts are properly centered

Then the space between elements could be obtained as well with pseudoelements again:

li:after,li:before {
   content: "";
   display: block;
   height: 0.4em;
   background: #fff;
   width: 100%;
li:before { border-top: 1px dotted #ccc }
li:first-child:before { border: 0; }

while the tooltip text could be positioned (the <li> needs to have position: relative defined), trying to properly adjust both left and margin-left properties (especially for lower screen resolution, but you may use mediaqueries for this purpose), e.g.

li span {
    position: absolute;
    left: 60%;
    white-space: nowrap;
    margin-left: 100px;

li:nth-child(2) span { left: 59%; }
li:nth-child(3) span { left: 58% }
li:nth-child(4) span { left: 57% }
li:nth-child(5) span { left: 56% }
li:nth-child(6) span { left: 55% }
li:nth-child(7) span { left: 54% }
li:nth-child(8) span { left: 53% }
li:nth-child(9) span { left: 52% }
li:nth-child(10) span { left: 51% }

basically this example may work even on IE8 if you change each :nth-child with the adjacency selector (e.g. li + li + li + ... + span )

Hope it could be helpful.