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

What does Industry Knowledge mean?

Friday, February 10, 2012 2:59 PM

MeetingThis week for our all-staff meeting at EffectiveUI, our CEO gave a presentation on what we’ve learned from the customer experience research that we have been doing in order to continue to improve the experiences that our customers have with us and to strengthen those relationships.   She used a word cloud of terms that our customers had used to illustrate both what we, as a company, are doing well, and what areas our customers perceive a need for improvement in.  One of the phrases in the areas for improvement that stuck out to me was “industry knowledge.”  She explained that our customers were looking for us to show more knowledge of their particular industry so that we could help guide them more effectively.  This got me thinking more on what “industry knowledge” means for a software developer.

One of this things that I’ve said at numerous interviews in the past is how I think that Computer Science is a great generalist’s degree.  Having a degree in Computer Science is like having a degree in problem solving.  I can say with 100% certainty that I’ve never solved a computer problem for the sake of solving a computer problem.  Any problem that I’m addressing is directly related to the needs of the business and the computer is simply a tool to accomplish that goal.  I have to be able to understand the business problem in order to be successful.

In my career, I’ve developed software for the nuclear environmental cleanup, laboratory operations, time and attendance tracking, financial services, mine safety, telecommunications, real estate, and municipal management industries.  All of those different industries span a career of just 14 years (counting my internship during college).  In each project, I find myself needing to rapidly learn the business of my client in order to develop software that actually works for them. 

Going into each of these projects, I usually know almost nothing about the industry or the business model.  For example, I was asked in my interview at the Mine Safety and Health Information if I had a mobile device, continuous miner, and conveyer belt in a mine, what could the mobile device tell me about the continuous miner and conveyor belt.  Having never had any contact with any mining equipment, I had a hard time coming up with a very detailed answer, but I asked a lot of questions to try to figure out what might be useful.  If I can’t understand the conversation, I have no hope of understanding the problem well enough to build a solution.  I have to be conversant in my client’s language in order for me to understand them and for them to trust my ability to deliver the solution that they need. 

With all of that being said, I will never be the subject matter expert that my client is.  I will always have to rely on them to some degree to be able to tell me if I’m pointing in the right direction.  So how do I gain the industry knowledge that customers are asking for and demonstrate to them that I truly care about them and their business? 

First, I listen and I ask a lot of questions.  I have learned to be assertive about asking questions about terms, acronyms, and interactions that I don’t understand. I’m not shy about interrupting a customer if need be to ask them to explain a term or a concept that I don’t understand or I am not familiar with.  I paraphrase the answers to make sure that I truly understood what they were trying to communicate.  Through these questions I learn more about the company, the industry, and the business problems.

Second, I draw pictures.  Diagrams are a software engineer’s best friend when it comes to understanding complex systems and business models and the relationships between them.  Drawing a diagram of the problem space really helps me see the bigger picture.

Third, I read a lot.  I read on a broad range of topics, both work related and not, to be able to understand a wide range of problems and ideas.  Having this breadth of knowledge helps me see parallels between the customer’s current problem and others that might be related.  I can say that I’ve solved a similar problem before or that I’m familiar with a similar concept, easing the customer’s concerns about lack of knowledge in their particular space.

Finally, I liberally search online.  There is definitely a skill to locating the right information online and building a search to find it.  It’s taken a lot of practice in critical thinking and information analysis to be able to separate the really useful information from the sheer volume of other noise online.  The best result is usually not the first one.

This ongoing learning process about new problems and industries is one of my favorite things about being a software engineer.  I consider myself very fortunate to be in a position where I get the opportunity to be constantly learning new things and taking on new projects.  It’s important to me that my customers feel that I understand their business, their problems, and value them as a customer and learning their business is critical to accomplishing this.

 
By: Shane
Comments

Comments

Be the first to comment on this post

Trouble

Wednesday, February 8, 2012 8:20 AM

Tags:

Mr. AttitudeWe are in so much trouble with Ethan…  He is such a character.  A couple of stories from the past couple of weeks really illustrate how far he’s come:

First, while Andrea and Ethan were in Iowa visiting her parents, he was hanging out with Grandma when she asked him to put away some of his toys.  He looks at her and says, “Seriously?”  All attitude.

Next, this past Thursday, we were all sitting in the living room after dinner when Andrea asks him, “Ethan, would you like some C-A-K-E?”  He responds, “Cake! Cake! Cake!” and runs to the kitchen.  The kid is 19 months old!  He shouldn’t have the spelling trick figured out yet.  He now has the spelling trick figured out for cake, ice cream, and cookies.  He is way too smart for his own good.

After all of this, we were looking at the development guide that our pediatrician gave us, and that said that “normal” vocabulary is 15-20 words at this point with 50 being really advanced.  We counted, and he has 21 words just to describe his own body parts at this point.  And that doesn’t even count  all of his different toys, all of the animals he knows, cars, snow, and the like.  I’m pretty sure if we really stopped to count, he would be way over 100 words that he knows now and he’s already using phrases too.  Like I said, way too smart for his own good.

 
By: Shane
Comments

Comments

Be the first to comment on this post