To Framework, or Not To Framework: Part 2

In part 1 of “To Framework, or Not To Framework“, I wrote about why I don’t tend to use frameworks like Bootstrap or Foundation. If you haven’t read that, it gives a bit of context to the “why” part of this article.

The first thing people use in a framework (at least it feels that way) is the grid system. In Foundation .large-1 accomplishes the same thing.

Both Bootstrap and Foundation are based on a 12 column grid. So those classes above are asking for 1/12 of the grid. Bootstrap implies we’re working with desktop styles. Foundation makes it a bit more obvious by adding “large” to the class.

If you want to assign a column to be 1/2 of the width of the screen on mobile, you would write:

Bootstrap: .col-xs-6 (xs = extra small)

Foundation: .small-6

When you want to make things responsive, you can mix and match those classes to get it right.

Bootstrap

<div class=“col-xs-6 col-md-3”></div>

Foundation

<div class=“small-6 large-3”></div>

Freedom

Now there’s nothing wrong with those grid systems. But for me, I don’t use Bootstrap or Foundation because of all the overwriting of styles that I have to do to make something look unique. So, I don’t include Bootstrap or Foundation just for their grid system. For me, since I’m not bound to a framework, I get to choose the grid system that makes the most sense to me. Instead, I use Nathan Smith, who wrote Unsemantic, used percentages to build the grid system. So, if I want a div that sits at 50% width on mobile and 10% on desktop, that looks like this:

<div class=“mobile-grid-50 grid-10”></div>

By just using .grid-10, I get the desktop styles. Adding mobile- or tablet- to the class applies that style if the reader is on a mobile or tablet device.

Application

Now, for a long time, I wrote my divs exactly as seen above so that other people could figure out what I was doing:

<div class=“sidebar mobile-grid-100 grid-25”></div>

Usually there’s another class in there anyway, in this case .sidebar. So instead of adding a series of classes in my HTML, I’m now making use of Unsemantic inside my SASS files as often as I can. So I write something like:

.sidebar {
    @extend .grid-25;
    @extend .mobile-grid-100;
    /* More styles go here */
}

By adding them in the SASS file they’re included in the CSS files when that’s all combined. As a result, my HTML is more minimal. My SASS files stay cleaner, too. By using @extend, I can do widths, margins, padding, and responsive styles all in one single line.

Impacts on Design

The biggest departure isn’t the grid-10 vs col-1 vs large-1, it’s in the design phase. If you design for Bootstrap or Foundation (or just prefer 12 columns), not having 12 columns as a basis can be a little jarring. But for me, if I look around at other designs, most of the basics exist in all three systems. 1/3 is still 1/3, regardless of whether it’s 4 columns or 25%, for example. But Unsemantic doesn’t break down into twelve parts you get ten instead.

If that bugs you for some reason, I’d recommend HTML and CSS, because regardless of what back-end languages, or JavaScript libraries are in play, they all tend to need HTML and CSS at the core of it.

Apparently it was the right answer for this team, however.

At the time I had worked in web apps, where the entire thing was written in Rails/Java/.NET and I just had to make the front-end work. And I had also worked on apps that were front-end heavy, written in AngularJS or Backbone. Even the iOS development work that I’ve done fell into that second category.

If you can write HTML and CSS well, it takes away a whole lot of cruft from the interface. You don’t have random unnecessary tags floating around. Things aren’t in tables, unless you’re working with tabular data. And you can often speed up the UI by not leaning on JavaScript in the first place.

Frameworks

But there was a bigger context to that question, which revolved around Bootstrap and AngularJS.

At the time, I had been working on apps that used (and occasionally abused) Bootstrap or Foundation. One of those apps also happened to use AngularJS. Another still used Bootstrap, AngularJs, and a few random bits of CoffeeScript because someone wanted to upgrade their resume.

I could certainly write Bootstrap specific HTML, I didn’t consider it hard or a big, scary unknown. It’s just not for me. I’ve built my career on being a minimalist HTML and CSS writer, and that has never failed me. Not once.

But having that skill gives me an opinion about Bootstrap and the HTML and CSS that it expects.

Now, I’m not at all hating on Bootstrap. Use it or don’t, I don’t really care. But for me, I never use 95% of Bootstrap, or any other framework. There’s a ton of stuff that nobody uses. But yet, if I choose it, it sits there in my project. Sometimes, Bootstrap updates, and things break. I have to rewrite code, update classes, etc. But minimalist stuff just doesn’t move. It stays in place.

And of course, the more weight my scripts and CSS files have in them, the more of a pain it is to get that stuff loaded into a browser or mobile device. (One of my recent Angular projects had about 500KB of scripts alone.)

I see so many job posts asking for something particular, like Foundation or Bootstrap that it’s easy to see why young front-end developers focus on it. And with the variety of things that a framework like that can do, it’s easy to see why they’re often “the obvious choice.”

But I think there’s a better way forward. In the next few articles, I’ll be writing about my own processes and how I go about building sites. I’ll be starting with the bits of CSS and HTML that I use in almost everything I build.

Part 2: Grid Systems

Web Standards and JavaScript for Aging Devices

The first thing I learned about web development was that there was this thing called “Web Standards”, and it was awesome. We as an industry are better for it because it’s inclusive and altruistic. People with screen readers, for example, benefit from it because we knew better than to just use Flash on everything. You’re probably not writing your HTML into tables these days, so thank the web standards movement for that too.

But web standards also ventures into things like removing onClick=“Insert your JavaScript Here” from your HTML, and instead advocates for placing that JavaScript in your actual JavaScript file. And that’s smart, because when you’re working on a web app, or a site with a lot of pages, you don’t want to go through and pull out references to things you use over and over again.

In fact, that has been one of my primary frustrations with AngularJS. It’s so much of ng-click=”“ that it’s basically a collection of “bad practices”.

The Problem With that

We’ve been working hard on an iOS app over at Artletic. We opted to use the Ionic Framework, but not all of the Angular JS stuff because, well, at the time it didn’t seem to be necessary when all we wanted was some HTML and some JS. I set the thing up on day one and it just flew. Seriously, it was quick.

Fast forward to last week and the app was just dragging on my actual iPhone 4. Now, that’s on a 4. It was semi-usable on a 5, but not everyone has a 5. In fact, I could hardly test the latest features because it was so slow on my phone.

So I remembered something that happened to me a few years ago when I worked at (what was then) Nathan Smith and I (mostly Nathan) refactored my code to work for larger sets of data because it had a serious performance drain under those conditions.

The Wisdom in Being “Wrong”

The way he did it, was to rework and then reference the JavaScript function with an onClick. Why did it work? By registering click events for every last one of those thousand items, there was just so much extra memory weight that it dragged down the app. Putting things in the HTML itself meant that the browser didn’t have to roll through every entry and create those events, then watch each and every one of them. It meant that the browser didn’t have to care until you interacted with that data. Then, it would see the onClick event and take action… But only when you clicked it.

In my Ionic project it was the same thing, but on a much smaller and finicky scale. My browser was completely fine with the JavaScript, the simulator was fine with the JavaScript, but the actual device was not. The iPhone is a much lighter device than my Macbook (obviously), there should be no expectation of comparability.

I had been using the module pattern, and each click event was already referencing functions.

Before, it looked like this:

$('body').on('click', '#something', function ( ){
	interaction.load_something();
});

But for performance’s sake, I changed it to be this:

<a href="#whatever" id="something" onClick="interaction.load_something();">Whatever</a>

When there are large sets of data, that markup is neatly placed in a Handlebars template that gets added and subtracted from the DOM as necessary. It’s just as performant if there are one or a hundred things in the list, and because it’s included in a partial, I’m not having to maintain that code in 100 pages across an app. And I think that’s why AngularJS uses hg-click as well.

The speed increase was immediately apparent. I removed the click function in my JS file for one of the biggest offenders, and the app was suddenly very usable. It wasn’t as usable as I wanted it to be, however, but when we removed a good number of the click events it sped up quite a bit.

So while it wasn’t exactly a tactic that I’ll be applauded for in the web standards community, it saved our app and, thanks to Handlebars, still kept me from having to weed through too much JavaScript in my HTML.

In Reality

This really isn’t an anti-web standards post. Honestly, the old wisdom is so good that most of my sites will still use the same module pattern and click events routine. But when I’m building something mobile/hybrid, inline click events are a small price to pay for what could be a large number of happier users on aging, lightweight devices.

Web Standards and Pragmatism

The first thing I learned about web development was that there was this thing called “Web Standards”, and it was awesome. We as an industry are better for it because it’s inclusive and altruistic. People with screen readers, for example, benefit from it because we knew better than to just use Flash on everything. You’re probably not writing your HTML into tables these days. So thank the web standards movement for that too.

But “web standards” also ventures into things like removing onClick=“Insert your JavaScript Here” from your HTML, and instead advocates for placing that JavaScript in your actual JavaScript file. And that’s smart. When you’re working on a web app, or a site with a lot of pages, you don’t want to go through and pull out references to things you use over and over again.

In fact, that has been one of my primary frustrations with AngularJS. It’s so much of ng-click=“” that it feels like a recreation of onClick.

The Problem With that

We’ve been working hard on an iOS app over at Artletic. We opted to use the Ionic Framework, but not all of the Angular JS stuff because, well, at the time it didn’t seem to be necessary when all we wanted was some HTML and some JS. I set the thing up on day one and it just flew. Seriously, it was quick.

Fast forward to last week and the app was just dragging on my actual iPhone 4. Now, that’s on a 4. It was semi-usable on a 5, but not everyone has a 5. In fact, I could hardly test the latest features because it was so slow on my phone.

So I remembered something that happened to me a few years ago when I worked at (what was then) Fellowship Technologies. I created this nice and orderly list wherein people could interact with their data. However, we never tested it with thousands of entries. Shortly after, Nathan Smith and I (mostly Nathan) refactored my code to work for larger sets of data.

The Wisdom in Being “Wrong”

The way he did it, was to rework, and then reference the JavaScript function with an onClick. Why did it work? By registering click events for every last one of those thousand items, there was just so much extra memory weight that it dragged down the app. Putting things in the HTML itself meant that the browser didn’t have to roll through every entry and create those events, then watch each and every one of them. It meant that the browser didn’t have to care until you interacted with that data. Then, it would see the onClick event and take action… But only when you clicked it.

In my Ionic project it was the same thing, but on a much smaller scale. My browser was completely fine with my JavaScript, but the actual device was not. The iPhone is a much lighter device than my Macbook (obviously), there should be no expectation of comparability.

I had been using the module pattern, and each click event was already referencing functions.

Before, it looked like this:

$(‘body’).on(‘click’, ‘#something’, function ( ){
	interaction.load_something();
});

But for performance’s sake, I changed it to be this:

<a href="#whatever” id=“something” onClick=“interaction.load_something();”>Whatever</a>

When there are large sets of data, that markup is neatly placed in a Handlebars template that gets added and subtracted from the DOM as necessary. It’s just as performant if there are one or a hundred things in the list, and because it’s included in a partial, I’m not having to maintain that code in 100 pages across an app.

The speed increase was immediately apparent. I removed the click function in my JS file for one of the biggest offenders, and the app was suddenly very usable. It wasn’t usable as I wanted it to be, however, but when we removed a good number of the click events it sped up quite a bit.

So while it wasn’t exactly a tactic that I’ll be applauded for in the web standards community, it saved our app and, thanks to Handlebars, still kept me from having to weed through too much JavaScript in my HTML.

In Reality

This really isn’t an anti-web standards post. Honestly, the old wisdom is so good that most of my sites will still use the same module pattern and click events routine. But when I’m building something in the mobile/hybrid space, something like inline click events is a small price to pay for what could be a large number of happier users on aging, lightweight devices.

Better Team Projects with Grunt JS

For years I pre-processed my SASS/LESS files and minified my JavaScript with apps like Codekit. And while those are great, they don’t always work nicely with whatever apps your coworkers are using. That’s where Grunt JS shines.

What I Was Doing

Because I had mostly been working by myself on things, I was running CodeKit or even SASS/Compass from the command line. It works, obviously, but when your teammates want to run something else, like Prepros, for example, not all apps build things the same way.

Sometimes it was a minor difference. The first thing we noticed, for example, was that one of our apps was adding in line-numbers while the other one was not. It’s fine, until you work in a shared Git repo and suddenly those line numbers are all changes that need to be merged.

Or in some cases, because I was using CodeKit to also minify my JavaScript and lint it for errors, we would run into differences in which files were being included at what points. So while it worked fine for me, my coworkers were throwing errors because one library was being included before jQuery, or it just wasn’t being pulled in at all.

It was a mess, an actual mess.

Enter GruntJS

I had heard things about Grunt, but I wasn’t buying into the hype. Until I got really frustrated one night and decided that it was either give it a shot or hate working with pre-processors and minify everything by hand.

Within an hour, I was up and running on Grunt. I now use it for every last project because, well, I have too much to do to fight inconsistencies with teammates. (Totally not their fault.)

Configuring Grunt

I won’t get into the install steps, because the Grunt site does that rather well: Getting Started.

But what might be more useful is to show how my Grunt file is helping me.

module.exports = function(grunt) {
	'use strict';
	grunt.initConfig({
		pkg: grunt.file.readJSON('package.json'),
		concat: {
			options: {
				separator: ';'
			},
			dist: {
				src: ['/_js/jquery.js', '/_js/handlebars.js', '/_js/raphael.js', '/v10/_js/g.raphael.js', '/_js/g.line.js', '/_js/interaction.js'],
				dest: /_js/interaction.min.js'
			}
		},
		jslint: { // configure the task
			// lint your project's client code
			client: {
				src: [
				'/_js/interaction.js'
				],
				directives: {
					browser: true,
					predef: [
					'jQuery'
					]
				},
				options: {
					junit: 'out/client-junit.xml'
				}
			}
		},
		sass: {
			dist: {
				files: {
					'/_css/screen.css': '/_css/screen.scss'
				}
			}
		},
		uglify: {
			options: {
				banner: '/*! <%= pkg.name %> <%= grunt.template.today("dd-mm-yyyy") %> */\n'
			},
			dist: {
				files: {
					'/_js/interaction.min.js': ['/_js/interaction.min.js']
				}
			}
		},
		watch: {
			files: ['/_js/interaction.js', '/_css/*.scss'],
			tasks: ['concat', 'uglify', 'sass']
		}
	});
	grunt.loadNpmTasks('grunt-contrib-concat');
	grunt.loadNpmTasks('grunt-contrib-uglify');
	grunt.loadNpmTasks('grunt-contrib-watch');
	grunt.loadNpmTasks('grunt-contrib-sass');
	grunt.loadNpmTasks('grunt-jslint');
	grunt.registerTask('default', ['concat', 'uglify', 'sass']);
	grunt.registerTask('tests', ['jslint']);
};

Grunt and Concatenation

To break that down, there’s a bit of configuration before we get to this important bit here:

concat: {
	options: {
		separator: ';'
	},
	dist: {
		src: [‘/_js/jquery.js', '/_js/handlebars.js', '/_js/raphael.js', ‘/_js/g.raphael.js', '/_js/g.line.js', '/_js/interaction.js'],
		dest: '/_js/interaction.min.js'
		}
	},

As you might have guessed, that’s the concatenation function. It grabs everything listed in the “src” array and uses it to create interaction.min.js. If you were to run just that, it would be as if you manually copied and pasted all those files into one, large JavaScript file.

Next up, we have the JSLint plugin which opens up just my custom JavaScript file, and looks for errors or syntax issues. A point of consideration here is that I’m working only with the “client” code block. If you’re a NodeJS developer, (you probably already use Grunt), but you can also separate your server code to be linted.

Grunt and SASS

The SASS section caught me a bit off guard at first, because it reads backwards to me, but it looks like this:

sass: {
	dist: {
		files: {
			'/_css/screen.css': '/_css/screen.scss'
		}
	}
},

All it’s doing is taking that second file (/_css/screen.scss’) and using compiling it to the first (/_css/screen.css). Now for me, I have a bunch of other SCSS and CSS files that I include in screen.scss, but they don’t need to be pre-compiled. So this is the extent of it.

Grunt and JavaScript Minification

The next function is Uglify, which is this block:

uglify: {
	options: {
		banner: '/*! <%= pkg.name %> <%= grunt.template.today("dd-mm-yyyy") %> */\n'
	},
	dist: {
		files: {
			'/_js/interaction.min.js': ['/_js/interaction.min.js']
		}
	}
},

The options section just creates a stamp at the top of your file, in this case I have the package name and the timestamp for today. But the “dist” section is the important part. In the concat function, we’re building interaction.js into interaction.min.js, which until this function runs, isn’t actually minified. If I were to point this function at interaction.js, it would minify my source, and that would be awful to maintain. So all we’re doing is taking that temporary file from above and minifying it instead.

Watching for Changes

And lastly, we have the watch section:

watch: {
	files: ['/_js/interaction.js', '/_css/*.scss'],
	tasks: [‘concat', 'uglify', 'sass']
}

All this does, is keep an eye on anything listed in the “files” array for changes. If any of them change, it runs the other functions in order. (Concat, uglify, SASS). And this is key here. If you were to switch concat and uglify, you’d always see unminified code. And, if you’re only working on the CSS side of your project at any given time, you can move “sass” to the front of the list and have your output faster.

After the functions are all defined, we get to some Grunt commands that load the actual modules to do the work, but the last bit of importance for us is this:

grunt.registerTask('default', ['concat', 'uglify', 'sass']);
	grunt.registerTask('tests', ['jslint']);

The first line instructs what should happen if I were to run Grunt without any other options. It would roll through concat, uglify, and sass, just like in the watch function. The second line, only runs the JSLint function. Personally, I don’t like to have JSLint yelling at me every time I need to compile the scripts, or worse, CSS. Sublime text can already do basic linting as I write.

Running Grunt

Now, once this file is in place, I can open terminal and find the root of my project. Then, it’s just as easy as typing “grunt.” Doing that would load the default function. But, I don’t do that very often since I’d have to do it over and over again. Instead, I usually run:

grunt watch

That invokes the watch function and keeps an eye on the JS and SCSS files I work with.

And while there’s a lot more you can do with Grunt, I personally don’t need anything more than this. I’m sure as I get deeper into Angular JS and Node JS that will change, but for now, I’m content with just having a way to get my whole team onto the same page without conflict over the files we work with most often.

A Little HTML/CSS/JS in a CMS Never Hurt Anyone, Right?

For years we’ve been talking about separating JavaScript from HTML, and CSS, but there’s always a temptation to continue writing HTML and CSS into the wrong parts of our content management systems. I wasn’t willing to say this before, but it’s a design problem. And it really is a tough line to walk.

For as long as I’ve used a content management system, someone has tried to get me to write HTML into it. I’m not talking about the CMS’ template feature. Do that. But I mean specifically inside articles or page content.

It may seem like a good idea at the time to write:

<img src="something.jpg" alt="This is an image of something" class="go_full_width float_left" style="border: 1px solid #fff;" width="960" height="320" />

But what happens in two years when you redesign your site and you don’t remember to remove the class “.go_full_width”, or the border on the image? Or what if you need to resize that image with CSS for some reason? Well, you have to go back through all your articles and take that stuff out.

It’s a pain, trust me on that one. The bigger the site, the more headache it is.

Why Is It a Design Problem?

It’s easy to blame the person who drops that HTML into the CMS, to point fingers for doing it “the wrong way”. Personally, I think it comes down to neglect on the design side. It may not seem like it from the example above, but consider the case of someone trying to create columns of content in a WordPress article page, or declaring a million styles about text formatting and colors. That almost always comes from expectations laid out in a design.

It’s a design problem because we didn’t consider how the chosen CMS actually works.

For the most part, a CMS typically has one space for content per article or page. As a result, you only get one chunk of content to drop on your page, typically in the main content section. But yet we create designs with interesting and non-versatile expectations of how that one block of text is going to be presented from the CMS. Maybe it’s as simple as perfect columns of varying widths, or that the third column is floated right and smaller to imitate a pull quote.

My rule of thumb going forward, will be to only design what can be accomplished through external CSS using minor classes and semantically meaningful tags. (So giving a paragraph the class of “pull_quote” is fine.) If on a particular project I’ll be using a CMS that does allow me to split content up or add extra boxes for different things, then I’ll have to consider their best use before I design anything. I would still very likely err on the side of simplicity, because you don’t want to have to go back through every page to merge various fields together again.

How Do We Solve It?

I recommend using a unique identifier to give your stylesheet something to pick up for styling. In Textpattern and WordPress there are custom fields, for example. You can enter a value and it’s ready for you at the template level.

When you create your template, find those values and put them on a div, or any container, so that you can write styles against it. Here’s an example from Textpattern:

<div id="main_content" class="<txp:if_custom_field name="is_divided">divided</txp:if_custom_field"> 
// Content goes here, probably lots of it.
</div>

So what does that do? First, it looks for the custom field named “is_divided”, and just checks to see if there’s a value in there. If there is, it adds in the divided class. In this particular case, that tells my CSS to apply these styles:

.divided {
	-moz-column-width: 20em;
	-o-column-width: 20em;
	-webkit-column-width: 20em;
	column-width: 20em;
	-moz-column-gap: $margins;
	-o-column-gap: $margins;
	-webkit-column-gap: $margins;
	column-gap: $margins;
	padding: 0 40px 0 60px;
}
.divided p {
	margin-left: 10px;
	margin-right: 0;
	padding-right: 0;
}
.divided p:first-child {
	margin-top: 0;
}

All from the safety and confinement of the CSS file, which I can adjust to my heart’s content. A more advanced way to do this would be to request an extra stylesheet entirely. However, it’s probably more useful to apply a body class and just distinguish between the added styles in your master CSS file.

So there you have it, a quick way to help avoid the need for HTML and CSS in your content management system.

Don’t Over-Think Your CSS (Part 1)

Over the years I’ve developed a love for making HTML and CSS as streamline as possible. Consider this piece of content for a very lean carousel. (You’d probably need more to actually make it work, but the point here is to show a principle of CSS, not to build a carousel.)

<div id="this_specific_thing" class="carousel">
<div class="slider_left">
	<a href="#" class="slide_left_button">Left</a>
</div> <!-- end of .slider_left -->
<div class="imagery">
	<!-- imagine a set of images here that build a carousel -->
</div> <!-- end .imagery -->
<div class="slider_right">
	<a href="#" class="slide_right_button">Right</a>
</div> <!-- end .slider_right -->
</div> <!-- end #this_specific_thing -->

The temptation here, for a lot of people, is to start declaring styles against #this_specific_thing. Sometimes that’s good, but if you ever want to reuse the carousel you’ll have to redeclare all your styles over again. In this case, you should be styling against .carousel instead.

I once knew a guy who would write these meticulous styles in crazy-deep stacks. His CSS files were massive because of it, and none of it was reusable. If you had a correction to one slider, you had to make it to every one.

Most of the time things aren’t that drastic. But there’s always a temptation when starting out to do something like this:

#content p {
	color: #333;
	font-family: "lucida grande", verdana, sans-serif;
	font-size: 14px;
	line-height: 1.4;
	margin: 10px 20px;
}
#aside p {
	color: #ccc;
	font-family: "lucida grande", verdana, sans-serif;
	font-size: 12px;
	line-height: 1.4;
	margin: 10px;
}

And while that may be exactly what you want, you can simplify your CSS like this:

 body {
	color: #333;
	font-family: "lucida grande", verdana, sans-serif;
	font-size: 14px;
	line-height: 1.4;
}
#content p {
	margin: 10px 20px;
}
#aside p {
	color: #333;
	font-size: 12px;
	margin: 10px;
}

And that’s the point of CSS, right? The fact that things cascade. But yet it seems that some people miss the real value of that. Whether you’re working with HTML, CSS, or JavaScript, always, always shoot for reusable pieces. Your life will be much easier because of it.

Your First Web Application: From Design to Launch

Last night I had the privilege of speaking at Refresh Detroit about building web applications. Thank you to all the members and attendees of Refresh Detroit, and especially to Deborah, for inviting me. I had a great time as always!

Since it’s after the fact, and I think the presentation went fairly well, I’ll admit that the topic was a bit large. And by “a bit” I mean, “oh wow, that was massive.” One of the attendees even mentioned that each section could have been a talk on its own. He was absolutely right.

But I also don’t regret taking it on. It was supposed to be a general overview of the process I use to work through creating web applications and I think it accomplished that goal.

If you’re interested in an overview of the talk, the slides are up on Slideshare, or you can Download the PDF.

Your first web application. From Design to Launch from David Brooks

Sometimes Using IDs in CSS Just Makes Sense

Recently Chris Coyier and Harry Roberts opened up the conversation for CSS best practices and people are chiming in. I won’t disagree that the majority of the things Harry mentions are dead-on accurate, though whether or not I or anyone else actually follows them to the letter is debatable. But one of the personal guidelines that he points out is not to use ids in targeting CSS styles. As you might have guessed from the title, I subtly disagree.

He even says it’s a personal thing, so I won’t even say it’s wrong. Louis Lazaris backed him up on it, even getting into a disagreement with Jeffrey Zeldman of all people over the semantic nature of ids. And I won’t disagree there either.

What good is an id in HTML?

Nobody is contending that ids aren’t important for cases like JavaScript, where uniqueness is important and quickly checkable. Where the disagreement lies, essentially, is that ids make something so unique that they’re hard to cancel out in CSS. And that’s completely true.

Let’s consider this case:

<aside id="side_note">
	<p>This is some content that gets pulled toward the side. I'm sure there's more content that would go here, but since this is an example it's going to be a very short paragraph. Don't tell my High School English teacher.</p>
</aside>

In CSS I have two obvious options to style the paragraph inside the <aside>:

aside p {
	color: #333;
}

and

#side_note p {
	color: #333;
}

Here I would say that they’re about equal, since an <aside> element is likely buried in your HTML. The further into the structure you go the less likely there are to be stray styles and the need to reverse style declarations. The best choice is probably still to use aside p { }, simply because there’s one <aside> and there’s not a compelling reason to bother with an id.

Clarity

Now let’s consider this case:

<aside id="side_note">
	<p>This is some content that gets pulled toward the side. I'm sure there's more content that would go here, but since this is an example it's going to be a very short paragraph. Don't tell my High School English teacher.</p>
</aside>
<aside id="a_unique_side_note">
	<p>Here is some other unique, tangental content that should be associated with the content. It should look different than the other aside, just to be difficult.</p>
</aside>

What if in the first case we have a small paragraph that pulls to the side as a note, and the second case is a pull quote. Maybe there is other content in-between. But regardless of more context, and for argument’s sake, they should be different.

If in this situation we use the same method, aside p { }, they will look the same. We can write in classes to make them different, obviously. Maybe that would look something like this:

<aside id="side_note" class="side_note columnar">
	<p class="mini">This is some content that goes…</p>
</aside>
<aside id="a_unique_side_note" class="pull_quote emphasized">
	<p class="large_text">Here is some other unique, tangental content…</p>
</aside>

(Assume that each of those has some unique style to it and that I didn’t just write classes that would do the same things.)

That’s six classes when I could have written:

aside p {}

and

#a_unique_side_note p {}

Now, if you’re going to write things like .large_text and .pull_quote anyway, do that and reuse them. But sometimes you have a one-off thing that is really unique. For clarity, I would argue that targeting #a_unique_side_note instead of making a class .a_unique_side_note does no harm and actually signals to me as a developer that it’s unique and won’t be used elsewhere. That could be important if you only want to see that in one single place ever. If it’s low enough in the document, I see no harm in using an id here. If something will be reused, don’t make it an id.

I’d also never advocate for rewriting all of the styles in aside p {} in #a_unique_side_note p {} that’s insanity. ids should only ever exist to be unique, even when targeted in CSS.

Brevity

Sometimes you have a case where you could write a class on repeat in your CSS. Consider classes like .full_width or .width_100, or whatever else that could be mass applied at a high level. Sometimes it just makes sense to write a single declaration in CSS like this:

#branding_and_navigation,
#content,
#secondary_content,
#site_information {
	width: 100%;
}

In this situation it’s a bit of six in one, half dozen in the other. You could have a series of classes, or a few lines of CSS targeting ids. You might make the case that in a responsive situation these will go away for iPad or iPhone media queries. That might be a case in your particular pattern, and that’s fine. For my standard work these styles go all the way through with each media query and I often don’t negate them at all. So, your mileage may vary here.

Backgrounds

Sometimes you have a design where an element stands out entirely from everything else. Mastheads come to mind quickly, and so do those advertising sites with large imagery. If the correct approach is to drop a background image on a div, why not use

#my_decorative_element {
     background: url('something.jpg') no-repeat center;
}

and call it a day? It’s a singular element that won’t have a twin elsewhere. You could write a class for it, but for me, an id just feels more natural. Ids exist to stand out, to be unique. In this case there’s nothing to interfere, nothing to break, nothing to cascade.

Conclusion

I admit that for years we’ve abused ids when we should have used classes instead. But what I don’t want to see is the vilification of ids, or people scoffing at developers who choose to use them occasionally when there might be a good reason to do so.

Having a set of ideals is good, I wholeheartedly suggest we write the best HTML and CSS we can. Let’s think about efficiency and reusability, but let’s be realistic when we do that. Let’s lean on the uses for ids that do make sense, if it doesn’t go against your personal path for writing HTML. If this isn’t your process and you never touch ids, awesome! But also, as a community of professionals, I’d hate to see this build for a few years into another situation where people toss around arguments that they don’t understand simply because they heard somewhere that ids are evil. !important, or the semantic-ness of classes anyone?

A Quick nofollow for Drupal 7

I built a site for a client in Drupal 7, and it quickly started to gather spammers. I implemented Mollom to filter out a bunch of the spam, but as icing on the cake, to prevent empowering spam links and a deterrent from posting spam comments in the first place, I wanted to make sure all links in the comments were given the rel=“nofollow” attribute like Textpattern does. But, regardless of how many people have asked since 2008-ish, nobody has built this in a way that isn’t handled on a link by link basis, and even then it doesn’t come into play for comments. So, I changed my comment template like so:

The standard code


print render($content);

What it looks like now


$comment_pre = (string) $comment_body[0]['safe_value'];
$replace = '<a href="';
$with = '<a rel="nofollow" href="';
$comment_post_edit = str_replace($replace, $with, $comment_pre);
echo $comment_post_edit;

What it does, is search each comment for anchor tags and drops a rel=“nofollow” just before the href. Their link still shows up, but search engines ignore it.

Now, if spammers will just take the hint, everything will be golden. But even if they don’t, you won’t have to worry about them getting any SEO points from your site.

© 2019 All rights reserved.