问题
I want to show the data like funnel stack as illustrated below.
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 div.taper
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: http://jsfiddle.net/audetwebdesign/fBax3/
Browser support: modern browsers are fine, legacy support, as long as it degrades nicely.
回答1:
TL;DR : see the example at http://jsfiddle.net/97Yr6/
A way to create a funnel stack is with pseudoelements: with this basic markup
<ul>
<li>1,234,567,890 <span>Tooltip: 0</span></li>
<li>234,567,890 <span>Tooltip: 0</span></li>
<li>23,456,789</li>
<li>2,345,678 <span>Tooltip: 0</span></li>
<li>234,567</li>
<li>23,567 <span>Tooltip: 0</span></li>
<li>4,567<span>Tooltip: 0</span></li>
<li>789</li>
<li>23 <span>Tooltip: 0</span></li>
<li>4 <span>Tooltip: 0</span></li>
</ul>
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.
回答2:
For those looking for a funnel with different colors for each layer in the stack:
http://jsfiddle.net/D9GLr/
HTML:
<ul>
<li>1,234,567,890</li>
<li>234,567,890</li>
<li>23,456,789</li>
<li>2,345,678</li>
<li>234,567</li>
</ul>
CSS:
ul {
margin: 0 200px; padding: 0;
list-style: none;
text-align: center;
}
li {
font-size:14px;
line-height:30px;
height:30px;
width:200px;
position:relative;
background:#ccc;
border-bottom:1px solid #fff;
}
li:before {
content: "";
position: absolute;
z-index: 10;
left: 0%;
margin-left: -30px;
width:30px;
border-top: 30px solid #ccc;
border-left: 30px solid transparent;
}
li:after {
content: "";
position: absolute;
z-index: 10;
right: 0%;
margin-left: 30px;
width:30px;
border-top: 30px solid #ccc;
border-right: 30px solid transparent;
}
li:nth-child(1) { background:#ddd; }
li:nth-child(1):before,
li:nth-child(1):after { border-top-color:#ddd; }
li:nth-child(1):before { width:200px; margin-left: -200px; }
li:nth-child(1):after { width:200px; margin-right:-200px; }
li:nth-child(2) { background:#bbb; }
li:nth-child(2):before,li:nth-child(2):after { border-top-color:#bbb; }
li:nth-child(2):before { width:170px; margin-left: -170px; }
li:nth-child(2):after { width:170px; margin-right:-170px; }
li:nth-child(3) { background:#999; }
li:nth-child(3):before,
li:nth-child(3):after { border-top-color:#999; }
li:nth-child(3):before { width:140px; margin-left: -140px; }
li:nth-child(3):after { width:140px; margin-right:-140px; }
li:nth-child(4) { background:#777; }
li:nth-child(4):before,
li:nth-child(4):after { border-top-color:#777; }
li:nth-child(4):before { width:110px; margin-left: -110px; }
li:nth-child(4):after { width:110px; margin-right:-110px; }
li:nth-child(5) { background:#555; }
li:nth-child(5):before,
li:nth-child(5):after { border-top-color:#555; }
li:nth-child(5):before { width:80px; margin-left: -80px; }
li:nth-child(5):after { width:80px; margin-right:-80px; }
回答3:
Ryan,
Thanks for your code example! I took your example and changed it a bit to reflect my project needs. Maybe someone will find this helpful.
body {
font-family: Lato, Arial, Helvetica, sans-serif;
}
.center-text {
text-align: center;
margin: 0px auto;
}
.funnel {
width: 750px;
margin: 0 auto;
}
ul.one {
margin: 40px 278px;
padding: 0;
list-style: none;
text-align: center;
}
.one .funnel-top {
position: absolute;
top: -7px;
left: -199px;
z-index: 20;
width: 599px;
height: 14px;
background: #919eb1;
border-radius: 100%;
}
.one .funnel-bottom {
position: absolute;
bottom: -7px;
left: -20px;
z-index: 20;
width: 240px;
height: 16px;
background: #273445;
border-radius: 100%;
}
.one li {
font-size: 16px;
line-height: 70px;
height: 70px;
width: 200px;
position: relative;
background: #ccc;
color: #ffffff;
font-weight: bold;
}
.one li span {
background: rgba(255, 255, 255, 0.3);
padding: 5px 8px;
border-radius: 4px;
margin-left: 15px;
}
.one li:before {
content: "";
position: absolute;
z-index: 10;
left: 0%;
margin-left: -30px;
width: 30px;
border-top: 70px solid #ccc;
border-left: 30px solid transparent;
}
.one li:after {
content: "";
position: absolute;
z-index: 10;
right: 0%;
margin-left: 30px;
width: 30px;
border-top: 70px solid #ccc;
border-right: 30px solid transparent;
}
.one li:nth-child(1) {
background: #919eb1;
}
.one li:nth-child(1):before,
.one li:nth-child(1):after {
border-top-color: #919eb1;
}
.one li:nth-child(1):before {
width: 200px;
margin-left: -200px;
}
.one li:nth-child(1):after {
width: 200px;
margin-right: -200px;
}
.one li:nth-child(2) {
background: #8491a5;
}
.one li:nth-child(2):before,
.one li:nth-child(2):after {
border-top-color: #8491a5;
}
.one li:nth-child(2):before {
width: 170px;
margin-left: -170px;
}
.one li:nth-child(2):after {
width: 170px;
margin-right: -170px;
}
.one li:nth-child(3) {
background: #778599;
}
.one li:nth-child(3):before,
.one li:nth-child(3):after {
border-top-color: #778599;
}
.one li:nth-child(3):before {
width: 140px;
margin-left: -140px;
}
.one li:nth-child(3):after {
width: 140px;
margin-right: -140px;
}
.one li:nth-child(4) {
background: #6d7b8f;
}
.one li:nth-child(4):before,
.one li:nth-child(4):after {
border-top-color: #6d7b8f;
}
.one li:nth-child(4):before {
width: 110px;
margin-left: -110px;
}
.one li:nth-child(4):after {
width: 110px;
margin-right: -110px;
}
.one li:nth-child(5) {
background: #606f84;
}
.one li:nth-child(5):before,
.one li:nth-child(5):after {
border-top-color: #606f84;
}
.one li:nth-child(5):before {
width: 80px;
margin-left: -80px;
}
.one li:nth-child(5):after {
width: 80px;
margin-right: -80px;
}
.one li:nth-child(6) {
background: #536075;
}
.one li:nth-child(6):before,
.one li:nth-child(6):after {
border-top-color: #536075;
}
.one li:nth-child(6):before {
width: 50px;
margin-left: -50px;
}
.one li:nth-child(6):after {
width: 50px;
margin-right: -50px;
}
ul.two {
margin: 40px 278px;
padding: 0;
list-style: none;
text-align: center;
}
.two .funnel-top {
position: absolute;
top: -7px;
left: -199px;
z-index: 20;
width: 599px;
height: 14px;
background: #1b99e6;
border-radius: 100%;
}
.two .funnel-bottom {
position: absolute;
bottom: -7px;
left: -20px;
z-index: 20;
width: 240px;
height: 16px;
background: #003352;
border-radius: 100%;
}
.two li {
font-size: 16px;
line-height: 70px;
height: 70px;
width: 200px;
position: relative;
background: #ccc;
color: #ffffff;
font-weight: bold;
}
.two li span {
background: rgba(255, 255, 255, 0.3);
padding: 5px 8px;
border-radius: 4px;
margin-left: 15px;
}
.two li:before {
content: "";
position: absolute;
z-index: 10;
left: 0%;
margin-left: -30px;
width: 30px;
border-top: 70px solid #ccc;
border-left: 30px solid transparent;
}
.two li:after {
content: "";
position: absolute;
z-index: 10;
right: 0%;
margin-left: 30px;
width: 30px;
border-top: 70px solid #ccc;
border-right: 30px solid transparent;
}
.two li:nth-child(1) {
background: #1b99e6;
}
.two li:nth-child(1):before,
.two li:nth-child(1):after {
border-top-color: #1b99e6;
}
.two li:nth-child(1):before {
width: 200px;
margin-left: -200px;
}
.two li:nth-child(1):after {
width: 200px;
margin-right: -200px;
}
.two li:nth-child(2) {
background: #148ad3;
}
.two li:nth-child(2):before,
.two li:nth-child(2):after {
border-top-color: #148ad3;
}
.two li:nth-child(2):before {
width: 170px;
margin-left: -170px;
}
.two li:nth-child(2):after {
width: 170px;
margin-right: -170px;
}
.two li:nth-child(3) {
background: #117fc3;
}
.two li:nth-child(3):before,
.two li:nth-child(3):after {
border-top-color: #117fc3;
}
.two li:nth-child(3):before {
width: 140px;
margin-left: -140px;
}
.two li:nth-child(3):after {
width: 140px;
margin-right: -140px;
}
.two li:nth-child(4) {
background: #0b75b6;
}
.two li:nth-child(4):before,
.two li:nth-child(4):after {
border-top-color: #0b75b6;
}
.two li:nth-child(4):before {
width: 110px;
margin-left: -110px;
}
.two li:nth-child(4):after {
width: 110px;
margin-right: -110px;
}
.two li:nth-child(5) {
background: #006bac;
}
.two li:nth-child(5):before,
.two li:nth-child(5):after {
border-top-color: #006bac;
}
.two li:nth-child(5):before {
width: 80px;
margin-left: -80px;
}
.two li:nth-child(5):after {
width: 80px;
margin-right: -80px;
}
.two li:nth-child(6) {
background: #005f98;
}
.two li:nth-child(6):before,
.two li:nth-child(6):after {
border-top-color: #005f98;
}
.two li:nth-child(6):before {
width: 50px;
margin-left: -50px;
}
.two li:nth-child(6):after {
width: 50px;
margin-right: -50px;
}
<br />
<div class="funnel leads estimated">
<h2 class="center-text">Estimated 100 Day Lead Conversion</h2>
<ul class="one">
<li>
<div class="funnel-top"></div>
1574<span>Contacts</span>
</li>
<li>203<span>MQL2</span>
</li>
<li>112<span>MQL2</span>
</li>
<li>57<span>SAL</span>
</li>
<li>11<span>SQL</span>
</li>
<li>
<div class="funnel-bottom"></div>
4<span>Wins</span>
</li>
</ul>
</div>
<div class="funnel leads estimated">
<h2 class="center-text">Actual 100 Day Lead Conversion</h2>
<ul class="two">
<li>
<div class="funnel-top"></div>
1574<span>Contacts</span>
</li>
<li>203<span>MQL2</span>
</li>
<li>112<span>MQL2</span>
</li>
<li>57<span>SAL</span>
</li>
<li>11<span>SQL</span>
</li>
<li>
<div class="funnel-bottom"></div>
4<span>Wins</span>
</li>
</ul>
</div>
View on JSFiddle
回答4:
I like the approach of dividing it into few divs. See the code here
I have to add code so an example:
<div class="cont">
<div class="taper-left"></div>
<div class="taper-center">123,456,789</div>
<div class="taper-right"></div>
</div>
and the CSS:
.taper-right {
width: 25px;
height: 0px;
border-color: lightgray transparent;
border-style: solid;
border-width: 50px 25px 0 0px;
float: left;
}
.taper-left {
width: 25px;
height: 0px;
border-color: lightgray transparent;
border-style: solid;
border-width: 50px 0px 0px 25px;
float: left;
}
.taper-center {
width: 200px;
height: 34px;
border-color: lightgray transparent;
border-style: solid;
background-color: lightgray transparent;
background-color: lightgray;
float: left;
text-align: center;
padding-top: 10px;
}
回答5:
Here's another take on it, this version is a bit more responsive: https://jsfiddle.net/ehynds/j3fL6hof
.funnel {
list-style-type: none;
margin: 0;
padding: 0;
text-align: center;
color: #fff;
background-color: #fff;
}
li {
padding: 10px 5px;
margin: 0;
background-color: #409ca9;
margin-bottom: 5px;
position: relative;
overflow: hidden;
}
div:last-child {
font-size: 36px
}
li:last-child {
background-color: #a5c13f;
}
li:before,
li:after {
content: '';
position: absolute;
top: 0;
height: 0;
border-bottom: 90px solid #fff;
}
li:before {
left: 0;
border-right: 27px solid transparent;
border-left: 0;
}
li:after {
right: 0;
border-left: 27px solid transparent;
border-right: 0;
}
li:nth-child(1):before,
li:nth-child(1):after {
width: 0;
}
li:nth-child(2):before,
li:nth-child(2):after {
width: 25px;
}
li:nth-child(3):before,
li:nth-child(3):after {
width: 50px;
}
li:nth-child(4):before,
li:nth-child(4):after {
width: 75px;
height: 100%;
border: 0;
background-color: #fff;
}
<ul class="funnel">
<li>
<div>First Segment</div>
<div>12,345</div>
</li>
<li>
<div>Second Segment</div>
<div>2,345</div>
</li>
<li>
<div>Third Segment</div>
<div>345</div>
</li>
<li>
<div>Fourth Segment</div>
<div>45</div>
</li>
</ul>
来源:https://stackoverflow.com/questions/16439777/styling-a-funnel-stack-layout-using-native-css-and-html