Notes from my BD Conf Workshop

Avatar of Chris Coyier
Chris Coyier on

Just a few days ago I gave a four hour workshop at BD Conf in Dallas, Texas. I thought I’d round up the notes from it to give to the attendees. And I also thought it might be useful to post publicly so everyone could benefit. Some of the stuff might not make much sense if you weren’t there, but hey, that’s the huge advantage of going to these events!

We started out with a completely empty folder. No framework, no starter code, just totally from scratch. We made a simple structure inside the folder: index.html and folders for css, js, and images.

We added this project folder to CodeKit and demonstrated that when you change content in the HTML, the browser will automatically refresh to show that change. This is CodeKit doing that, and doesn’t require anything else special. The browser in our case was regular ol’ Chrome (works in Safari too) and the text editor was Sublime Text 2 (could be any text editor).

We plopped down some texture from Subtle Patterns.

When we edited CSS, we watched the style changes “inject” themselves without a page refresh. We talked about how in a stated application this is particularly useful. Imagine a web app where it takes a few clicks to get it into a particular state (open dialog box, open dropdown menu). A refresh would close those things, but with style injection you can style them without that worry.

Right away we had our project use Sass. In our case the .scss variety of Sass, which looks pretty much like regular CSS with the curly braces and all. We made a “scss” folder in addition to the “css” folder, and CodeKit knew to compile our “style.scss” into “style.css” when we saved the file. Style injection still works.

We started building a grid for the project. Even something like a layout that has a sidebar is essentially a grid. Instead of using a fancy framework, we don’t overthink it and create our own.

Right away we broke off grid stuff into a file we called _grid.scss in our scss folder. That’s a naming convention signifying that this file will be included in other files and is not to be compiled directly.

Our grid “framework” is as simple as floating elements to the left in percentage proportions. For instance 66.66% wide next to 33.33% wide. Or four 25% wide elements. These we set by classnames like grid-2-3 or grid-1-4.

We used the clearfix class so the grid didn’t collapse to zero height.

Gutters were handled by adding left padding to the grid itself and then right padding to each of the columns. Initially, this broke the grid, until we added box-sizing border-box universally. That meant that the padding would come out of our set width rather than add to it, immediately fixing the problem.

With columns in place, we made our content set into modules. Modules were styled from another new stylesheet we create called _modules.scss imported into the global stylesheet. The trend was to break grouped styling into separate stylesheets just to keep organized. Sublime Text 2’s “Command-T” feature makes it really easy to jump to those files when you know you need to.

When we added the border-box stuff, we only used the non vendor prefixed version, but in reality, we need to use a few vendor prefixes to get the best browser support possible. Whenever we think vendor prefixes, we think “we should make a @mixin!” and whenever we think that, we think “and by that I mean use Compass!”

We add Compass to the project through CodeKit, specifying the folder names which we have set up. Nothing really changes, it’s just now we can @import "compass/css3"; in the global stylesheet and use all the Compass CSS3 @mixins. In our case, we used @include box-sizing(border-box);

Switching gears, we add a logo to the site. It’s a simple one-color logo, so we decide that SVG is the way to go. Because: 1) SVG file will be super small 2) it will be very crisp at any screen size 3) browser support is pretty good but not perfect.

Using SVG is very very easy. You use it just like you would a .jpg or .png: <img src="logo.svg" alt="logo"> or background: url(logo.svg);

You can save an SVG right out of Adobe Illustrator. Just like you would save the file as .ai you can save it as .svg.

There are a couple of browsers that don’t support SVG. We check out for support levels. It’s green across the board for current browsers, but IE 8 and down don’t support it. We also open up BrowserStack and bring up the site in an emulator of a Samsung Galaxy Tab 8.9 running Android and the SVG doesn’t work there.

We were able to open up our local site on BrowserStack because we made a real local domain for it through MAMP and then using their local tunnel feature.

We decide that we want to support these older browsers, so we make a .png version of the logo. Then we needed to test the support of SVG in any given browser, so we built a custom build of Modernizr that would run that text. Now we can just do if (Modernizr.svg) { } else { } to handle support or non-support situations.

We insert jQuery onto the page quickly by snagging the script tag through ScriptSrc.

For our non-support SVG situation, we just target the logo with jQuery and use the .css() method to change the background-image to point to the .png file instead of .svg. We test it in BrowserStack and it works great.

Switching gears again, we add some media to our main content area in the grid layout. We add a YouTube video in there and a Flickr photo, both using the copy and paste code that those services provide (as is likely a content creator would do). Both of them have immediate problems in our fluid with layout (yep, our layout is entirely fluid, we’ve only used percentages so far. Remember the web is always fluid until you specifically break that feature by setting non-percentage widths).

To make the media fluid, we essentially set the max-width to 100% and override any set height with auto. This works well for the image, but not for the video. YouTube videos come in iframes which don’t have a sense of aspect ratio like images do. We write some extra markup and CSS to handle this situation essentially following the intrinsic ratios for video model.

That concept is cool and all, but the extra markup required makes it impractical for most sites (including my own) so we implement FitVids.js on the site. All FitVids does is automate the CSS method we just learned about. FitVids requires jQuery to work, but we already had that in place because of the SVG swapping stuff we did.

We started running into the issue of too many scripts being loaded. We talked about how performance should be a part of workflow. Reducing number of resources loaded is a big part of performance, so we take some steps to minify and concatenate scripts. We’re already essentially doing this with CSS through @import. We do it with JavaScript through CodeKit’s ability to append/prepend scripts to each other while minifying.

Switching gears, we build out some navigation for the site. A row of links that works great on wide screens but starts to break into multiple lines and get clumsy on small screens. We look at a bit at some off-screen nav patterns and decide that’s the way to go. Ours will be simple though. Simply click a link to reveal the menu and the entire screen fills with navigation. Click another link to hide it.

We decide to go with a “stated” CSS approach. We’ll use jQuery to watch for the clicks on our Hide/Show Menu button, but all it will do is toggle a class name on the body element. That class name will control the visual state the page is in. With the class name present and the screen at a narrow width (determined through a @media query), the navigation menu gets the full screen treatment.

We mess around with some accessible hiding techniques in which we move the elements off screen rather than use display: none; It became a little tricky to get them to show up again, but ultimately employed position: static; which means that the top/left values became meaningless.

Switching gears, we start working on the idea of conditional loading. Changing layout for different screen sizes is part of responsive design, but so is sometimes having different content that is more appropriate for the situation. We take the example of Google Maps. On a small screen, not only don’t we want the slowness of overhead of an embedded interactive iframe, but that experience is also worse than that native experience that most mobile phones have (e.g. a real maps app or

The plan is to go “mobile first” by embedding a static image of a map that links out to, then on large screens swap that out for the iframe. We use the library Enquire.js to listen for when certain media queries match and fire off callback functions. In those callback functions, we $.load (jQuery Ajax) the appropriate content.

That’s pretty much were we left off. We finished with some random stuff like loops in Sass and things Compass can do beyond the simple things we did in our project.

If you were at the workshop, I’ll email you a cleaned up final version of the project.