Creating Angled Tabs using CSS3

by Jack Bradford 15. January 2012 01:51

The new CSS3 transform property adds a host of options for, well, transforming, page elements. The latest revision even adds 3D transformations. I'll be starting easy by using the rotate method to create a "tabs" menu like this:

I have used graceful degradation for non supporting browsers, so the tabs should look like the following in Internet Explorer 9 and below.

Older versions of IE do support rotation of 90/180/270 degrees, but I will not be using this.

The HTML markup

The HTML markup is a simple block level container element with hyperlinks nested inside. I have used the HTML5 'nav' element, but if you prefer you can subsitute this for a 'div'

        <nav class="AngledTabs">

            <a href="#">Tab1</a>

            <a href="#">Tab2</a>

            <a href="#">Tab3</a>

        </nav>

Rotating the Tabs

The W3C defined transformation property (which includes translation, rotation, scaling and skewing) is still a working draft, and so cannot be reliably implemented by all browsers. Some of the leading browsers have already implemented their interpretation of the feature, and we can access these implementations using the vendor specific properties:

        -webkit-transform: rotate(-55deg);
        -moz-transform: rotate(-55deg);

Webkit browsers include Chrome and Safari, and the mox prefix targets Mozilla firefox.

Positioning the Tabs

By default, the rotation origin is 50% 50%, or the centre of the element. To Make the maths simpler, we will choose to rotate about the bottom left corner of the tab. This will be the highest point we want visible on the tab, so moving the tabs down by the height of the container will leave this point resting on the bottom of the container.

        -webkit-transform-origin: top left;
        -moz-transform-origin: top left;
        margin-top: 175px;

Leaving us with:

The tabs at this point are still spaced out horizontally by the width of the tab. We need to move them closer together by specifying a negative margin to one side. If we specify a negative left margin, this leaves the left most tab outside the container, so we need to bring it back inside by using the same left padding on the container. Finally, we need to hide the bottom of the tabs:

        
        padding-left: 80px;
        overflow: hidden;

Using selectors to target browsers

Adding the various margins and paddings above makes the tabs render horribly in browsers that don't support rotation. Therefore we need to make sure that they are only being applied in browsers with HTML5/CSS3 support. There are several methods of doing this, however I have opted for using the nth-of-type selector:

        body:nth-of-type(1) .AngledTabs { ... }
        body:nth-of-type(1) .AngledTabs a { ... }

Alternatively you could use targeted stylesheets (e.g. an IE only stylesheet which overrides the margins). I prefer the selectors method as it keeps everything together, avoids using the !important declaration to override properties and should distinguish between any HTML5/ non-HTML5 browser. The potential pitfall is that a browser could implement the nth-of-type selector before rotation. 

Styling

At this point it is up to you how you style your tabs to fit in with your website. The other properties I have set that you should be aware of and probably want to keep are:

        height: 45px;
        line-height: 45px; /* Keep line-height equal to height to keep the text centered vertically */
        padding-left: 30px; /* Keep the text from dissapearing beneath the overflow at the bottom of the tab)*/

 

Download the full code- Angled Tabs.zip (2.65 kb)

Tags: , , , ,

Web Development

Chrome 16 update causing duplicate headers error

by Jack Bradford 28. December 2011 18:27

Update 7th Jan 2012: My original post assumed that the AddHeader() Method appended a second header to the response which caused the error- I've since realised that this is not the case, and it appears that ASP.NET (or more likely IIS) is clever enough to realise that there should not be multiple content-disposition headers and instead overwrites the generated header. The error in most cases is caused by a comma in place of a semi colon.

As a web developer I've always been a big fan of the auto updating features found in Chrome. But today I witnessed first hand the problems that auto updating can bring when a browser implements new security features.

Last week I began receiving odd error reports for a clients internal system for a feature that had been working for months and I hadn't made any changes to. When they tried to download resources from the database, they received the following error message:

Duplicate headers received from server

The response from the server contained duplicate headers. This problem is generally the result of a misconfigured website or proxy. Only the website or proxy administrator can fix this issue.

Error 349 (net::ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION): Multiple Content-Disposition headers received. This is disallowed to protect against HTTP response-splitting attacks.

If you receive this error on someone elses website, contact the webmaster to make them aware of the problem. You can work around the issue by using another browser- I would recommend the latest version of Firefox.

It wasn't possible to examine the headers using the Chrome Developer Tools, but thankfully the error message was descriptive enough. On inspection of my code, I found the following line to be causing the problem:

Viewing the headers using Firefox's web developer tools showed that my original assumption of the header being defined twice was incorrect. Having read the W3C spec, I realised the error was not in how ASp.NET adds the header, but rather in how I had defined it using a comma instead of a semi colon. The problem line:

context.Response.AddHeader("Content-Disposition", "attachment, filename=""" + resource.FileName + """")

Clearly this just appends the new header to the response without removing or overwriting the one generated by ASP.NET. The fix seemed easy enough, I either needed to remove or edit the existing header.

The correct fix simply involves replacing the comma after 'attachment' with a semi colon, thereby making it a single header definition.

context.Response.AddHeader("Content-Disposition", "attachment; filename=""" + resource.FileName + """")

This is not a bug in Chrome, but rather a change of functionality where the parsing of headers is stricter. 

The W3C spec allows multiple headers, but only in circumstances where they could be combined into a single header with a comma separated value value list.

Multiple message-header fields with the same field-name MAY be present in a message if and only if the entire field-value for that header field is defined as a comma-separated list [i.e., #(values)]. It MUST be possible to combine the multiple header fields into one "field-name: field-value" pair, without changing the semantics of the message, by appending each subsequent field-value to the first, each separated by a comma

Clearly with content-type this is not valid, a file can only have one content type.

On closer inspection of the spec, the Content-Disposition header is not in fact an official part of the W3C spec, but is simply documented because of its widespread use. Still, the format of headers and the use of commas to denote multiple values is standard, and this also affects other headers such as content-length.

Tags: , , , ,

ASP.NET | Web Development

About this Blog

This blog has been added as a place for discussion on all aspects of web development, SEO and other services we offer.

Copyright © 2012 Altitude Solutions Ltd