-
Tips for Developing a Custom Design for HubSpot CMS
At NMC, we develop 95% of our projects on our own Content Management System. Our system gives designers total flexibility and is very intuitive for end users, so it ends up being a good fit for just about all of our clients. However, occasionally clients come to us with a strong backend preference for certain reasons. This has happened a few times with the HubSpot CMS, due to the system's helpful business analytics and supporting community.
The HubSpot CMS wasn't originally developed for custom designs and is more geared toward the company's templates. However, with some elbow grease, you can get a custom look on there that follows HubSpot's requirements. We have now designed a couple of custom HubSpot sites (including SLX for Sun Microsystems) and put together this brief tutorial on some shortcuts to freely developing on the system.
Developing on an unfamiliar platform has it challenges, most of which is relinquishing control. For me, not having control of front-end conventions is frustrating. As a web standards enthusiast I’ve established patterns during the build-out of sites designed to minimize browser errors and cut down on development time.
So when it came time to dive in and work with the Hubspot CMS for the Yamaha Music School of Boston and Sun Microsystems' SLX, I went into the projects with the mild hesitation of having no idea what my experience would be like. Thankfully, I was pleasantly surprised with what I was able accomplish through some tricks and ingenuity. Here are a few tips and recommendations I’ve learned from my experience from using the Hubspot’s Business Website Manager:
1. Utilize the Color Scheme Configuration settings

Hubspot’s system generates a CSS styles that are placed within thebodytags, taking precedence of entire styles sheets I load to the DOM. Since the design specs I had to work with matched one of the systems page templates I thought it would be best to work within the confines of the system. This turned out to save me a lot of headaches later.2. !important important important
Everything I couldn’t accomplish within the Color Scheme Configuration I wrote into a new CSS file based on some id and class selectors created by Hubspot’s templating system. After uploading a file through the system’s File Manager and linking that file into the header using the Website Setting, I noticed some of file’s declarations weren’t rendering in any browsers. After a few minutes of digging I realized the styles were being overwritten by styles loaded further down in the cascading order. Adding ’!important’ to the end of css declaration value give it precedence over all other ‘author’ and ‘user agent’ styles, or styles created by the developer and browser:h1{font-weight:bold!important;}3. Use HTML / JavaScript to add custom code

When you need to add static content or custom images, you need to add a new page Module. Given all Module options, I recommend using plain markup. You can create things with a fresh slate and not be tied down by the templating system’s css conventions and markup. When you’re configuring your new module make sure you select the options to not use the module title and to use plain formatting. With those two items selected, you now have that clean slate to work with.If any of you are charged with developing a site on HubSpot, hopefully these tips are helpful in tackling the project. While HubSpot's system isn't ideal for totally custom designs, with some extra work, you can still put together an attractive site.
-
AutoSprites - A jQuery Menu Plugin
Update 1/22/2009 - This plugin now contains support for an active state. It is just as easy to use and all of the animation still works with it. Read below to see how it works. (This was originally posted 10/28/2009)

Download the Files (Zip) | View a Demo
We have written and released a jquery dropdown menu plugin as well as a CSS Sprites2 Plugin -- this post is along the same lines. Its purpose is to allow you to build an image-based menu with animated hover states as easily as possible and by using the most concise descriptions possible. To see the results on both a horizontal and vertical menu, check out the demo.
Setting up the jQuery Menu Plugin
The first component when doing something with sprites is a combined image that contains all menu states. For the menu above, this is the image below was used. (This was designed by Liaison Design Group, one of our Partners)

The image contains, the normal state, the hover state and the active state. The value to doing things this way is that it allows your site to load faster. Rather than downloading an image for each nav item its hover state and its active state, only a single image needs to be downloaded. This minimizes the overhead of many http requests.
The next thing to do, is set up the HTML for the nav bar:
<ul id="hnav"> <li id="hnavhome"><a href="#">Home</a></li> <li id="hnavlocal"><a href="#">Local Industry</a></li> <li id="hnavhigher"><a href="#">Higher Education</a></li> <li id="hnavcomm"><a href="#">Our Community</a></li> <li id="hnavnews"><a href="#">News</a></li> </ul>
Then we need to set up the CSS. There are a couple of things to note here. We are applying the background image to the containing element so that we don't need to respecify background positioning. This also makes the menu usable if javascript is disabled. Each element needs to have its size defined specifically as well.
#hnav { position: absolute; top: 0; left: 0; width: 615px; height: 72px; background: url('horiz_sprites.gif') no-repeat; } #hnav li { position: absolute; left: 0; height: 72px; } #hnav #hnavhome { width: 82px; left: 0px; } #hnav #hnavlocal { width: 146px; left: 82px; } #hnav #hnavhigher{ width: 162px; left: 228px; } #hnav #hnavcomm { width: 143px; left: 390px; } #hnav #hnavnews { width: 82px; left: 533px; } #hnav li a { display: block; position: absolute; top: 0; left: 0; width: 100%; height: 72px; text-indent: -9999em; }Notice how much less complicated the CSS is than what is typical with sprites. There is no need to define background positioning for each element and its hover state. The last piece you'll need to do is enable the autosprites plugin:
$(document).ready(function(){ $('#hnav').autosprites(); });There are no required options. The plugin defaults to a horizontal menu and fading for the animation. It infers everything else from the CSS. If you would like to customize things, here are the options that are available:
settings = $.extend({ offset: '100%', orientation: 'horizontal', over: { opacity: 'show' }, overSpeed: 500, out: { opacity: 'hide' }, outSpeed: 500, activeState: false, activeClass: 'active', activeSprites: false }, settings);The only bit worth explaining is the active state. In the image above, I show three states. By default, you only need two, a normal state and a hover state. If you set 'activeState' to true, it will use the hover state by default. If you want to specify your own active state, simply set 'activeSprites' to true as well.
So that's it! You can specify the minimum amount of information about your menu and the sprites will be built automatically. Be sure to check out the demo and download the zip for your own projects. As always leave a comment if you have any complements, insults, suggestions or questions.
A Special Note on Compiling Javascript
The purpose of using sprites is to minimize HTTP requests. It would be foolish to use this plugin by including jQuery, the minimized plugin, and a setup script. Instead, it is best practice on a production site to bring all of your scripts together into one file, just as sprites bring your images into one file.
-
Tutorial: A Horizontal jQuery Accordion using Custom Event Binding
This is the second of two posts about a site we recently launched for a non-profit called Striving for More. This is a great new organization that has started with the goal of improving overall care for young cancer patients. It was a fun and deserving project with a great design:
The first post was about how to build a custom jQuery Slideshow on top of some popular jQuery plugins. It covered the required html, css and js needed and it also gave a look into the through process that went into it. This post will take the same approach, but instead look at the custom jQuery horizontal accordion that is on the homepage. Unlike the last project, this one will be build without the help of any plugins. It was created entirely from scratch using jQuery custom events.
Here is a look at the final product.
What is it?
Essentially, this is a horizontal accordion that also changes the text below it on each transition. The one difference between this and a traditional accordion is that when a slide becomes active or inactive, it doesn't just shrink. Instead it slides behind the other slides. Click around on it above to see what I mean.
The HTML
The html for this project is really straightforward. There is a group of slides and a group of content:
<div id="slideshow"> <ol id="slides"> <li class="slide open" id="slide-[SLIDE NUMBER]"> <a href="[SLIDE LINK]"> <img src="[SLIDE IMAGE]" alt="" /> </a> <a class="slidebutton" href="javascript:void(0);"><img src="[SLIDE BUTTON]" alt="" /></a> </li> ... </ol> <ol id="slidecontents"> <li class="slidecontent" id="content-slide-[SLIDE NUMBER]"> [SLIDE CONTENT] </li> ... </ol> </div>
The html is in two logical groups, the slide images/navigation and the slide content. These are paired by convention using programatic id attributes. Notice that each of the image slides and the content slides has an id with the [SLIDE NUMBER] in it. This makes the javascript much simpler.
Ideally the content would be grouped in with the images. This would have made for better markup, as the related items would be put together. This would have required a lot of css positioning trickery since the content wasn't supposed to move with the slide. For the sake of overall simplicity, some html complexity was added.
The last thing worth noting here is that the slide button text is actually a rendered image. That text can't be rotated reliably in all browsers is really sad. I am confident that this will be accomplished shortly with Canvas. If you're wondering which browsers are the offenders here, you'll probably be surprised. Text can be rotated reliably in EVERY major browser except for Firefox 2.0. It even works in IE. Alas.
The CSS
The CSS for this project is probably the simplest part. You'll only notice one little quirk:
#slides { position: absolute; top: 21px; left: 22px; width: 577px; height: 285px; overflow: hidden; } #slides .slide { position: absolute; top: 0px; width: 541px; } #slides .slide img { position: absolute; top: 0px; left: 0px; } #slides .slide .slidebutton { display: block; position: absolute; top: 0px; right: 0px; height: 285px; width: 21px; background: #693d5e; text-decoration: none; border-right: 1px solid white; } #slides .active .slidebutton { background: #55354a; } #slides .slide .slidebutton img { position: absolute; top: auto; display: block; bottom: 5px; left: 5px; } /* Manually place slides to begin */ #slide-1 { position: absolute; top: 0; right: 44px; z-index: 3; } #slide-2 { position: absolute; top: 0; right: 22px; z-index: 2; } #slide-3 { position: absolute; top: 0; right: 0px; z-index: 1; }It's all straighforward except for that bit at the bottom. I've hardcoded the number of slides. This is typically something I like to avoid, but there were a couple of reasons for it on this project:
- I was assured that these slides would be unchanged for quite some time.
- At least some CSS Positioning would be required so the page wouldn't look broken while the JS loaded. By being exact there would be no jarring readjustment at all.
- It was easier.
These reasons made the decision obvious. As a quick aside and bonus, here is the css that could be used to rotate the text in CSS. Note that this depends on slightly different markup and it just won't work in Firefox 2.0. So remeber that until FFox2.0 disappears this is useless, though fascinating.
#slides .slide .slidebutton span { display: block; text-align: right; -webkit-transform: rotate(90deg); -moz-transform: rotate(90deg); position: absolute; bottom: 100px; left: -90px; width: 200px; color: #f2ecd0; font-family: verdana, sans-serif; font-size: 12px; } /* Put the following in your IE stylesheet */ #slides .slide .slidebutton span { bottom: 190px; left:2px; filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1); }The jQuery
The jQuery for this little project was the most fun. It ended up being very compact due to the intial positioning of the slides using CSS and because I used custom events.
What are custom events? In short, they are functions that you can bind to jQuery selectors. This lets you associate actions with the objects that do them, rather than with what triggers them. As an example, you could bind the event 'toggle' to a lightbulb and then trigger it from any number of switches. So if you have multiple switches, they all don't need to keep track of the lightbulb's state. They can just call toggle and the bulb will handle it. (If you like this example, don't credit me. It's borrowed from a great article on jQuery Custom Events written by Rebecca Murphey).
So here is the entirety of the jQuery code:
/* Binding Events to the slides */ $('.slide') .bind('open', function(){ if(! $(this).hasClass('open')){ $(this).next().trigger('open'); $(this).addClass('open'); $(this).animate({right: "-=511px"}); } else{ $(this).prev().trigger('close'); } $(this).siblings().removeClass('active'); $(this).addClass('active'); }) .bind('close', function(){ if($(this).hasClass('open')){ $(this).removeClass('open'); $(this).animate({right: "+=511px"}); $(this).prev().trigger('close'); } }); /* Binding Events to the Slide Contents */ $('.slidecontent').bind('show', function(){ $('.slidecontent').removeClass('open'); $(this).addClass('open'); }); /* Triggering from the buttons */ $('.slidebutton').click(function(){ $(this).parent().trigger('open'); $('#content-' + $(this).parent().attr('id')).trigger('show'); });This is certainly terse, so it is worth explaining. I'll start with the events we are binding to '.slide', open and close. To set the stage, remember that each slide is either open (navigation on the right), or closed (navigation on the left). I am keeping track of this by applying an 'open' or 'closed' class to each slide. This is a fairly standard technique.
Where things might get a bit tricky lie within how an accordion works. The visibile slide isn't the only slide that is open. The slides that come after it must be open as well (their navigation is on the right). So when the second slide is active, the first must be closed and the second and third must be open. This problem gets handled with a little big of recursion.
The Event Binding
Let's look at the close event, as it is the simpler of the two. When we close a slide, we first check that it is open. If it is closed, there is nothing to do. If it is open, we close it and then close the slide immediately to its left. This repeats until there isn't a slide to the left or it reaches a slide that has already been closed.
The open event is only a little more complicated. It works in the exact same way as the close event, except trickles to the right. It also updates which slide is active at each stop along the way.
Finally you can see how the 'show' event is bound to the slide contents. All this does is remove an open class from every slide content, and then add it back to the one that has been triggered.
As you can see, a lot of complexity has been encapsulated under these events. This makes it really easy to jump to a particular slide. All that needs to happen is to trigger the 'open' event on the desired slide and the 'show' event on the correct content. This is exactly what the '.slidebutton' code does.
Putting it all together
With all of the pieces in place you can see it in action below. Be sure to leave any questions or comments you have about this in our comments below.
-
Tutorial: A jQuery Slideshow for a Good Cause
We recently launched a site for a new non-profit called http://www.strivingformore.org" target="_blank">Striving for More. The project was a lot of fun. The site is great-looking, has some cool features, and more importantly it was for a good cause.
In this post, I am going to cover one of the more important features of the site: an interactive gallery that tells Colleen's Story. I'll breakdown how it was built and the reasons for doing some of the things the way I did. It ends up being very simple and a great example of the power that can be had by combining and tweaking jQuery plugins.
Here is the final product so you can see where this is headed:
What is it?
Colleen's Story is a simple slideshow that can be navigated in any order with an introduction screen. Each slide has a nice navigation button, some narrative and a cool graphic. Because we didn't want the navigation to move around, the content needed to scroll in place, another requirement. For something that looked this good,
overflow: auto;wouldn't cut it. After doing some looking around, I decided to use the following plugins for the project:- Cycle - This is one of my favorite plugins. If you haven't checked it out you need to. With some improvments that have come in the last 6 months or so it is the only plugin you'll ever need for rotating content. We've rolled our own cycle-like jquery code in the past, but that is rarely necessary. On this project, Cycle will handle all of the slide transitions as well as the navigation.
- jScrollPane - I'm not generally a fan of replacing the default behavior of browsers, but this situation required it. I played around with serveral plugins before settling on this one which seems to have the fewest downsides.
The HTML
To use these plugins will require that we structure our html in a certain way. Here is how it is setup:
<div id="gallery"> <div id="gallery-intro"> [Introduction Content] <a href="javascript:void(0);" id="startslides">Begin</a> </div> <div id="gallery-slides" class="hidden"> <ol> <li id="slide-[slidenum]"> <div class="slide-content"> <h2>[Slide Title]</h2> <div class="scroll-content"> [Slide Content] </div> </div> <img class="slide-image" src="[Slide Image]" alt="" /> </li> ... </ol> </div><!-- gallery-slides --> <div id="gallery-nav"> <ol> <li id="slide-1-nav">1. Monkey</li> <li id="slide-2-nav">2. Necklace</li> <li id="slide-3-nav">3. IV Beads</li> <li id="slide-4-nav">4. Bag</li> <li id="slide-5-nav">5. Blistex</li> <li id="slide-6-nav">6. Notebook</li> <li id="slide-7-nav">7. Pink Hair</li> </ol> </div><!-- gallery-nav --> </div><!-- gallery -->
There are some things to point out here:
-
The Gallery Intro
Before the slideshow is shown, a description of its purpose is shown. This is grouped independently of the slides. The plan is to make this disappear once the slideshow is started.
-
The Navigation
Cycle provides a navigation (pager) generator. For this project I wanted to have all of my html in one place and give good text descriptions for each slide. Having this dynamicly match the number of slides didn't matter either because these were set in stone. Instead, I just used an id attribute convetion so I could write some simple javascript to link the navigation to the slides.
-
Scroll-Content Class
I wrapped the content of each slide in a container with the class "scroll-content". This is so that we can target it if necessary using the jScrollPane plugin.
The group of slides
All Cycle asks for is a group of slides that are children to one element. In this case it is the ol. We'll end up calling cycle on "#gallery-slides ol". Also notice that I have given this the class "hidden". I do this so that I can hide the slides with css rather than javascript. This is important to do, otherwise while the page loads they will flash.
The CSS
A concern with this site due to the texture used was download size. While the end result is not perfect, it was taken into consideration when putting this together. The overall strategy was to use one background image for the slideshow frame and let the slide text, images and navigation float over it. One concession was to also include some of the background in the slide images. While this made for some redundant information, the use of jpg compression instead of a 24-bit or even 8-bit png more than made up for it. Finally, sprites were used for the navigation.
Here is the major layout css:
/* Container */ #gallery { position: relative; width: 696px; height: 494px; background: url('gallery-background.jpg'); } /* Intro Container */ #gallery-intro { position: absolute; top: 8px; left: 9px; height: 268px; width: 459px; padding: 70px 110px; font: italic 16px Georgia,serif; color: #1e5584; line-height: 32px; text-align: center; } #gallery-intro strong { color: #bc9906; display: block; font-weight: normal; } #startslides { width: 116px; height: 30px; display: block; margin: 20px auto; background: url('gallery-begin.jpg'); text-indent: -9999em; } /* Slides */ #gallery-slides { position: absolute; top: 8px; left: 9px; height: 408px; width: 679px; overflow: hidden; background: transparent; } #gallery-slides ol { position: absolute; top: 0; left: 0; list-style: none; margin: 0; padding: 0; width: 679px; height: 408px; background: transparent; } #gallery-slides ol li { width: 629px; height: 338px; padding: 25px; } /* Slide Components */ #gallery-slides .slide-content { width: 340px; padding-right: 20px; height: 338px; line-height: 18px; z-index: 2; } #gallery-slides .scroll-content { overflow: auto; width: 320px; padding-right: 20px; height: 315px; } #gallery-slides .slide-content p { margin: 6px 0; } #gallery-slides .slide-content h2 { margin: 0px 0 6px 0; font: italic 25px Georgia,serif; color: #bc9906; } #gallery-slides .slide-image { position: absolute; bottom: -25px; right: 1px; z-index: 1; }The quick things to notice are:
- The container is positioned relative so that everything else can be placed absolute inside of it.
- ".scroll-content" has overflow set to auto. This is required for the jScrollPane plugin.
The navigation was also positioned absolute and set up with a basic CSS sprites technique. You can see the image used here. I am using '.on' in addition to the ':hover' pseudo-class so that we can get the hover states to work in IE6 using javascript. You can get more information on this technique in detail in a classic article on A List Apart. For those of you interested in using the technique for navigation menus, I've also written a plugin to make that dead simple called jQuery AutoSprites.
#gallery-nav { position: absolute; top: 425px; left: 8px; width: 680px; height: 50px; } #gallery-nav ol { position: absolute; margin: 0; padding: 0; top: 0; left: 0; width: 680px; height: 50px; background: url('gallery-sprites.jpg'); } #gallery-nav ol li { list-style: none; margin: 0; padding: 0; position: absolute; top: 0; left: 100px; width: 85px; height: 50px; text-indent: -9999em; cursor: pointer; cursor: hand; } #gallery-nav ol li.activeslide, #gallery-nav ol li.hov { background-image: url('images/gallery-sprites.jpg'); } #gallery-nav #slide-1-nav { left: 0px; width: 100px; } #gallery-nav #slide-1-nav.activeslide, #gallery-nav #slide-1-nav.hov{ background-position: 0px -50px; } #gallery-nav #slide-2-nav { left: 97px; width: 100px; } #gallery-nav #slide-2-nav.activeslide, #gallery-nav #slide-2-nav.hov { background-position: -97px -50px; } #gallery-nav #slide-3-nav { left: 194px; width: 100px; } #gallery-nav #slide-3-nav.activeslide, #gallery-nav #slide-3-nav.hov { background-position: -194px -50px; } #gallery-nav #slide-4-nav { left: 291px; width: 100px; } #gallery-nav #slide-4-nav.activeslide, #gallery-nav #slide-4-nav.hov { background-position: -291px -50px; } #gallery-nav #slide-5-nav { left: 388px; width: 100px; } #gallery-nav #slide-5-nav.activeslide, #gallery-nav #slide-5-nav.hov{ background-position: -388px -50px; } #gallery-nav #slide-6-nav { left: 485px; width: 100px; } #gallery-nav #slide-6-nav.activeslide, #gallery-nav #slide-6-nav.hov { background-position: -485px -50px; } #gallery-nav #slide-7-nav { left: 582px; width: 100px; } #gallery-nav #slide-7-nav.activeslide, #gallery-nav #slide-7-nav.hov { background-position: -582px -50px; }The Javascript
Since our plugins come with quite a bit out of the box it is really simple to get the jQuery running. The first step was to handle the items hidden by css I described above. We can do this right away since the javascript will execute quickly once it gets going as it will be replaced bya jQuery hide.
$('.hidden').removeClass('hidden'); $('#gallery-slides').hide();Next I got the navigation hover states working in IE6 which needs javascript since it doesn't recognize the :hover psuedo-class on non-anchor elements.
$('#gallery-nav ol li').hover( function(){ $(this).addClass('hov'); }, function(){ $(this).removeClass('hov'); } );Next was the simple step of enabling jScrollPane. Don't forget to set these containers as overflow:auto in the css too.
$('#gallery-slides .scroll-content').jScrollPane({ scrollbarWidth: '10' });Setting up a jQuery Cycle is easy, but there was a trick needed for IE. Because I used the fade effect, Cycle sets a background color during the transition to get the text fading to work correctly. I reset this to transparent once the transition is over using the after callback. While this may seem like a pain, little features like this are part of the reason to use established plugins over something homegrown.
$('#gallery-slides ol').cycle({ timeout: 0, fx: 'fade', after: function(){ $('#gallery-slides ol li').css('background', 'transparent'); } });The last step is adding the custom navigation features. You'll notice that the id of the nav item is used to figure out which slide to show. I also set up the swap between the intro and the slides to occur if either the navigation or "Begin" button is pressed.
$('#gallery-nav ol li').click(function(){ $('#gallery-slides').fadeIn(); $('#gallery-intro').fadeOut(); $(this).parent().children().removeClass('activeslide'); $(this).addClass('activeslide'); var slidenum = Number($(this).attr('id').substr(6,1)) - 1; $('#gallery-slides ol').cycle(slidenum); }); $('#startslides').click(function(){ $('#gallery-slides').fadeIn(); $('#gallery-intro').fadeOut(); $('#slide-1-nav').trigger('click'); });Conclusion
So that's it. Once again you can check out the final product on the Striving for More site. Next week I'll post a tutorial about how the homepage slider was done entirely from scractch. If you want to read about that when it comes out, you should subscribe to the blog.
-
Season's Greetings and Happy New Year from the NMC Team!
With the holiday season and a lot of projects wrapping up, it's been rather quiet on the blog for the past few weeks. Just wanted to wish all of our readers a Happy 2010 and thank them for their support over the past year. Below is a blast email we sent out to clients earlier today. One of our priorities in 2010 is to send quarterly updates to our clients, readers, and others. If you'd like to receive these, please fill use the form in the sidebar to receive our newsletter.
Season's greetings and happy New Year from the NMC team!
2009 was a fun and busy year at New Media Campaigns. Our team doubled in size, we launched over 100 sites, we recommitted to our blog, and we even had two people get engaged! Through all of these happenings, we were proud to be able to stay true to our core principles of quality work at affordable prices with great service.
However, we recognize none of this would have been possible without your support, feedback, and business. We truly appreciate it all, and we want to wish you a happy holiday season and a joyous 2010!
Below are some more highlights from the past year. We look forward to making 2010 an even bigger success!
Best,
The New Media Campaigns Team
PS - To keep up with our daily happenings in 2010, follow us on Twitter, join our somewhat lonely Facebook page, and subscribe to our Blog.
NMC News Highlights from 2009
NMC Team Grows to 7 and Launches 350th Site
Featured across Web for jQuery Tools
Highlighted Sites from 2009
Looking Forward to 2010
Quarterly Email Newsletter
Updated NMC Website Design and Layout
-
Use HTML5 form attributes now with nmcFormHelper plugin for jQuery
Inayaili de León's post last week on 24 ways reminded me about some of the new attributes that HTML5 will be adding to the
<input>element. In addition to the flashy new input types (search, color, date, etc.), there are several more mundane, but just as useful, new attributes that can be used on the input types we already have. I created a small jQuery plugin that checks if these attributes are supported natively, and if not it adds support via JavaScript. See an example, or continue reading for the full explanation.PlaceholderA common trick is to set the value of a text input to a short hint about the type of information that should be entered there. Then a couple lines of JavaScript are used to clear that value when the user clicks or tabs into the input. Although there are usability issues with this technique, its convenience is hard to resist. The HTML5 spec includes a new
placeholderattribute that creates the same effect without the usability problems.To Use:
<input type="text" name="name" id="name" placeholder="Enter your first and last names" />
AutofocusWhen the primary purpose of a page is the form—a login page, for instance—it is helpful to start out with the focus on the first input, so the user can just start typing. You can use the new
autofocusattribute on the first element to do that. (Be careful, though: setting autofocus on a non-essential form, like a comment form, can be very annoying.)To Use:
<input type="text" name="name" id="name" autofocus="autofocus" />
RequiredSetting the
requiredattribute prevents the form from submitting unless the input has some value.To Use:
<input type="text" name="name" id="name" required="required" title="This is required" />
PatternThe
patternattribute lets you set a regular expression pattern that must be matched by the input value before the form can be submitted. This is a very powerful tool, allowing for complex validations. Our HiFi RexExp Tool will help you create regular expressions that test for anything from credit card numbers to urls. You should also read the HTML5 spec on the topic, as there are a few caveats. In particular, be aware that the pattern matches the entire value by default, and you should not wrap the expression in forward slashes.To Use:
<!-- Only accept US zip codes -->
<input type="text" name="zip" id="zip" pattern="(^d{5}$)|(^d{5}-d{4}$)" title="US zip codes only" />Using the Plugin
Some or all of these new attributes are supported by both Safari and Opera. But Firefox and Internet Explorer do not support them natively at this time. To be safe, the nmcFormHelper plugin checks for availability of each attribute (using a technique suggested by Mark Pilgrim) and, if it doesn't exist, uses JavaScript to emulate support.
At a minumum, you just need to include my script and place a single line in your $(document).ready() block:
nmcFormHelper.init();. That will set up all of the new attributes, and you're ready to go.Options
- Placeholder styling: The placeholders are styled to match the native placeholder functionality in Safari. If you wish to set a different style, you can set
nmcFormHelper.placeholder.styling = {'color':'red','font-style':'italic'};or whatever look you choose. - Validation functions: The
requiredandpatternattributes will prevent form submission and display an error if the value does not exist or does not match the pattern. By default, a new label will be added after each invalid input, containing thetitletext of the input. But you can write a function to do anything you want! Just override the functionsnmcFormHelper.validation.showErrorsandnmcFormHelper.validation.hideErrors(the latter function should undo the former). Both functions will be passed a jQuery object containing all the elements that are affected. Each element will also have one or both of the classes "requiredError" or "patternError" set.
Bonus!
Since Internet Explorer does not support CSS attribute selectors, it can be hard to style a text input, for instance, without screwing up your buttons, or vice-versa. So the plugin also adds a class to each of your inputs containing "input-" and the type of the input (i.e. "input-submit"). That way, you can style them individually.
See an example
Get the Code
- Placeholder styling: The placeholders are styled to match the native placeholder functionality in Safari. If you wish to set a different style, you can set
-
The Complexity of Simplicity
'Simplicity' is often the protagonist in product design lore. Perhaps too often. Simplicity is deceptive. Simplicity isn't always the good guy, and many of its best showings aren't simple at all.

Take Google, for example. Its user interface is undeniably simple. In a recent experiment it is as simple as a logo and a text box. No submit button. No links. No "I'm feeling lucky". No advertisements. The web's most popular application has the simplest design.
Very little about Google though, outside of user interface design, is simple. Google is the web's most complex application. Feel the dissonance? The most complex web app has the simplest interface. This is a key trait of 'good simplicity': leverage.
Leverage is simple with a purpose. Leverage as in mechanical advantage, not Lehman Brothers. The ability to do more with less, not less with less. Simple not as in simple stupid, but as in simple machine. Good simplicity moves the fulcrum closer to the load. Bad simplicity removes the fulcrum all together.
Good simplicity restricts user input to multiply its value. On one end of the Google machine you type in words, on the other end of the Google machine you get a list of the web pages most relevant to those terms *from across the entire internet*. On one end of the Twitter machine you type 140 characters, on the other end everyone on the internet who cares about what you're saying receives it. On one end of the iPhone machine you stretch your fingers out, on the other end a map of the entire world zooms in.
The iPhone is another icon of simple design. Its face has one physical button. One button. This beautiful simplicity is achieved through patentable complexity: a multitouch screen. When the iPhone was introduced it was both the world's simplest smart phone and its most technologically complex. The 'simple' capacitive touch screen leads us to another key trait of 'good simplicity': complexity disguised.The face of an iPhone really has 153,601 "buttons". Only one of them can be pressed reliably: the one that isn't on the screen. The other 153,600 are points on the screen so small that when a single finger touches it tens to hundreds of them are pressed at once. Specialized hardware and algorithms then turn this large amount of noisy input into the single point on the screen your finger was aiming for. Somehow it works and the result of this complexity is an interface that feels natural and familiar. It feels simple.
Good simplicity disguises necessary complexity. Bad simplicity labels all complexity as unnecessary and throws it out the door. Google could have chosen not to accept misspelled words, they could have created a separate app for solving mathematical expressions, multilingual searches, etc. These are all complex problems Google solved not by avoiding them, but by disguising complexity to make us believe it's just as simple as every other search.
Simple can be a siren just as easily as it can be a signal. Good simplicity is less with leverage, not less with less. Good simplicity is complexity disguised, not complexity denied. Don't give in to stupidity when creating simplicity.
-
Designing for the mobile web
Devices and Platforms
New Media Campaigns recently launched a mobile version of its website. When I was first approached with this project, Joel Sutherland and I debated how we should develop the mobile website. Should we develop a mobile website only for Apple, Inc.'s iPhone? Or should we develop a mobile website for as many mobile devices as possible?The mobile web has surged in popularity lately with help from the iPhone. The iPhone has been a tremendous success, and it has propelled web standards into the main stream thanks to its adoption of the Webkit platform. Other recent smart phones and mobile devices have also adopted the Webkit platform, such as Verizon's Droid and Palm's Pre.
Joel and I decided to target the Webkit platform rather than a single device. The Webkit platform provides a nice breadth of device coverage and a surplus of advanced web development features, such as web standards and CSS3 support. As a result, we were able to leverage advanced CSS properties such as
border-radius,text-shadow, and more. Of course, these properties will degrade gracefully in less-advanced web platforms. In an earlier blog post, Joel describes how we targeted specific devices that support the Webkit platform.Simplify, simplify, simplify
A smart phone is small compared to a desktop web browser. The Apple iPhone and Palm Pre provide a 320x480 screen. The Verizon Droid provides a slightly larger screen. With such little space, it is imperative to provide a good user experience with a simple and easy to use interface that provides only the most important information.
While designing our mobile website, I filtered our primary website into four distinct categories: Home, Work, Blog, and Contact. These categories were translated into tabs, a global layout element that resides at the top of every page on our mobile website. Tabs are an immediately identifiable and easy to use form of website navigation.
The "Home" tab provides a brief description of New Media Campaigns, with links to recent blog posts and an about page. There is also a link that will initiate a phone call and a link that will initiate an email.
The "Blog" tab provides the best example of simplification. Unlike our primary website, we do not use categories or tags on the mobile website. Instead, we provide a single paginated stream of blog posts. The listing view provides the title, excerpt, and number of comments for each blog post. Viewing an individual blog post also allows the mobile website visitor to read existing comments or leave a new comment. Ultimately, our mobile website provides a simple, usable, informative blog that provides exactly what is needed and nothing that is not.
The "Contact" tab provides only what is necessary to contact our web design agency: a simple HTML form and a link to initiate a phone call.
Our mobile website is simple and easy to use. It provides the most important information in an accessible format. This is perfect for mobile website visitors who are usually on the go, in a hurry, and need important information fast.
Device agnostic, platform centric
In my opinion, the future of mobile web-enabled devices is Webkit. Webkit provides a stable, standards-compliant, and forward-thinking platform that is being adopted by the most popular mobile devices, including Apple Inc.'s iPhone, Verizon's Droid, and Palm's Pre. RIM recently posted a job listing for a Webkit developer... perhaps a future Blackberry will also support the Webkit platform.
Our mobile website works in any Webkit-enabled mobile device, in portrait or landscape orientation. If an end-user visits our website in another device, the same information will still be accessible; we used simple, clean, standards-compliant XHTML markup to structure our mobile website. This ensures the information will still be readily accessible to any device that can adequately parse HTML.
-
Following content management's core concepts with your CMS
Content Management is nothing new, but it does have its fair share of growing pains as it relates to the web. With the number of options readily available, it is easy for designers, developers and clients to lose sight of content management's core principals:
- Sorting 'Stuff' — content defined by an end-user — into a content repository.
- Support the workflow of the end-user.
The web community has the first principal down thanks to relational databases, but we really struggle with the second. Since the end-user can vary from an individual with varying skill sets to a large corporation with endless resources, demands on a Content Management Systems and its specific workflow have create countless options in the marketplace.
With each options comes a list of pros and cons, fanboys and detractors which ends up creating some misconceptions. Here are some misconceptions I've read repeatedly in the last few weeks that neglect to take these core principals into account:
One type of system is better than other.
Is it better to go open source, third-party or proprietary system? Truthfully, there is no right answer because each option can meet your goal of publishing content to the web but could create a potential workflow nightmare.
I use to advocate for using third-party software. I preferred working with a system that offered continuing support thanks to its customer base. If I was unable to continue to help client with maintenance there was always someone within the community. Now a client would never feel like they've wasted their investment on piece of technology.
That philosophy helped me in large part but I'm not sure it was in my clients best interest. When I started using other technology that better suited their workflow needs, I found myself getting more projects in the long run. Just because a company can afford an expensive system doesn't mean Wordpress isn't the best solution for their needs.
With the volume of clients and sites we work on, our proprietary system has proven the best option over time and I realized that within my first few days here.
CMSs should be more open to customization.
I think there is a false perceptions in the title 'Content Management System.' People seem to infer that they should have more control over the system itself and this can lead to people neglecting the content itself. Not all systems are created equal, so you can't be under the assumption any system will meet your needs.
If you feel like your system can't be customized, you have either chosen a system that doesn't fit into your workflow or you didn't define your content before development began on your system (I'll discuss defining your content in a future post). By ignoring your content from the start, you won't have a clear understanding of the work needed to publish your content and you will feel limited by any system.
Buying into a system means that you are committing to a set of standards, like a fixed design, so that you can produce and manage content quickly be streamlining your workflow. If you can't conform to any set of standards, moving to a CMS isn't in your best option.
I don't need to learn HTML now that I have a CMS.
The point of moving to a CMS is to avoid coding and/or reduce the reliance of a developer to speed up your publishing process, creating a better workflow. So why would I have to learn HTML when I have a WYSWYG editor to do the work for me?
You don't.
While there is no need to learn the syntax of a web language like HTML still you need to have an general understanding of how it works. You need to realize that pasting source code info your CMS from an e-mail newsletter is going to break your page in all likelihood. You need to realize when something is outside of the workflow of publishing content.
CMSs are bad for SEO
This goes back to the same ideas with customization: If you don't make SEO part of your workflow and create/use a system with it in mind early, it's going to make it harder to have good SEO. If that's the case, is it the systems' fault or yours?
Conclusion
The success of any CMS is tied to its ability to conform to your workflow. Most complaints with specific systems can be drawn to the fact they weren't developed with your particular workflow in mind. After all, the end goal of using a system is to publish and management content easily and quickly. Most systems can accomplish that, which is align with the first principal.
Having only worked with our in-house system for a few days, I can tell the team put careful thought into the workflow and it seems to be paying dividends.
-
Three Ways to Target Mobile Devices

We recently launched a beta version of a New Media Campaigns mobile Webkit site. If you're reading this post from an iPhone, iTouch, Palm Pre or Android based phone you're seeing it right now. Josh Lockhart did the design and frontend code for the site, a topic he will be covering in a post later this week.
This post discusses how to target mobile devices and show them either different content, different stylesheets or even redirect to a mobile URL. Ideally, the check would be done for ALL mobile webkit platforms, not just the iPhone. It would be a shame to leave those Android/Palm out after developing a pretty mobile site. So without further ado, here are the methods:
1. Checking User Agent Serverside
When a browser visits a site, it sends a string describing who it is called the user-agent string. It varies depending on the browser and platform. The user-agent string for key mobile webkit browsers are:
iPhone - Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko) Version/3.0 Mobile/1A543a Safari/419.3 iTouch - Mozilla/5.0 (iPod; U; CPU like Mac OS X; en) AppleWebKit/420.1 (KHTML, like Gecko) Version/3.0 Mobile/3A100a Safari/419.3 Android - Mozilla/5.0 (Linux; U; Android 0.5; en-us) AppleWebKit/522+ (KHTML, like Gecko) Safari/419.3 Palm Pre - Mozilla/5.0 (webOS/1.0; U; en-US) AppleWebKit/525.27.1 (KHTML, like Gecko) Version/1.0 Safari/525.27.1 Pre/1.0
Unfortunately there is not a good way to check for mobile webkit in general. So each of these needs to be checked for in a case by case manner. Here is some rough php to do that:
if( strstr($_SERVER['HTTP_USER_AGENT'],'Android') || strstr($_SERVER['HTTP_USER_AGENT'],'webOS') || strstr($_SERVER['HTTP_USER_AGENT'],'iPhone') || strstr($_SERVER['HTTP_USER_AGENT'],'iPod') ){ // Send Mobile Site }We did this type detection since we wanted to send completely new templates for pages at the same URL. This worked nicely with our CMS since both the normal frontend and the mobile fronend were updated from the same database. We could also use this technique to redirect to a mobile URL if that is how we wanted to present our mobile site.
2. Checking User Agent Clientside
This method simply uses javascript to check the User Agent after the page has loaded. The obvious downside is that it first requires mobile visitors to load your standard site which might be fairly heavy. It is fine to use in a pinch where you are not able to modify server-side code.
Here is some javascript to detect the mobile webkit browsers:
if( navigator.userAgent.match(/Android/i) || navigator.userAgent.match(/webOS/i) || navigator.userAgent.match(/iPhone/i) || navigator.userAgent.match(/iPod/i) || ){ // Send Mobile Site }You can use this method to either redirect to a different site, send a different stylesheet or whatever else you may need to do for a mobile site.
3. Use CSS Media Type
If your HTML doesn't need to change between your mobile site and standard site, it may make more sense to send a different stylesheet just to mobile browsers. There are a couple of ways to do this, but using the media type capabilities of CSS may be the way to go.
To load an entirely different stylesheet, use the media attribute when loading the stylesheet:
<link href="mobile.css" rel="stylesheet" type="text/css" media="only screen and (max-device-width: 480px)" />
Alternatively you can just add some declarations into your existing stylesheet:
@media screen and (max-device-width: 480px) { /* mobile declarations */ }This method is a little dangerous since it depends on the screen resolution to send the stylesheet. A mobile site is generally not different from a typical site because of resolution alone; it is also different because of the physical screen size of the device. For instance, the new Verizon Droid has roughly the same screen dimensions of the iPhone but a resolution of 854px by 440px! Serving a mobile site to this device makes sense even though it has such high resolution.
If you've done a mobile site and have a perferred method be sure to share the site and the method in the comments.













Network with Us