First off, don’t panic! You might have already scanned the article and noticed no headings mentioning either geolocation or any APIs. Yes, it is true that there isn’t anything about geolocation in this part of the article, but that’s only because I wanted to ease you into it. Well, OK, that isn’t true. Here’s the truth: this article is envisioned as a continuation of my last post – Build a HTML5/CSS3 Website Layout Without Images – Part 1 on Onextrapixel where we discussed some of HTML5’s new elements and some of the properties introduced with CSS3.
Starting with the demo from my previous article, I wanted to see what changes I could make to introduce more HTML5 elements and attributes and to also show off some more CSS3 goodness. There have also been some changes to the existing CSS to make sure we use the features now supported by Opera 11.10, Internet Explorer 9 and Firefox 4 (er, Firefox 5).
[tut demo=”https://onextrapixel.com/examples/geolocation-js-api/” download=”https://onextrapixel.com/examples/geolocation-js-api/geolocation-js-api.zip”]
Part 1
So, in part 1, we will discuss HTML and CSS and the idea for part 2 is to locate the visitors of our demo page using the geolocation API and then use PHP to calculate the sunrise and sunset times based on the users latitude and longitude. If the current time happens to be before sunrise or after sunset, we add a new style sheet which will darken the layout’s colors.
That’s probably too much for an intro, so here’s the dark layout that we will automatically switch to in case it’s nighttime at the visitor’s location:
The Content of Our Demo Folder
This time, we have a few extra files needed to make everything work. Alongside the usual index page and the style sheet, we have one more style sheet (I’ll pretend that the style sheet for Internet Explorer isn’t there) that changes the colors of the layout if we determine that it is after dark. There is also the calc.php
file where we will determine if it is past sunset and before sunrise. Of the two folders, the scripts
folder is new and it contains the JavaScript file which holds our small script.
HTML – What Has Changed
Actually, this will be a rather short section as not much has changed in the markup – most of the changes were made to the CSS.
The Viewport Meta Tag
Starting from the top, we have one new meta tag which helps a lot when you need to control how your site/web app behaves in a mobile or a tablet browser. As our page now has a fluid layout which adapts to different resolutions, including the low ones on smartphones, pixel not being a pixel becomes a huge problem. This is where the viewport
meta tag comes into play: it gives us a couple of properties which can “restrain” the scaling which mobile devices perform, e.g., when you change their orientation.
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0" />
The first property, width
, lets the browser know the width to which it should render the page. By setting it to device-width
, we make sure that the width of our layout equals the width of the viewport.
The following three properties: initial-scale
, minimum-scale
and maximum-scale
lock the scaling of our layout to the value of 1
. In other words, we prevent the scaling of the layout on orientation changes (and if a visitor tries zooming by pinching). You can view it as making sure the layout adapts to the width of the device just like it does when we change the width of the browser window on desktop browsers as opposed to it scaling like we were zooming in or out of the page. By setting all these properties, our fluid layout can adapt to the width of the device, be it a smartphone or a tablet.
The Time Element
Another change from the original demo is reflected in the way the dates of the posts are coded in HTML (as well as the way they are presented). This time we make use of the HTML5 time
element.
The time element represents either a time on a 24 hour clock, or a precise date in the proleptic Gregorian calendar, optionally with a time and a time-zone offset.
I didn’t get to mark up the dates with the time
element in the original demo because of all the nested elements which I used to style that section. This time, the date section has a simpler style and I was able to use the HTML5 element.
The time
element is another asset in adding more semantic meaning to your pages. Here, we use it to specify the publishing dates of our posts.
<time datetime="2011-04-16" pubdate>16 apr</time>
Between the time
tags, we place the date we want the visitors to see: “16 apr”. Within the opening time
tag, we have two attributes: the first one is datetime
and it lets us specify the actual date in a standard format. Check out the HTML5 specification for a list of valid date & time formats. The second attribute, pubdate
, is a Boolean attribute and it basically indicates that that’s the publishing date of the content in its ancestor article
element; if it isn’t nested in an article
element, then it signifies the publishing date of the entire document. Many of you are probably already rubbing your hands together knowing that you can use WordPress’ template tags to echo out this information for your and your client’s blogs.
Further (Minor) Markup Changes
Other than adding/removing some class
and id
attributes to certain elements, there aren’t many changes in the code since the original demo. One change worth noting is wrapping the post tags nested in the footer
elements within the article
elements in unordered lists. (I actually can’t figure out why I haven’t done this in the original demo). You’ll probably notice that one post has repeating post tags – those are there to test wrapping at different resolutions. There is also the new div
element with the id
of wrapper
. I have used it to wrap the page’s content and define the width of the site.
Another notable change is removing Remy Sharp’s HTML5 shiv script which enabled older versions of Internet Explorer to apply styles to the new HTML5 elements. We are removing Remy’s script because we will be using the Modernizr script to detect browser support for geolocation & localStorage and Modernizr can enable IE to style the new elements so it would be redundant to include Remy’s shiv as well.
The final addition to the HTML code is a div
element with the id
attribute of modalOverlay
. This element holds the modal popup which will be presented to visitors if the script, about which we’ll talk in the second part of the article, calculates that it’s nighttime at the visitor’s location.
CSS – Making Our Layout Fluid & Responsive
Most of the changes in our CSS are reflected in the way we control our demo page’s layout. But, first, I have one new CSS transformation I wanted to show you.
Skew – A Distorted Perspective
Instead of the sliding animation from the original demo, we will rotate and skew the “Continue Reading” buttons when they are hovered.
Our button, rotated and skewed:
Here is our new :hover CSS rule:
.button:hover { border: none; -webkit-transform: rotate(-5deg) skew(-5deg,-5deg); -moz-transform: rotate(-5deg) skew(-5deg,-5deg); -ms-transform: rotate(-5deg) skew(-5deg,-5deg); -o-transform: rotate(-5deg) skew(-5deg,-5deg); transform: rotate(-5deg) skew(-5deg,-5deg); }
As you can see from the code, we can combine the rotate
and skew
transformation to keep the left and right edges of the button vertical. The syntax is the same for all browsers; we just add the appropriate browser vendor prefix. Here, we included the -ms-
prefix for Internet Explorer 9 which supports CSS transforms (but not the transition effects, those should come with IE10).
We first rotate the button by five degrees in the negative direction and that would look like this without skewing:
If we were only to apply the skew
transform, distorting the button by five degrees in the negative direction on both axes, we would get the following look on hover:
Our button with just the skewing applied:
You can see how combining the two transformations make the side edges vertical. It’s a simple effect but you can come up with your own by combining different transitions.
Moving from Pixels to Percentages – Laying Out the Flexible Grid
Since the main topic of this article is the geolocation JavaScript API and since support for it on smartphones is fairly decent (iOS, Android, Maemo and Opera Mobile all support it) and very good on tablets, I wanted to make our layout look good on those smaller screens as well (or, rather, I wanted to remove the horizontal swiping). The best approach to accomplish this was Ethan Marcotte’s Responsive Web Design. In his A List Apart article, Ethan suggests we should use a combination of flexible grids and CSS3 media queries to achieve a layout that is truly flexible and “device-agnostic”.
Given how well Ethan explained this concept, I won’t talk too much about it. In a nutshell, the approach has two major ‘phases’: the first is converting our fixed width layout of not-as-standard-as-they-used-to-be 960
pixels to a fluid layout which will adapt to the changes of the browser window’s width. The second ‘phase’ consists of using media queries to pull the layout into shape at certain resolutions – you will see that our fluid layout will need some further adjustments at very low resolutions and that’s where you’ll see how awesome media queries are.
I’ll try to keep my explanations short enough not to bore you too much, but also clear enough so that you understand what and why I did things. (Of course, should I fail, don’t hesitate to ask me to elaborate on something in the comments.)
So, this is our task: make the layout adapt to the width of the browser window. We will move from:
#wrapper { margin: 0 auto; width: 960px; }
to the following:
#wrapper { margin: 0 auto; width: 92%; min-width: 300px; max-width: 1180px; }
The margin: 0 auto;
rule should be very familiar to you – it has been used for quite some time to horizontally center our layouts. (Go ahead: inspect the #home
element here on the Onextrapixel site. Told you!) Next, we set the width of our layout to 92%
of the total width. The number ninety-two is the result of some experimentation but I’ve found that values around ninety percent generally work well to give the layout a decent amount of whitespace on either side.
I have mentioned that the second part in the process of making our layout responsive consists of making some further adjustments to ensure the layout doesn’t break at lower resolutions (or at very high resolutions), we have made that process a bit easier by placing some constraints on the layout’s width. By setting a minimum width of 300
pixels using the min-width
property, we make sure that the layout doesn’t fall below that value even if the browser window/viewport is narrower.
Exactly the opposite is achieved with the max-width
property: by limiting the width to 1180
pixels, we don’t have to worry about lines being too long to read comfortably and the sidebar getting ridiculously wide. Admittedly, this is taking the easy road as we could have spent a little more time later defining rules for the extremely low and high resolutions. On the other hand, the layout wasn’t originally planned to be responsive so I am happy with how flexible it turned out to be – plus, media queries aren’t the main topic of this article.
Our old layout was 960
pixels wide with the main area split into two sections: a section
containing the blog post snippets and an aside
holding the social media links and the blogroll. This section
which had the id
attribute with the value mainContent
was 630
pixels wide and had a 30
pixel right margin. Now, as we are using Ethan Marcotte’s responsive web design (or should that be capitalized?) approach, our goal is to convert those pixels to percentages which we will do by applying Ethan’s formula: target / context = result
.
Here is a quick explanation of the method (for a better and more detailed explanation, check out Ethan’s article): the context
in the above formula is the full width of our layout – 960
pixels, which we take to be 100
percent; the target
is the desired width – 630
pixels; finally, the result is the same desired width but expressed in percentages.
Most of you have keyboards with a multimedia key dedicated to launching the operating system’s calculator application so let’s use them. If we divide 630
by 960
, we get 0.65625
. I am sure that doesn’t look like a proper percentage value to you (or it looks way too low) and with good reason: we need to multiply it by 100
and get: 65.625
. The new width of the #mainContent section
element is 65.625%
.
We will get to the other widths in a second after I propose a formula that will get you to the percentage value immediately: (target / context) * 100[%] = result[%]
. I just incorporated the additional step of multiplying the initial result value with 100
to get to the percentage value. I just think it might do away with some confusion if it’s placed in the formula from the start.
After that diversion and blasphemous formula alteration, we move onto calculating that right margin for the section
element by placing the values into our new formula: (30 / 960) * 100
, which gives us the value of 3.125
. So, our #mainContent
gets the following CSS rule:
#mainContent { width: 65.625%; margin-right: 3.125%; […] }
We have the main
section settled (the containing element, at least); now to calculate the width of the sidebar. The original aside
element was 300
pixels wide, we plug that into the formula: (300 / 960) * 100
. And the new width for the aside
element is: 31.25%
.
The next section that needs a responsive treatment is the header
element nested in the article
elements.
The article
element with a slightly redesigned header
:
A quick recap: we determine the width expressed in percentages by dividing our target width with that of the context. The key word here is context – it is very important to note that the context changes as the parent elements of our targets change. Originally we had the full width of our layout as the context but that changes when we start to look at the header
element nested within the article
elements. The article
elements expand to the full width of their parent element – #mainContent
– and that is 630px
, but, having 20px
margins on either side, the width its ancestor elements can occupy is 590px
and that is our new context.
Now, since our layout wasn’t meant to be responsive and because I changed the date and the number of comments sections a little bit, the percentages resulting from our calculations won’t match the values in the style sheet of the demo. I got the actual values by tweaking the calculated values so they worked well with the content. The original value for the date section was 9.3220339 (= (55 / 590) * 100)
but I tweaked that to 11%
. The same goes for the div
element holding the number of comments: it got tweaked from 10.16949153
to 11%
. Finally the titles of the articles, the h1
tags, are 72%
wide and have 3%
margins on either side.
The same formula was applied for the website’s footer which has three sections, all 300px
wide and spaced out by 30px
margins. The new values for the element width and margins, respectably, are: 31.25%
& 3.125%
.
Before we move onto media queries, I wanted to give you an alternate way you can view this process: you can think of our old fixed layout as just one instance of the flexible layout where the full 100%
width equals 960px
, 65.625%
equals 630px
.
Media queries! – Bulletproofing the Layout
After applying a bunch of tweaks to our CSS, our layout now adapts to the changes in browser/device widths and it can go from 300px
to 1180px
. Pretty awesome, huh? It is, until you start playing around with the browser window and decrease its size to, say, about 700px
.
Notice all the wrapping? Not as awesome:
Above is our layout when the browser window is about 700
pixels wide. Making the browser window narrow causes more wrapping and it makes the lines way too short to be read comfortably. What’s that? “What can we do?” you ask? Well, employ CSS3 media queries, of course.
You can view media queries as if statements for CSS: if
the condition in the media query is satisfied, let the browser access the following CSS. The conditions we can check for are the orientation
of the device (portrait, landscape), width
, height
, resolution
and quite a few more. For the complete list, consult the W3C Media Queries Recommendation.
There are several ways we can use media queries:
Inline, in a media query block (the option we are going to use):
@media screen and (max-device-width: 840px) { #mainContent { width: 100%; margin-right: 0; } }
When we use the @import
rule in our CSS:
@import url(840px.css) screen and (max-device-width: 840px);
When we link a style sheet in the head section of our HTML documents:
<link rel="stylesheet" media="screen and (max-device-width: 840px)" href="840px.css" />
In each of the examples above, we are checking if our browser window or device isn’t wider than 840
pixels. If it isn’t, we let the browser see the CSS rules contained within (first example) or serve the style sheet to it (the other two examples). Media queries are equivalent to HTML conditional comments for Internet Explorer but they are work in modern browsers (IE9 included).
When working with media queries to specify different rules for various widths you’ll keep running into certain cut-off points and they will often match the common widths of many mobile & tablet devices (768px
for the iPad in portrait orientation, 480px
for the original iPhone in landscape orientation and 320px
for the original iPhone in portrait orientation) and, on the other end, values around 1140-1180px
for the widescreen desktop monitors and laptop screens. The media queries for the demo miss the 768px
mark and yours might as well. I don’t consider this to be an issue but I do believe that I could have made the rules work with just the 768px
rule (instead of specifying two: one for the 840px
mark and one for 620px
).
Let’s go over a few of the more important changes to the layout we make inside of the media query declarations.
Life, er: Layout width under 840 pixels
In our first media query, we make the biggest change to our page: we collapse it to a single column layout.
#mainContent { width: 100%; margin-right: 0; } aside { width: 100%; float: left; padding-bottom: 0; }
Both the main section and the sidebar are set to be 100%
wide and the margin between them is zeroed out. Next, we set the width of the sidebar and footer blocks to 48%
and add a 4%
margin between them.
aside nav, aside section { width: 48%; float: left; } aside section:first-child { margin-right: 4%; } footer section { max-width: 48%; margin-left: 4%; }
We have also hidden the latest tweet section from the sidebar and the recent comments from the footer:
#latestTweet, #recentComments { display: none; }
Please note that we don’t zero out the margin
for the first section in the footer
as that was already done when we originally wrote the rules for the footer
elements earlier in our style sheet and, thanks to the cascade, that rule is inherited.
Layout Width Under 620 pixels
Before I say anything else, allow me to mention another benefit of the CSS cascade: since our layout widths under 620px
also have a width under 840px
, all of the rules written in the previous media query are inherited here. Neat!
Now is the time to make our logo and tagline a little smaller as they become too big for this layout width:
hgroup h1 { font-size: 56px; line-height: 56px; } hgroup h2 { font-size: 13px; }
We also reduce horizontal padding for the main navigation to prevent wrapping:
#global ul li a { padding: 0 12px; }
And we let the date and the number of comments sections breathe a little more by making them slightly wider and the title a bit narrower:
article header h1 { width: 70%; margin: 0 2%; } time { width: 13%; } .comments { width: 13%; }
Layout Width Under 480 Pixels
This is our final stop and, again, we reduce the logo and tagline as well as the navigation items’ font-size and padding properties:
hgroup h1 { font-size: 46px; line-height: 40px; } hgroup h2 { font-size: 11px; } nav#global ul li a { font-size: 12px; text-transform: none; padding: 0 10px; }
We make the sidebar and footer single-column:
aside nav, aside section { width: 100%; float: left; margin: 0 0 20px; } footer section { width: 100%; max-width: 100%; margin-left: 0; float: none; }
And do some more maintenance on the article
headers:
article header { min-height: 38px; } time { width: 20%; } article header h1 { font-size: 18px; line-height: 22px; padding: 5px 0; width: 76%; margin: 0 2%; } .comments { display: none; }
We have hidden the comments section because the layout is quite narrow at this point and the post publishing dates are more important than the number of comments.
As I have already said, these aren’t all of the changes made to the CSS but that isn’t the main topic of this article.
[tut demo=”https://onextrapixel.com/examples/geolocation-js-api/” download=”https://onextrapixel.com/examples/geolocation-js-api/geolocation-js-api.zip”]
Last Words
Well, we have reached the end of part 1. Stay tuned and Part 2 will be published tommorow with the promised geolocation API being used. Follow us on Twitter or Subscribe to our RSS Feed to stay up to date for part 2. In the meantime, please share any comments and questions below.