Workshop Notes from InControl Hawaii

Avatar of Chris Coyier
Chris Coyier on

Last month I was in Honolulu, Hawaii for In Control. The first day I gave an all-day workshop on, essentially, building a responsive website from start to “finish.” It was the longest of its kind I’ve ever done. Like we’ve done before, I’ll post the notes here.

I tossed together a Photoshop file we could work from. It was a fictional used cars dealership named “Boxtown Cars”. You can download it.

What it lacks in beauty it makes up for in a slew of excuses to talk about modern web development topics.

I tossed the project in GitHub if you want to snag it from there. Or you can view a live demo. We didn’t get all the way finished as you can plainly see, but we got far enough to talk about a lot of stuff.


We used CodeKit big time. It allowed us to use Sass and Compass on the project, do style injection which is great for workflow, as well as minify and concatenate all our CSS and JavaScript files.


Using Compass means we get @mixins for all the important CSS3 stuff for free. For instance the “module” pattern that we used all over the place can have:

.module {

  /* Doesn't need a mixin */
  box-shadow: 0 0 10px rgba(black, 0.4);

  /* Our global number */
  padding: $padding;

  /* Compass! */
  @include background(
    linear-gradient(
      top,
      white,
      #e4e4e4
    )
  );

}

We created a local domain to work from with MAMP (video). This means we can do smart things like reference assets from the root (e.g. <img src="/images/logo.png">) which is just more understandable in my opinion. We also plan to do some Ajax, so we need to be on a “real” domain name for that to work. Also, we will be using TypeKit which requires us to put in a domain name to allow access to. None of that is possible working from a file URL (i.e. just opening an index.html file off the desktop).


Our project folder was created from scratch as just an empty folder on the desktop. We created index.php and folders for js, css, scss, images. we quickly fleshed out HTML structure in index.php using the html:5-TAB command in Emmet. We’re using PHP because 1) it’s easy to do include()‘s (which we didn’t quite get to but are super useful for little demo sites like this) and 2) we can make comments in the markup using PHP comments instead of HTML comments (no need for those to come across the internet tubes).


We load just one CSS file on the page, global.css. This file is created from global.scss, which @import‘s lots of different smaller parts. Things like normalize.css (link), components like icons.scss, typography.scss, and buttons.scss, and sections like header.scss and footer.scss.


The fonts are from TypeKit: Proxima Nova and Market Web. We used their default embed code, which ensures no flash of text through because it’s naturally a blocking script. But we do mention th unstyled at they have asynchronous loading methods which can be a bit safer.


One of our SCSS files we call _bits.scss (the underscore naming convention means “partial” or “to be included elsewhere”). This file has things like variables we intend to re-use and our own authored @mixins.

We don’t get too clever with our color variable names, sticking with $yellow, $blue, and $green, so we remember them.

There always seems to be a number that comes up all the time in a CSS layout. I call it $padding and use it all over the place to lend consistency.

This file also holds our @mixin for media queries, so we have one place to alter those if needed. Learn more about that.


We used a texture for the background from Subtle Patterns. The provide the textures in @2x for retina screens. To load that retina graphic conditionally, we used a retina media query. We added that to our custom breakpoint @mixin:

@mixin breakpoint($point) {

  @if $point == papa-bear {
    @media (min-width: 1600px) { @content; }
  }
  
  /* etc */

  @else if $point == retina {
    @media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
      @content;
    }
  }

}

The overall layout of the site needs fluid width columns that are equal height. There are plenty of ways to do this, but since we’re doing a workshop here and are showing off futuristic things, we go with flexbox. This kind of thing is very very easy in flexbox, just note the cross browser support for the latest syntax isn’t great.


The design is fluid width in that we never set any widths that aren’t percentages. Those squish down on small screens as we have properly set:

<meta name="viewport" content="width=device-width">

To stack the columns, we just remove the flexbox:

@include breakpoint(baby-bear) {
  .guts {
    display: block; // remove flexbox
  }
}

We have a “don’t overthink it”-style grid in place that we similarly fix by making all the floated columns 100% wide.


We needed a few icons for the design, so we picked out just a couple from IcoMoon and downloaded font files with just those icons in them. We included them on the page with accessible markup. Essentially:

<a href="#" class="star" data-icon="&#xe005;">
  <span class="visually-hidden">
    Star This Car
  </span>
</a>

The logo of the site is vector-y, so we use SVG. SVG is pretty darn fantastic: small, easy to compress further, scales well, and has fancy features like being able to embed CSS right in it. In our case we used it simply as a background-image. We used Modernizr to test for SVG support. Modernizr adds a class to the HTML element that indicates support. So we end up with:

.main-header {
  background: url(/images/logo.svg) no-repeat top left;
  background-size: contain;
  .no-svg & {
    background-image: url(/images/logo.png);
  }
}

The navigation was a bit unwieldily on small screens, so we hid it and exposed a “Show Menu” link (with a navicon). Clicking that link revealed the menu – which contained another new link to hide the menu. This was all done with just CSS – you can see an example here.


In the footer, we display a Google Map of the location of the dealership. On large screens we want to show an interactive map. On small screens, just a static graphic with a link to Google Maps. This is different content for different screens and is best not handled by CSS, but rather our server giving us different content. We use Enquire.js for this and Ajax in the correct content.

// wait until the site loads, it's in the footer anyway
$(window).load(function() {
  enquire
    .register("(min-width: 650px)", {
      // reverso mama-bear, essentially
      match: function() {
        $("#map").load(
          "/parts/map-papabear.html"
        );
      },
      // baby-bear
      unmatch: function() {
        $("#map").load(
          "/parts/map-babybear.html"
        );
      }
    })
    .listen();
});

Our global.js file ended up concatenating three libraries. CodeKit handles this well with it’s comment directives:

// @codekit-prepend "jquery.fitvids.js";
// @codekit-prepend "modernizr.js";
// @codekit-prepend "enquire.js";

// our custom code...

We didn’t leave any videos in the final example, but we did mess around with them in the Workshop and used FitVids.js to make them work in our fluid width design.

$(".main-column").fitVids();

Happy trails!