BlogBlog

Angled Table Headers in HTML5 and CSS3

Friday, February 17, 2012 4:09 PM

The original design compI got the design comp above for one of my projects at EffectiveUI and immediately thought, “How am I going to be able to do that in HTML and CSS?'”  The table headers are generated dynamically by system defined sections and could be different for different groups of users, so using an image for the table header was impractical.  I knew CSS3 gave me some new options using 2D transforms, but browser support was uneven.  Another problem in this design that looks like a really minor feature is the carrot under the “QuickNav” text.  Fortunately, the requirements of this project are that we are just supporting the latest versions of IE, Firefox, Chrome, and Safari, so CSS3 2D transforms it is.

My initial attempt didn’t go so well as you can see below.  Not only were the browser implementations of the 2D transforms uneven, but the documentation available online was less than complete as well. 

DxGAngledHeaders1

So all of my headers didn’t line up with their columns and the text was way out of whack too.  It turns out that the browsers calculate the position of an element first, then transform it, so I had to adjust the positioning of the elements to end up where I wanted them.  After some playing with the Skew() and Rotate() CSS3 2D transform methods, I discovered that I needed a little extra markup in each <th> cell to get the display to show up correctly.  Even with that being said, the end markup is still very clean to generate the table:

<div class="quick-nav-container">
    <h4>QuickNav</h4>
    <a class="close" href="#">x</a>
    <div class="quick-nav">
        <table>
            <thead>
                <tr>
                    <th></th>
                    <th class="skew"><div class="odd"><span>All</span></div></th>
                    <th class="skew"><div class=""><span>General</span></div></th>
                    <th class="skew"><div class="odd"><span>Typography</span></div></th>
                    <th class="skew"><div class=""><span>Colors</span></div></th>
                    <th class="skew"><div class="odd"><span>Buttons</span></div></th>
                    <th class="skew"><div class=""><span>Form Elements</span></div></th>
                    <th class="skew"><div class="odd"><span>Windows</span></div></th>
                    <th class="skew"><div class=""><span>Utilities</span></div></th>
                    <th class="skew"><div class="odd"><span>Images</span></div></th>
                    <th class="skew"><div class=""><span>Iconography</span></div></th>
                    <th class="skew"><div class="odd"><span>Layout Grids</span></div></th>
                    <th class="skew"><div class=""><span>Page Templates</span></div></th>
                    <th class="skew"><div class="odd"><span>Media</span></div></th>
                    <th class="skew"><div class=""><span>Misc.</span></div></th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td class="project-name">EffectiveUI DxG</td>
                    <td class="odd"><a href="/Search/SearchByProject?projectName=EffectiveUI%20DxG">&#187;</a></td>
                    <td class=""><a href="/Search/QuickNav?projectId=1&amp;sectionId=1">&#187;</a></td>
                    <td class="odd"><a href="/Search/QuickNav?projectId=1&amp;sectionId=2">&#187;</a></td>
                    <td class=""><a href="/Search/QuickNav?projectId=1&amp;sectionId=3">&#187;</a></td>
                    <td class="odd"><a href="/Search/QuickNav?projectId=1&amp;sectionId=4">&#187;</a></td>
                    <td class=""><a href="/Search/QuickNav?projectId=1&amp;sectionId=5">&#187;</a></td>
                    <td class="odd"><a href="/Search/QuickNav?projectId=1&amp;sectionId=6">&#187;</a></td>
                    <td class=""><a href="/Search/QuickNav?projectId=1&amp;sectionId=7">&#187;</a></td>
                    <td class="odd"><a href="/Search/QuickNav?projectId=1&amp;sectionId=8">&#187;</a></td>
                    <td class=""><a href="/Search/QuickNav?projectId=1&amp;sectionId=9">&#187;</a></td>
                    <td class="odd"><a href="/Search/QuickNav?projectId=1&amp;sectionId=10">&#187;</a></td>
                    <td class=""><a href="/Search/QuickNav?projectId=1&amp;sectionId=11">&#187;</a></td>
                    <td class="odd"><a href="/Search/QuickNav?projectId=1&amp;sectionId=12">&#187;</a></td>
                    <td class=""><a href="/Search/QuickNav?projectId=1&amp;sectionId=13">&#187;</a></td>
                </tr>
                <tr>
                    <td class="project-name">Test Project</td>
                    <td class="odd"><a href="/Search/SearchByProject?projectName=Test%20Project">&#187;</a></td>
                    <td class=""><a href="/Search/QuickNav?projectId=2&amp;sectionId=1">&#187;</a></td>
                    <td class="odd"><a href="/Search/QuickNav?projectId=2&amp;sectionId=2">&#187;</a></td>
                    <td class=""><a href="/Search/QuickNav?projectId=2&amp;sectionId=3">&#187;</a></td>
                    <td class="odd"><a href="/Search/QuickNav?projectId=2&amp;sectionId=4">&#187;</a></td>
                    <td class=""><a href="/Search/QuickNav?projectId=2&amp;sectionId=5">&#187;</a></td>
                    <td class="odd"><a href="/Search/QuickNav?projectId=2&amp;sectionId=6">&#187;</a></td>
                    <td class=""><a href="/Search/QuickNav?projectId=2&amp;sectionId=7">&#187;</a></td>
                    <td class="odd"><a href="/Search/QuickNav?projectId=2&amp;sectionId=8">&#187;</a></td>
                    <td class=""><a href="/Search/QuickNav?projectId=2&amp;sectionId=9">&#187;</a></td>
                    <td class="odd"><a href="/Search/QuickNav?projectId=2&amp;sectionId=10">&#187;</a></td>
                    <td class=""><a href="/Search/QuickNav?projectId=2&amp;sectionId=11">&#187;</a></td>
                    <td class="odd"><a href="/Search/QuickNav?projectId=2&amp;sectionId=12">&#187;</a></td>
                    <td class=""><a href="/Search/QuickNav?projectId=2&amp;sectionId=13">&#187;</a></td>
                </tr>
            </tbody>
        </table>
    </div>
</div>

As you can see in the code above, I used no images to achieve this effect.  The X close button in the upper right is a simple anchor tag with the border-radius property set to make it appear to be a circle.  The most interesting pieces to note for the angled headers are the <th class=”skew”> tags and the <div> and <span> tags contained within.  Those div and span tags are the extra markup needed to make all of the 2D transforms play nice with each other to generate the 45 degree angled headers. 

The CSS used to generate the table is as follows:

.quick-nav-container {
    background-color: #666666;
    -moz-border-radius: 4px;
    -webkit-border-radius: 4px;
    border-radius: 4px;
    position: absolute;
    z-index: 100;
    padding: 30px 14px 14px 14px;
    display: none;
}

.quick-nav-container h4 {
    position:absolute;
    color: #FFFFFF;
    font-size: 14px;
    font-weight: bold;
    width: 112px;
    top: 0px;
    left: 0px;
    text-align: center;
    padding: 8px;
}

/* creates triangle */
.quick-nav-container h4:after {
    content:"";
    position:absolute;
    bottom:-10px; /* value = - border-top-width - border-bottom-width */
    left:56px; /* controls horizontal position */
    border-width:10px 10px 0; /* vary these values to change the angle of the vertex */
    border-style:solid;
    border-color:#666666 transparent;
    /* reduce the damage in FF3.0 */
    display:block; 
    width:0;
    z-index: 1;
}

.quick-nav-container a.close {
    position: absolute;
    top: 4px;
    right: -12px;
    width: 16px;
    height: 16px;
    text-decoration: none;
    color: #333333;
    background-color: #FFFFFF;
    -moz-border-radius: 8px;
    -webkit-border-radius: 8px;
    border-radius: 8px;
    display: block;
    text-align: center;
    font-weight: bold;
    font-size: 14px;
}

.quick-nav {
    position: relative;
    background-color: #FFFFFF;
    font-size: 10px;
    padding: 20px 90px 20px 20px;
    -moz-border-radius: 4px;
    -webkit-border-radius: 4px;
    border-radius: 4px;
}

.quick-nav a {
    color: #333333;
    text-decoration: none;
    font-size: 14px;
}

.quick-nav table th.skew {
    height: 60px;
    width: 40px;
    position: relative;
    vertical-align: bottom;
}

.quick-nav table th.skew > div {
    position: relative;
    top: 0px;
    left: 30px;
    height: 100%;
    transform:skew(-45deg,0deg);
    -ms-transform:skew(-45deg,0deg); /* IE 9 */
    -moz-transform:skew(-45deg,0deg); /* Firefox */
    -webkit-transform:skew(-45deg,0deg); /* Safari and Chrome */
    -o-transform:skew(-45deg,0deg); /* Opera */    
    overflow: hidden;
    border-top: 1px solid #CCCCCC;
    border-left: 1px solid #CCCCCC;
    border-right: 1px solid #CCCCCC;
}

.quick-nav table th.skew span {
    transform:skew(45deg,0deg) rotate(315deg);
    -ms-transform:skew(45deg,0deg) rotate(315deg); /* IE 9 */
    -moz-transform:skew(45deg,0deg) rotate(315deg); /* Firefox */
    -webkit-transform:skew(45deg,0deg) rotate(315deg); /* Safari and Chrome */
    -o-transform:skew(45deg,0deg) rotate(315deg); /* Opera */        
    position: absolute;
    bottom: 15px;
    left: 1px;
    display: inline-block;
    width: 100%;
    text-align: left;
}

.quick-nav table td {
    width: 40px;
    height: 35px;
    text-align: center;
    vertical-align: middle;
    border: 1px solid #CCCCCC;
}

.quick-nav table td a {
    display: block;
    width: 100%;
    text-align: center;
}

.quick-nav table td.project-name {
    width: auto;
    text-align: right;
    font-weight: bold;
    border: none;
    padding-right: 8px;
}

.quick-nav table .odd {
    background-color: #E8E8E8;
}

The most important sections are highlighted above in the selectors for “.quick-nav table th.skew,” “.quick-nav table th.skew > div,” and “.quick-nav table th.skew span.”  This is where the rotation and absolute positioning happens to make the rotation happen correctly.  For the carrot below, “QuickNav,” I used the speech bubbles technique described by Nicolas Gallagher at http://nicolasgallagher.com/pure-css-speech-bubbles/.  The final result is below, pixel for pixel perfect with the design comp and a new technique that I will definitely be keeping in my back pocket for future projects.

The completed angled headers

 
By: Shane
10 Comments

Comments

  • Andy 2/23/20123:23 PM Thanks for sharing this! The lack of support in older browsers may eliminate this from my list of options, but it was nice to be able to have a quick starting point that I could use to show this option to the rest of my team. For anybody reading this that wants to just take the code and play around a bit, make sure you add "border-collapse: collapse" to the table and "padding: 0" to the th elements. I'm thinking Shane must have those defined in another spot in the CSS and that threw me for a loop for a second when I put together a test file. Anyway, thanks again!
  • Shane Church 2/23/20123:54 PM @Andy: Thanks for the comments. Due to the kinds of layouts that we routinely build at EffectiveUI, I typically use Eric Meyer's Reset CSS (http://meyerweb.com/eric/tools/css/reset/) to reset any browser defaults, so that is where the border-collapse:collapse" and "padding:0" elements that you mentioned are defined.
  • Shala 8/24/201212:57 AM Skew is a nonstandard function, e.g. with Firefox 14 it does not work. However there are the standard functions skewX and skewY, if you replace all occurrences of scew with skewX and remove the second argument (which is 0deg always anyways) it works perfectly well.
  • Chrerops 5/7/20174:04 AM Secure Progesterone Hormone Replacement Low Price Mastercard Nevada Brand Propecia Best Buy Discount Clobetasol Saturday Delivery Store Price Baton Rouge Propecia Itch Skin Clonidine Overnight Kamagra Vs Viagra [url=http://byuvaigranonile.com]viagra[/url] Celebrex Online No Prescription
  • Kennlewbrien 6/16/201711:37 AM Comprare Levitra Generico [url=http://buy-levitra-10mg.buylevi.com]Buy Levitra 10mg[/url] Priligy Oder Viagra Propecia Herz [url=http://dapoxetine-online.priliorder.com]Dapoxetine Online[/url] Viagra A Los 40 Anos Foro Cialis 10 [url=http://cial40mg.com/buy-cheap-cialis-on-line.php]Buy Cheap Cialis On Line[/url] Zithromax Dose In Children Cialis Occhi Rossi [url=http://real-viagra-online.via100mg.com]Real Viagra Online[/url] Levitra Food Propecia Atopico [url=http://viacheap.com]viagra[/url] Clomid Jeulin Viagra By Mail [url=http://kamagra-pharmacy.kamagpills.com]Kamagra Pharmacy[/url] Cialis Generic On Line United Pharmacies Propecia [url=http://xenical.ccrpdc.com/buy-generic-xenical.php]Buy Generic Xenical[/url] Ed Meds In Canada
  • Kennlewbrien 6/19/20178:04 PM Buy Bactroban Uk [url=http://lasix.ccrpdc.com/buy-online-lasix.php]Buy Online Lasix[/url] Amoxicillin 500 Viagra Preiswert [url=http://levitra-online.buylevi.com]Levitra Online[/url] Cialis Netpharm Amoxicillin Typical Dose [url=http://cial40mg.com/cheap-cialis-no-rx.php]Cheap Cialis No Rx[/url] Prix De Xenical 120 Mg Canadianmeds 24hr [url=http://buy-online-kamagra.kamagpills.com]Buy Online Kamagra[/url] Mail Order Stendra Internet Cod Only Next Day Delivery Celecoxib 200 Mg Price [url=http://dapoxetine-purchase.priliorder.com]Dapoxetine Purchase[/url] Viagra Online Auf Rechnung Viagra Canadian [url=http://via100mg.com]Buy Viagra[/url] Buy Generic Levitra Uk Compare Viagra To Generic [url=http://viacheap.com]viagra[/url] Tab generic isotretinoin website cod accepted
  • ShanAgow 11/30/20178:31 PM Lexapro Mail Order Us Pharmacy Kamagra Oral Jelly Wiki Cialis With Prescription [url=http://costofcial.com]cialis[/url] For Sale Generic Legally Dutasteride Mastercard Accepted Store Chicago Keflex Online
  • ShanAgow 11/30/20178:31 PM Lexapro Mail Order Us Pharmacy Kamagra Oral Jelly Wiki Cialis With Prescription [url=http://costofcial.com]cialis[/url] For Sale Generic Legally Dutasteride Mastercard Accepted Store Chicago Keflex Online
  • Briguitty 1/28/20185:38 AM Cheapest Indian Prices For Nizagara Cialis O Levitra [url=http://cial20mg.com]cialis price[/url] Generic Levaquin France With Free Shipping With Doctor Consult Levitra Pas Cher
  • ThaBroope 2/1/20187:26 PM Women Viagra Pills Generic Finasteride Drugs Propecia Effetti Collaterali Di Finasteride [url=http://tadalaffbuy.com]cialis[/url] Amoxicillin The Right Dose Forseniors Tadalis Sx Achat En Ligne