Steve Rydz

The thoughts, findings & opinions of a front-end developer

Building a Grid Using Sass Mixins

| Comments

Whilst on a train yesterday I had some time to spare, so I decided to make my own grid system. To see all the code at once check out the gist, otherwise read on to see how I put it together.

What I want from a grid system

When using a grid system I want it to be configurable and I want to be able to choose my own class names. With this in mind I created some variables for the parts that need to be configurable:

1
2
3
4
5
6
$container-width: 96% !default; // Sets the overall width
$container-max-width: 1200px !default; // Sets the max-width
$grid-base-outer-width: 940 !default; // Context
$grid-base-col-width: 60 !default; // Based on context
$grid-base-gutter-width: 20 !default; // Based on context
$grid-cols: 12 !default; // Number of columns

I’ve appended the !default flag to each variable so they can be overridden by the projects config/variables file if needed.

The basics

The first part of building a grid system is setting up the overall page container mixin:

1
2
3
4
5
6
@mixin container {
  @include clearfix;
  width: $container-width;
  max-width: $container-max-width;
  margin: 0 auto;
}

I’ve used a clearfix mixin based on Nicolas Gallagher’s micro clearfix hack. This would normally be somewhere else in the project but I’ve included it here for the sake of clarity:

1
2
3
4
5
6
7
8
9
10
11
12
@mixin clearfix {

  &:before,
  &:after {
    content: " ";
    display: table;
  }

  &:after {
    clear: both;
  }
}

To clear the columns I’m going to need a row mixin. You could use the clearfix mixin instead if you prefer, as it does exactly the same thing:

1
2
3
@mixin row {
  @include clearfix;
}

Making the columns

No grid would be complete without its columns. First I need to calculate some percentages for the grid columns and gutters:

1
2
$grid-col-width: percentage($grid-base-col-width / $grid-base-outer-width);
$grid-gutter-width: percentage($grid-base-gutter-width / $grid-base-outer-width);

Now I know what measurements I’ll be working with I can create a mixin to create the columns:

1
2
3
4
5
6
7
8
9
@mixin span-columns($cols) {
  float: left;
  width: ($grid-col-width + $grid-gutter-width) * $cols - $grid-gutter-width;
  margin-right: $grid-gutter-width;

  &:last-child {
    margin-right: 0;
  }
}

Allowing for more rows

This all works fine but it means every time I want a new row of columns I’ll need to create a new row container. In some cases this is fine, but if I’m working with a grid of thumbnails this isn’t very useful, so I created an omega mixin to clear the end of each row:

1
2
3
4
5
6
@mixin omega($nth) {

  &:nth-child(#{$nth}) {
    margin-right: 0;
  }
}

The drawback to this is that I may need to reset the omega element at a different breakpoint. For that I created another mixin:

1
2
3
4
5
6
@mixin omega-reset($nth) {

  &:nth-child(#{nth}) {
    margin-right: $grid-gutter-width;
  }
}

Usage

This grid system is all mixins. No code is output unless you choose to use it, which is as simple as including the relevant mixin when defining your layout classes. For example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
.page-container {
  @include container;
}

.thumbnails {
  @include row;
}

.thumbnail {
  @include span-columns(6);
  @include omega(2n);

  @media only screen and (min-width: 600px) {
    @include span-columns(4);
    @include omega-reset(2n);
    @include omega(3n);
  }
}

The class names I’ve used above are purely to illustrate how these mixins can be used. The idea is that it’s up to you to define the class names you use.

Going forward

There are many ways I could extend this grid framework, but for simple projects this has everything I need. If I wanted anything more fully-featured I would still use neat as it has everything I need in a grid system, whilst being tested and maintained by some very smart people.

The Boy Scout Rule

| Comments

Keeping a clean codebase is an ongoing process. We try our best to do things well to begin with, but we’re always going to come across things that we could be improved.

Refactoring

Refactoring is a great way to tidy up your codebase, but it’s highly unlikely you’ll have scheduled time to do this. The best method I’ve found is the Boy Scout rule.

Always leave the campground cleaner than you found it.

This can be directly translated to Always leave the codebase cleaner that you found it. So every time you work on a module, leave it in a better state than when found it.

Every day I touch multiple files from various parts of our codebase. For the past few weeks, every time I’m in one of those files, I try to find something I can improve.

The kind of things I’m looking for could be anything from improper indentation, mixed single and double quotes, obvious duplication, or maybe a function that I wrote six months ago that I now know could be more efficient or modular.

For the good of the team

What would happen if we all started cleaning up as we go?

I think if we all followed that simple rule, we’d see the end of the relentless deterioration of our software systems. Instead, our systems would gradually get better and better as they evolved. We’d also see teams caring for the system as a whole, rather than just individuals caring for their own small little part.

Uncle Bob

Cleaning up as you go is not only beneficial to you, but also to your fellow team mates. By making the codebase cleaner and easier to maintain, you make everyones life easier.

There is one caveat here. I’m not going to completely rewrite someone else’s code without involving them. There are many reasons for this, including the fact that I don’t necessarily understand the intent of that code.

It’s important to involve your team mates when making changes to their work. There would have been good reasons for using the approach they took. If there is a way it can be improved, you should pair, so you both understand what is going on.

Start small

If you’ve never worked in this way before, I highly recommend that you give it a try. Remember, you don’t have tidy up your entire codebase. Just make something a little bit better than it was before.

Keeping a Debugging Journal

| Comments

Have you ever found yourself trying to debug something that you’ve come across before, but can’t remember how you solved the problem? I know I have many times, so I started a debugging journal.

What is debugging journal?

A debugging journal is just a way of documenting the process you used to fix a bug. It can be in any format. You could start a tumblr, use a wiki, or use an app like Evernote (which is what I do). You could even use a real-life notebook. It’s your choice.

Why would I want to document all the bugs I fix?

By documenting all your bug fixes, you can be sure that next time you come up against that bug, you will have something to refer to if you can’t remember how you fixed it.

Another benefit is that by documenting how you fixed a bug, you ensure you understand how you fixed it. How many times have you moved code around, miraculously fixed a bug, and had no idea how? This way, you’re forced to understand what actually fixed the problem.

How do I make a debugging journal?

As I said above, you can use whatever you feel comfortable with. I use Evernote. I created a new notebook called Debugging Journal, and every time I fix a new bug I start a new note within that notebook which details the problem, the solution, and why it worked.

It’s a simple idea but has the potential to be very effective in saving you time in the future, and helping you to learn too.

It Should Have Been Vanilla

| Comments

Whilst looking for ways to improve the performance of a site I was working on, I wrote a simple function to lazy load an iframe. I did it in jQuery so it was only a few lines of code:

1
2
3
4
5
6
7
8
9
10
11
function lazyFrame(frameID) {

  var $myFrame = $(frameID),
      myFrameSrc = $myFrame.data("src");

  $(window).bind("load", function () {
    $myFrame.attr("src", myFrameSrc);
  });
}

lazyFrame("#myframe");

Later that evening I thought about this and realised that the exact same functionality was actually just as simple in vanilla JavaScript:

1
2
3
4
5
6
7
8
9
10
11
function lazyFrame(frameID) {

  var myFrame = document.getElementById(frameID),
      myFrameSrc = myFrame.getAttribute("data-src");

  window.onload = function () {
    myFrame.src = myFrameSrc;
  };
}

lazyFrame("myframe");

You might notice both examples span the same number of lines, and as this code is pretty basic, there aren’t any crazy hacks needed to make it work in legacy browsers. Ultimately, there was no benefit to using jQuery in this case. So why use it?

Disclaimer: It is worth noting that jQuery was already in use on the site in question, and in the spirit of maintaining consistency across the codebase it made sense to use jQuery in this situation.

What Are You Using?

| Comments

I just read a post on net tuts called What are you using?. Several front-end developers answered the same set of questions about their setup.

Whilst I wasn’t part of the article, I still thought it might be interesting to publish what my answers would have been. I’d also encourage other front-end developers to do the same, as it’s always interesting to read about others tools and processes.

What’s your primary development focus? As a front-end developer my main focus is HTML, CSS and JavaScript. I also work with Ruby and PHP (mostly in the form of WordPress) when I’m building and maintaining templates.

What hardware are you using at the moment? My primary work machine is a 21” iMac. At home I use a 13” MacBook Air. I also have an iPhone 4s and Nexus 7.

Which editor or IDE do you use? Exclusively Sublime Text 2. I love how fast and extensible it is, and every day I learn something new about it.

What software can you not live without on a daily basis? Obviously Sublime Text 2, but I also spend a fair amount of time on the command line using the likes of Git and Grunt, for which I use iTerm2. Other than that, the Chrome Developer tools are increasingly indispensable.

Revisiting My jQuery Gallery - Without jQuery

| Comments

There’s been a lot of talk lately about The Vanilla Web Diet and not relying on jQuery. This lead to me revisiting some of the code I wrote when I was learning jQuery.

A little over a year ago I published a post on how to make a simple JavaScript gallery. In the spirit of encouraging developers to learn the language behind the library, I’ve written a vanilla JavaScript version.

See the demo →

The HTML

The HTML is really simple. We have one main image and a list of thumbnails, each linking to the full sized image.

1
2
3
4
5
6
7
<img id="main-image" src="img-01.jpg" alt="Placeholder">

<ul id="thumbnails">
  <li><a href="img-01.jpg"><img src="img-01-tn.jpg" alt="Thumbnails"></a></li>
  <li><a href="img-02.jpg"><img src="img-02-tn.jpg" alt="Thumbnails"></a></li>
  <li><a href="img-03.jpg"><img src="img-03-tn.jpg" alt="Thumbnails"></a></li>
</ul>

The JavaScript

The amount of code here is fairly concise, and not that much more than last time. Whats more, it doesn’t require the overhead of the jQuery library.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
(function () {

  if (document.querySelectorAll) {

    var links = document.querySelectorAll("#thumbnails a"),
        mainImage = document.getElementById("main-image");

    for (var i=0; i < links.length; i++) {
      links[i].onclick = function (e) {
        e.preventDefault();
        var source = this.getAttribute("href");
        mainImage.setAttribute("src", source);
      };
    }
  }
})();

Now lets step through the code.

Keeping the window object clean

First we wrap our code in a self-executing anonymous function. This keeps our variables from polluting the global scope:

1
2
3
(function () {

})();

Checking for support

Next we’re going to declare the variables we need, but as we’ll be using querySelectorAll, we’re just going to check that the browser supports this before executing our code:

1
2
3
if (document.querySelectorAll) {

}

If the browser doesn’t support querySelectorAll then the browser will skip over the code that follows.

Now we can declare the variables we need. The first will cache all the thumbnail links, and the second will cache the main image:

1
2
var links = document.querySelectorAll("#thumbnails a"),
    mainImage = document.getElementById("main-image");

Switching out the main image

Now we want to loop through all the thumbnails and listen for the click event. When they’re clicked, we change the src attribute of the main image to the thumbnails href value:

1
2
3
4
5
6
7
for (var i=0; i < links.length; i++) {
  links[i].onclick = function (e) {
      e.preventDefault();
    var source = this.getAttribute("href");
    mainImage.setAttribute("src", source);
  };
}

Improvements?

That’s all there is to it. If theres anything you think could improve this code, I’d love for you to share in the comments or maybe even in your own post.

I Like My Bourbon Neat

| Comments

This week I started using Bourbon and it’s accompanying grid system, Neat. I really like the way they’ve been put together and think they’ll be really useful going forwards.

It’s easy to get started with bourbon and neat, and neither of them dictate the way you should structure your application. Lets go over some of the basics.

Installing bourbon and neat

Bourbon and neat are both gems, which makes them really easy to install. Just type sudo gem install bourbon neat into your command prompt and hit enter. Your now ready to harness the power of bourbon.

Setting up a project

In your command prompt, cd into the directory you want to store the bourbon and neat files, then install the dependencies as follows:

1
2
3
$ cd ~/Sites/project/scss/
$ bourbon install
$ neat install

Add the following to the top of your main .scss file:

1
2
3
@import "bourbon/bourbon";
@import "neat/neat";
// The rest of your CSS goes here

Using bourbons mixins

Bourbon comes with lots of really useful mixins and utilities. Making use of them is simple, for example a linear gradient:

1
2
3
.container {
  @include linear-gradient(#1e5799, #2989d8);
}

For more examples check out the docs.

Harnessing the power of the grid system

Many grid systems make you add presentational classes to your HTML which to a lot of us is undesirable. With neat, you don’t need to do that at all. If I wanted to create a container with a primary content area and sidebar, all I would need to do is:

1
2
3
4
5
6
7
8
9
.container {
  @include outer-container;
}
.content-pri {
  @include span-columns(9);
}
.content-sec {
  @include span-columns(3);
}

Your HTML would look something like this:

1
2
3
4
5
6
7
8
<div class="container">
  <div class="content-pri">
      <!-- Main content area -->
  </div>
  <div class="content-sec">
      <!-- Sidebar -->
  </div>
</div>

Neat also does some cool things with media queries. You can define breakpoints by declaring a variable like this:

1
$tablet: new-breakpoint(min-width 767px);

You can then call the appropriate media query like this:

1
2
3
@include media($tablet) {
  // Your code
}

Again, there are more examples in the docs.

Extending the mixins

Including these mixins is absolutely fine, but your codebase could become bloated very quickly if you find yourself calling the same mixins repeatedly. For example if you used the clearfix mixin on a lot of elements, the following code would appear in your compiled file for every one of those elements:

1
2
3
4
5
6
7
8
9
10
11
.element {
  *zoom: 1;
}
.element:after,
.element:before {
  content: " ";
  display: table;
}
.element:after {
  clear: both;
}

What I recommend is making use of the @extend rule. First you would create a silent class which includes your required mixin. This code will only be compiled if you extend it:

1
2
3
%cf {
  @include clearfix;
}

Then, anywhere you want to use that mixin, just extend your class:

1
2
3
.container {
  @extend %cf;
}

This technique can significantly reduce the amount of repetition in your codebase, which is always a good thing.

Striking the right balance

Bourbon manages to do what many other frameworks have so far failed to do, which is provide you with a collection of best practices without dictating how you structure your code.

I love the fact that my codebase is only going to include the things I need from bourbon, without lots of unused utilities, and my HTML can be as semantic as I want it to be. I strongly recommend giving bourbon a try on your next project.

Testing Localhost on Other Devices

| Comments

Testing our websites and apps on devices other than our dev machines can be a pain, but there is a (free) service out there that makes it really easy.

xip.io is a service built by 37signals to solve a common problem. What is xip.io?

xip.io is a magic domain name that provides wildcard DNS for any IP address.

It is really easy to use, and lately I’ve been using it on a daily basis. Here’s how it works:

Let’s say your running a local server at http://localhost:8000. You could also access that via your LAN IP. Here’s how to find your LAN IP on a Mac and on Windows.

Whatever your LAN IP is, paste it into your address bar, with the port number appended e.g. http://192.0.0.1:8000. You should see the same thing that your seeing at http://localhost:8000. If you’ve made it this far, it should all be plain sailing from here.

Now you want to see your localhost site on your mobile. Fire up the browser on your device, making sure you are connected to the same network as your dev machine. In the address bar, type your LAN IP, followed by .xip.io and if you are using a port, append that e.g. http://192.0.0.1.xip.io:8000.

That’s it. You can now test your development code easily on whatever devices you have handy.

Update: I have found that sometimes, it isn’t necessary to actually use xip.io. If it the above doesn’t work for you, try visiting your LAN IP, with the necessary port appended e.g. http://192.0.0.1:8000. Also, remember that you must have your local server running on your dev machine.

Setting Attributes With JQuery

| Comments

I’m going to share a quick jQuery tip: How to add multiple attributes to an element. I see people use chaining to achieve this on a regular basis, but there is a better way.

When adding multiple attributes to an element, the simplest way is to create an object, as shown in the following example:

1
2
3
4
5
$(".main-image").attr({
  "src": "/img/main-image.jpg",
  "title": "This is the main image",
  "alt": "This is the main image"
});

Personally I find this method much more readable and easier to maintain.

Terminal Tip: Case-insensitive Completion

| Comments

These days I use the command line all the time. Something I rely on quite heavily is tab completion, but it can be frustrating when it comes to case sensitivity.

Thankfully, there is a really simple solution to this. Just open your .bash_profile file, found in your home directory. As I use sublime I would do so like this:

1
$ subl ~/.bash_profile

Then add the following line to your ~/.bash_profile:

1
$ bind "set completion-ignore-case on"

Once you have done that, run the source command on that file:

1
$ source ~/.bash_profile

You should be good to go. From now on, your bash prompt will ignore case.