Progressive Enhancement Part 3, Layout

As with our previous sections follow along with our new tempate.txt and see the final result of this exercise as Template.html

Markup Changes

At this point we can finalize the full HTML structure by adding the proper doctype, <head>, and other related elements. In addition we can think about our layout's needs and add the DIV and SPAN needed to make that happen.

Despite my distaste for it as a specification, I went with a HTML 5 doctype since the simpler/smaller header is in fact a good thing. I condense the doctype, html opening, head opening and charset meta to a single line as really nothing should ever go between those for other tags, and the charset should be declared before any other content type elements. I do the same thing with the closure of head and opening of body, and the closing of body and html. It acts as a simple reminder that you don't paste any other tags between those!

The viewport meta exists to tell mobile browsers we know what we are doing, and to not try and override our scaling. Mobile browsers without this will flat out lie about their resolution, and start out with a different font scale. In landscape mode some Android devices will report their height as width, which is why we target that as well.

Some folks will try to set other values here that disable zooming -- if there was EVER a giant middle finger to users on the part of developers, that's it right there. As of the time of this being written (late 2015) there is NO reason to declare any values in the viewport meta other than what I declared here!

The stylesheet link includes media targets since our screen layout is'nae likely to make a lot of sense for print and aural devices. If you see link tags pointing at stylesheets without a media target, or worse using media="all" the developer clearly has no malfing clue what they are doing.

Recently HTML 5 validation has been throwing warnings about including "projection" and "tv" targets as they are deprecating those. I say ignore that warning as there are still PLENTY of devices in circulation like Kiosks, projectors and consoles that will try to use them instead of screen.

Getting into the body of our document, I've gone with double-wrappers around things so we can have full-width backgrounds with constrained widths. It is inefficient to try and apply the width restrictions to our semantic tags, so we use DIV.

DIV and SPAN are semantically neutral, used as we have here they make ZERO changes to the meaning of our previous step -- that's why we use them! They indicate something is goin to recieve style, WITHOUT saying exactly what that style is. This is part of the whole "separation of presentation from content" and why your classes and ID's should strive to say what things are, NOT what they look like just as our tags do. This is why many frameworks with their cryptic presentational classes completely miss the point!

The first wrapper, #top is so named for convenience should we at some point want to add a <a href="#top">Back to top</a> link at the bottom. It's a good consistent name for either the outermost wrapping element or the first of many.

The span with the hyphen inside the H1 will allow us to remove that span or repurpose that section for other styling. The hypen appears between our title and tagline CSS of, and we can do whatever we want to it CSS on. We don't need extra classes on any of the H1 elements since again as the heading that everything is a subsection of it makes little if any sense to have more than one H1 on a page. No matter what the halfwits that came up with HTML 5's new rules say!

All the widthWrapper classes exist to set our max-width and centering for the elastic and semi-fluid layouts. I reduced the social media and news to a single DIV#callToActionBar with one nested DIV. The outer id provides all the hooks we need to style the inner content.

To create a multi-column adjustable layout we need two sets of wrappers -- the outer pair wraps all the columns and provides that width. The inner #contentWrapper and #content allow us to space the content to allow columns next to it whilst keeping that content first in the source order. All our sidebar stuff is "extra" that is less important, which is why it belongs further down the page in our source.

Each of our page's subsections get a DIV.subSection on it for the application of style. Some would argue this is where HTML 5's section tag should be used, but that provides redundant meaning to our numbered headings. Again, we use DIV BECAUSE they actually mean nothing!

As I just said, the "extra" stuff goes further in the source, so I call it #extras. Inside it I divide it into two further sub-div as .firstSection and .secondSection. Having the outer #extras DIV and the two sub-div will allow us in our CSS to create a three column layout first-content-second, a two column layout with content-extra (first over second), two columns below one wide content column, or a single column all from ONE codebase.

We close out all those DIV, put a DIV around our footer, and we're done. Notice that for the most part our semantic markup from the previous step remained unchanged, we just added hooks to apply style.

Now, before we move on to the CSS, let's quickly cover the use of comments. As I used clear concise names on the elements instead of cryptic/vague ones, the need for opening comments is removed. Since </div> means something is being ended, there's no reason for the closing comment to say end, just say WHAT's being closed. I use number signs and periods just as per CSS on that. I put the closing comments before the actual tag closure so as to avoid a rare but annoying bug in IE and some early builds of Firefox where comments can actually trip rendering bugs if placed between sibling-level elements. If the closure is inside it, you dodge that particular headache entirely!

CSS, lets make that layout work

Be sure to follow along with the actual CSS file for this stage: screen.css

Notice I call it "screen.css" -- not some useless vague "style.css" or "main.css", but a word that implies it's media target. WELL WRITTEN sites should only have ONE css file when deployed per media type -- another reason "frameworks" are a bunch of idiotic nonsense.

When I build my first screen layout I like to start with the lowest common denominator. A LOT of people think that's mobile because "ooh, tiny!" -- but we can target small screen devices with media queries; or at least any that we actually care about. The big concern is devices that LACK media queries, which is why my initial layout is typically a mid-screen size friendly non-media query layout. I make it semi-fluid for IE7/newer, and shove a fixed width at IE6/earlier. (you'll see a comment about the last of those in the code).

I always start out with a reset. Resets exist because the HTML specification does NOT say what the default appearance of any tag should be, NOR SHOULD IT. The ENTIRE reason HTML exists is to say what things are, or would be in a professionally written document, so that the user-agent (all browsers are user-agents, but not all user-agents are browsers) can best determine how to show that content! Like anything else where it's not explicitly said in the spec, the browser makers went and each did their own thing in terms of margins, paddings and borders. A reset adjusts for that without having to say it each and every blasted time you want to use an element.

There are smaller resets like the so called 'universal' one of "* { margin:0; padding:0; }" but that can wreak havoc with the sizes of form elements between IE, FF and "everyone else". There are larger resets like Eric Meyers "reset reloaded", but that fat bloated mess borders on being a framework unto itself. It wastes time changing values that don't need to be rest, initializes values you are highly likely to change anyways, and is just too blasted big. Most of the time you encounter people saying "don't use resets" it's because all they can think of is massive bloated ones like that.

The one I use was developed by Dan Schulz shortly before he passed away, and at a quarter K isn't so big that it has any meaningful impact on load time. It resets JUST what's inconsistent across browser engines and removes most all the headaches common to styling a page. It's a nice safe middle-ground.

Once past the reset we can get into our actual elements. I'm going to present each of the major sections of this under headings for ease of looking up the how/what/why.

HR

I hide all the HR since they are there for semantics and "non-screen user agents", NOT for "drawing a line across the screen". With our screen media layout we'll have plenty of other ways to convey that meaning.

-text-size-adjust

A handful of older mobile browsers with small displays will STILL try to screw with the default font size ignoring the viewport META. Thankfully it's only small display units that take vendor prefixes, so we just hit the two that need it. Sadly if you send it to desktop Safari, the -webkit-text-size-adjust will break zooming (see my ranting and raving up above) so I put them in a media query. It's VERY unlikely that desktop safari would ever be on a 480px wide display.

html, body

I set the width AND height of these to 100%... Height is so that we can use BODY as a flexbox container for the min-height/sticky footer. The Width deals with that IE10 and 11 can be a real jackass about flex, shrinking BODY to the max-width of the .widthWrapper DIV for christmas only knows what reason. (Oh wait, it's IE, like it needs a reason to do something stupid!)

Remember that you cannot set percentage height on an element where it's parent doesn't have a height; it will be ignored. The only exception being the top-most element which is USUALLY HTML (some old browsers use body). This is why we have to send this to both BODY and HTML, so that in 'normal' browsers BODY can get it from HTML, and in crappy browsers BODY just works.

body

First I set it up as my flexbox container. Flex allows our content to stretch to fill the parent. If we set up .columnWrapper as the element allowed to stretch, the footer will be pushed to the bottom. I set min-width on body so the whole layout is nabbed in one fell swoop. I like to set the font used across most of the document on body. Experience has taught me that for MOST (but not all) sans fonts 85% is the ideal size.

If you change the fonts-size, you should ALWAYS change the line-height. You CANNOT trust it to inherit properly, particularly if declaring % or EM font sizes, MORE so once you start testing on systems with that different default font size. There is a LIE being perpetrated/parroted/defended on another forums with "point" in it's name that if you omit the metric and just say "line-height:1.5;" that it will inherit properly -- don't believe it. Fails miserably across multiple browser and default font size combinations.

... and since by the time you say "font-size:85%; line-height:150%;" you're within spitting distance of using the entire condesnsed font declaration, I just go ahead and use the full condensed declaration EVERY time I change the font-size. (with one minor corner-case IE hack exception that won't come up in this example)

For flow text I find that taller line-heights aid in legibility. The 110-130% that HTML suggests is fine for "times new roman" at 16px if you need to cram a bunch of text into a small display, but it isn't the best. There's a reason back when people had to use things called "typewriters" to write papers for school the teacher told us to double-space, and it wasn't JUST to have room for them to cram comments in between lines. (though that is a handy side-effect, particularly when editing). Really you have to base this on the font being used; just look at this picture I made years ago:

Font Face Comparison

All the fonts are declared in the same size of 1EM / 100%... top is at 96dpi/16px default, bottom is at 120dpi/20px default. "same size" my backside. Arial is significantly larger at the same declared "size" than TNR, "DejaVu Serif" and "courier new" are outright honking HUGE. Something people designing the front end need to learn and test for.

I set the #EEE background color so that I can make the content areas white and see them. This is more of a layout aid than planned style. Again don't fret about pretty colours and backgrounds at this point, make the layout work FIRST... that way you can design your graphics to the layout instead of the other way around.

#top, #callToActionBar, #footer

Technically these elements should default to this flex-shrink behavior, but IE is once again painfully stupid. You omit this, and the footer won't go to the bottom of the page if the content is too short to push it there.

.widthWrapper

First I set up float and margin wrapping behavior since we'll want to contain such things as much as possible. The max-width prevents long lines of flow text from getting hard to read, the padding makes it 'pretty' when smaller than the max-width so some background shows through, and the auto-margin centers it.

Whenever possible I use EM for my margins, paddings, etc. Based on the size of the font multiple of it most always look good regardless of the actual font-size. This takes a BIT of work to deal with as if you scale the font, you need to scale your values. Theoretically you could use REM instead of EM, but browser support for that is a bit wonky.

* html .widthWrapper

See the comment. This is for legacy IE, you could probably remove it if you wanted and tell IE6/earlier users to go plow themselves; but it's so tiny and simple there's no harm in at least TRYING to make the page useful for grandma on her Win98 box even if it doesn't get all the bells and whistles. Again, graceful degradation -- it doesn't have to work perfect, it just has to be usable.

Really once you take the attitude, "is it usable" instead of "does it perfectly match in every old browser like it does the modern ones" life becomes SO much easier. Simple fact is a lot of the artsy "designer" types who put form ahead of function will scream and cry like a five year old that you can't make their not even feasible to be on a website garbage work the same in IE6 or 7 as it does in bleeding edge Chrome. You know what? Tell 'em where to stick it!

h1

Floated so the menu can go next to it, nice big font size. The uneven padding is there to deal with that many sans-serif fonts do NOT put the distance between caps-line and base-line in the proper spots -- some don't even make their caps reach the declared caps-line. (which is just herpafreakingderp). Worse there's also a bit of optical illusion with the small text below the big text that has to be accounted for. I also made it all caps.

h1 small

h1 small span

Get rid of the hyphen, we don't need it for screen layout.

#mainMenu

kill the bullets, float it ot the opposite side, align the text to that side since we'll be using inline and inline-block inside it (otherwise there would be a extra "space width" gap on the right), and pad the top to push it even with the heading. I set a max-width to force it to two rows of three columns.

#mainMenu li

It's FAR easier to just set these to inline than it is to play with float or that legacy IE can't make block-level tags display as inline-block. This avoids al sorts of bugs like IE8's "staircase effect" and on the whole just makes life simpler. WHEN POSSIBLE on a menu, style the anchors, NOT the LI.

#mainMenu a

inline-block makes it so top and bottom padding is obeyed on these. I fix the width to make them look nice but do so elastic, so as to fit the differnet font size if any. A "space width" is typically 0.3 to 0.4em depending on the font, and we end up with a space between inline and inline-block siblings. The 0.2em margin ends up making roughly 0.5em so the space between these elements to the left and below looks mostly the same without playing any "games" to try and remove that whitespace behavior. I only really coloured these so we can clearly see them in the layout.

#callToActionBar

top and bottom padding, background so we can see it.

#callToactionBar div div

float the social media part, and margin it so that it won't run flat against the "news" text. YAWN.

h2

at 125% font enlargement 0.8em == 1 REM. Using sizes like 125%, 150% and 200% make the EM math so simple you don't really 'need' to resort to REM. (Which WILL someday be handy, but we're not there yet)

p

rather than try and use margins I pad the bottom. Means no margin collapse headaches and is just 'simpler' to work with. You want space above it, pad the element before it.

.columnWrapper

I clear just to be sure since #top and #callToActionBar have floats -- the .widthWrappers inside them SHOULD be float containing, but IE can still drop the ball on that once flex is in the mix. Setting flex to "1 0 auto" means that "1" this element should grow to fit as much space as possible, "0" it should NOT shrink to fit the screen forcing a scrollbar, and "auto" it should be dynamic instead of a relational or fixed height. By making this element grow, the footer will be at the bottom of the screen if the content is too short to push it there, or off the bottom of the screen if the content is tall enough to force scrolling.

.contentWrapper

The magic column layout begins. If we float this left but force the width to 100%, there is 0px free on the left for a float to fit into. REMEMBER THIS for when we get to #extras below!

#content

The padding is there to push the content subsections away from the sidebar and stuff above it. The margin is set to the width of our sidebar #extra to make room for it to be displayed OVER. We could just say margin-right:19em and lose the side padding, but I find it easier to not have to do the math separate. It's also handy to keep them separate should you find yourself having to mix metrics like pixels and EM's at the same time.

#extras, #extras.firstSection, #extras.sectionSection

I make these relative positioned as throughout the different screen layoutS we want them to depth sort over .contentWrapper and #content, and we may end up sliding them around as well.

#extras

Floated left I set the width to 18em and a negative margin equal to that width. Negative margins are fascinating in that they change the size of the container in "flow"

aka how big other elements THINK it is, but does not change the size at which it "renders", aka how it's drawn. By using a negative left margin equal to it's width it becomes 0px wide in 'flow', letting it fit into that zero-width gap next to .contentWrapper! Boom, the whole section rides up into that gap rendering OVER that side margin on #content.

Using this technique we could do three column, four column, no column layouts.

It DOES mean we need to declare a fixed or elastic width instead of a percentage one, but honestly trying to do things like "25% columns" on a website sidebar is most always a disaster that breaks somewhere. It's far easier and reliable to use an elastic sidebar with a fully fluid content column. Generally speaking when you see people trying to use things like "width:25%" they don't know what they are doing, and broken layouts are usually the result!

.contentBox

padding, bottom margin to space them apart, background so we can see them; nothing to write home about.

#recentBlogEntries .subSection

Pad them, add a border at the top to divide them. Simple.

#recentBlogEntries h3

I like to make the screen target version put the date on the right, and the text on the left with a gap between them, with the text able to flow below the date should wrapping kick in. That just means float the span with the time in it, so we need to add float wrapping behavior. Bigger font, pad the bottom, pretty simple.

#recentBlogEntries h3 span

Float it right, pad it so the time won't sit flush against the title. Simple.

#recentBlogEntries h3 span span

kill the hyphen, we don't need it for screen media.

#featuredArticles ul

kill bullets, yawn.

#featuredArticles li

pad them apart. 1EM felt like too much, 0.5 like too little. 0.75 was just right.

#featuredArticles a

Setting this to block increases the target area that hover and clicking can hit. Ever notice how sometimes anchors only work if you are over the rendered text or a specific line, but not the whole element? This fixes that. I also kill off the underscores.

#featuredArticles a strong

force these to their own line for our screen layout.

#advertisement h2

since this is NOT real content of the page I don't like making it look like a major heading, so I drop it in size to normal text, make it italic, and grey it out slightly.

#advertisement i

our dummy advert box. 160x600 is a fairly common "skyscraper" size. Background-color so we can see it.

#footer

padding, alignment, YAWN.


... and that gives us a two column intermediate desktop layout that should work all the way back to IE 6. (and with two or three extra lines could be made to work all the way back to IE 5.x if desired). NO significant extra effort.

It's semi-fluid and elastic, leaving just one more need: RESPONSIVE.

Media Queries and Responsive Layout

Responsive simply means using media queries to change out things in the layout to make it fit different displays. It's not "hard", it's not rocket science, and it sure as shine-ola doesn't need some idiotic massive framework much less arbitrary "grid" asshattery to pull it off!

In keeping with our theme of working "from the inside out" I'm going to make a query that on large displays turns our two column layout into three... then have a query that turns our two columns into one column at the top with to columns below it, and then finally at the smallest size go to a single column.

These media query widths were determined by resizing the window and figuring out what worked according to the needs of the CONTENT, as opposed to trying to shoe-horn things into some arbitrary grid nonsense.

@media (min-width:64em)

If the display is bigger than 64em wide, up the maximum width to make more room, then pad/margin the opposite side of #content to make room for another column on that side. We strip the float/column behavior off #extras and instead add that behavior to .firstSection and .secondSection.

.firstSection gets margin-right which pushes it right, then slid left 100% putting it on that side of #content. .secondSection just gets the same left negative margin behavior as we had on #extras as our two column design.

REALLY simple.

@media (max-width:46em)

If the display is smaller than this size, we first let the body go down to 192px as the minumum. That min-width on BODY was for non-media query capable browsers, since we KNOW we can run media queries at this point, we can remove that limitation.

The content area has it's margins and side padding stripped off removing the sidebar space. Likewise we strip the column behaivor off #extras, but pad it's right side to make room for .secondSection to be a sidebar.

Floating .firstSection at 100% width allows .firstSection to be fluid width, whilst we can put that same negative margin float behavior onto .secondSection to make it a narrow elastic column on the right.

@media (max-width:40em)

At this point the menu alongside the h1 breaks, so we want to strip the float behaviors off these and just center them. Sicne displays this small are pretty much guaranteed to be touch devices I enlarge the menu anchor sizes to make them "finger-sized" (something google actually checks for now!). I also up the max-width to a ridiculous amount on #mainMenu so they can display as a single line. Likewise the float behavior gets removed from #callToActionBar and we kill the padding on #content and #extras. In all side paddings are removed or reduced to make better use of the rapidly dwindling available screen space, and once again we strip off ALL columnar behaviors from #extras. I add a bottom border to the .contentBox so we can clearly see divisions between them, then pull the top border (if any) off #footer so there's no conflict there.

@media (max-width:34em)

Way down here at this tiny size I put the max-width back on #mainMenu to force it to two even rows as having just the last one or two menu items below four or five items just looked like ass. I also kill the line-break in the footer since how it was wrapping wasn't entire attractive either.

@media (max-width:20em)

Our final query just adjust the size of the H1 text down smaller so that it actually fits the screen.


... and that's the layout step.

Projects

  • elementals.js
    A lightweight JavaScript library focusing on cross browser support, ECMAScript polyfills, and DOM manipulation.
  • eFlipper.js
    An image carousel script using elementals.js
  • eProgress.js
    A JavaScript controllable progress bar using elementals.js. Based on the nProgress project that relies on the much heavier jQuery library.

/for_others

Browse code samples of people I've helped on various forums. These code snippets, images, and full rewrites of websites date back a decade or more, and are organized by the forum username of who I was helping. You'll find all sorts of oddball bits and pieces in here. You find any of it useful, go ahead, pick up the ball, and run with it.