I don’t usually do this, but let me share my thoughts about a book I’ve read recently.
Mike Monteiro’s Design Is a Job is a brilliant book. A must-read for pretty much every single person in this industry and for many, many others too. Even for our clients. It is so true and straightforward, you just can’t find these things put in a better or simpler way.
I can’t count how many times I thought “So true.” or “Damn right!” while reading the book. Even though I’m not even close to the author’s experience, in my short proffessional career I have had so many situations when I thought and acted like he says (and those were good decisions and actions to make) or when his advice would help me a lot.
I’m not going to review every chapter, but let me give you a few of my favorite quotes from the book.
“Never work for free. Any work you take on for free will get pushed aside for paying work. That does neither you nor the client any favors. Neither of you will respect each other’s time. (…) Let the client know the value of what they’re getting.”
“if you hand a client an estimate and slap them across the face and they complain about the slap, then the estimate wasn’t high enough.”
“The problem with designers isn’t that they don’t know how much to charge; it’s that they’re afraid to charge it!”
“No one is going to value your work, or your time, if you don’t.”
“The secrets to getting the price you want for your work are having done the homework to know you’re asking for the right thing, the confidence to ask for it, and the willingness to walk away when you can’t get it.”
“And sit back. Relax. It’s important that you’re relaxed when reading client feedback. Open your mind to the possibilities that you might be going on a journey. Client feedback has a way of taking you to places you never dreamed you’d go.”
(What a nice way to say You’ll be pissed. So pissed, you have never imagined you could be.)
The book is packed with such short and accurate advice that can save you a lot of trouble, make more money and make you and your client happy.
I love Mike Monteiro’s work and thinking since his appearance on the Pipeline and his Fuck you. Pay Me. talk.
Read Mule blog and listen to his podcast with Katie Gillum from the beginnings on the 5by5 network and you’ll see Erik Spiekerman is right saying “Mike Monteiro is known as a straight talker. He is a living bullshit detector and will not suffer fools.” And this book is his priceless knowledge from years of experience, condensed and put straight in your face. You just can’t miss it or ignore it.
Now go read the book.
Several random thoughts and notes after a few mobile projects I worked on recently.
If you expect images too big for a small screen, you might want to make sure they always take a new line and are not floated with text:
img {
display: block;
max-width: 100%;
height: auto;
margin: 10px auto;
}
display: block; ensures line break before and after all images and removes white space following inline elements.max-width: 100%; ensures that image won’t take more than 100% of available horizontal space.height: auto; keeps the right aspect ratio when scaling image. You don’t need this one if you don’t define width and height with HTML attributes.margin: 10px auto; – centering image if it’s not big enough to fill all horizontal space.Consider using different responsive images options to serve the right image resolution to your site’s visitors.
Let’s say you want your form fields take 100% horizontal space. Fixed width defined in pixels is not an option, using media queries won’t be perfect either. Use width: 100%; with box-sizing.
input[type="text"] {
width: 100%;
padding: 5px;
border: 1px solid #ccc;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
Box-sizing is widely supported and super useful in mobile projects - use it!
To get rid of default iOS form fields styling you can use -webkit-appearance: none; but that’s not enough for <input type="number" /> field.
Even though spin buttons are hidden, you will notice width: 100%; for text input is not the same as it is for number input. That’s because the spin button is not visible, but it’s still there… kind of. Reset margins and you’re good to go.
input[type=number]::-webkit-inner-spin-button,
input[type=number]::-webkit-outer-spin-button {
margin: 0;
}
I’ve seen this a couple months ago, looks like it’s fixed in iOS5.
Use word-wrap: break-word; for long links and situations where you expect long strings without spaces. They can cause horizontal scroll on small screens, and this usually is not a good experience.
Tables with more than just a few columns are not very easy to read on small screens.
If possible, try to linearize tables, make them look more like a list if only your data stays easy to read and understand. It depends on situation, but you can always experiment with display: block; on table cells and rows, hide empty cells with td:empty { display: none; } and so on. Whatever works for you, but don’t forget about accessibility.
Here’s Chris Coyer’s take on this topic and how it affects accessibility.
HTML5 video and audio are great on desktop but when it comes to mobile, consider a different approach. Turns out using just a link to a video file is the easiest solution. As always it depends on your project and supported devices, but if you’re only aiming to relatively modern platforms, let’s say iOS, Android 2.2+ and Blackberry 6.0+, tapping on a link to a .mp4 video file will open a full-screen native video player and this, I think, is the best video experience you can get on a phone.
One thing to remember. Media source file can’t be stored on a password protected domain, even if it’s the same as the web site and you have already logged in. It doesn’t make a difference to iOS, but Android and Blackberry just won’t play it and keep saying the media file can’t be played/found/etc.
Your desktop website can use lots of fancy jQuery plugins to make everything jump and dance but make sure you don’t do that on your mobile site. And if you don’t use them, don’t load all the JavaScript files. Use JS media queries and scripts like LazyLoad.js or yepnope.js to load your code only when it’s needed.
The latest jQuery version, 1.7, is 92KB minified, so really, don’t make me download it to see your fancy carousel, please.
If you really need jQuery-like syntax, go for Zepto.js – a brilliant little framework for mobile WebKit browsers. You probably won’t even notice it’s not jQuery. If you only want to access DOM with CSS selectors, use querySelector and querySelectorAll, all browsers support them!
There’s also a bunch of other micro-frameworks to help you not use jQuery to do the most basic tasks.
Great library to add position: fixed; support to mobile devices. Works well most of the time and is easy to use, but when it comes to more complex and JS-heavy content it might get pretty nasty.
With current version (iScroll 4) you need to make sure on your own if form fields are still usable, as the library uses event.preventDefault() on all touched elements, thus making form fields not receiving focus. Using event.stopPropagation() on touchstart and mousedown events in your loaded function should help, but sometimes you may even need to use iScroll’s destroy() method and initialize it again every time user taps on a select field. It’s as bad as it sounds and performance can suffer.
function loaded() {
myScroll = new iScroll('wrapper');
$('select').bind('touchstart', function(e){
myScroll.destroy();
setTimeout(function(){
myScroll = new iScroll('wrapper');
}, 500);
});
$('input, select')
.bind('touchstart', function(e){
e.stopPropagation();
})
.bind('mousedown', function(e){
e.stopPropagation();
});
}
iScroll needs to be refreshed every time you do anything that changes height of the content like showing, hiding or adding new elements. As basic thing as accordion worked terribly slow for me on iPhone 4 even thought it couldn’t be any simpler than just adding and removing class from a few elements with no animation.
img { height: auto; } will break iScroll because document height calculation gives wrong results, so when all images are loaded you need to refresh iScroll again.
All that said, think about this: if you need fixed header or footer on your site, just use position: fixed; in CSS and forget about JS for this stuff. Latest Android supports it (I guess?), iOS5 supports it too, even if it’s buggy, it should be good enough for basic use. iOS5 can be installed on iPad, iPod Touch and iPhones starting with 3GS, so it’s a majority of iOS users.
Or maybe not? Brad Frost on fixed positioning in mobile browsers.
Swipe left and right through history with jQuery Mobile:
$('body')
.live('swipeleft',function(e){
window.history.back();
e.preventDefault();
})
.live('swiperight',function(e){
window.history.forward();
e.preventDefault();
});
html { overflow-y: scroll; } used in 320 and Up breaks select fields on Android when used with jQuery Mobile. This happened only to selects not visible in the viewport right after page load. Remove that rule and it should be OK.
You can spend most of the time developing in a narrowed desktop Safari window, but sooner or later you’ll need to test your work on mobile devices. Most likely you don’t own a couple smartphones just for teting, so you need another way to do it.
If you’re lucky enough to work on a Mac you should download Apple SDK with iOS Simulator, which is the best simulator available. You can test on the latest iOS versions on both iPhone (also Retina display) and iPad.
There are Opera Mobile Emulator and Opera Mini Simulator, both work pretty well for doing some quick checks.
When it comes to Android and Blackberry… yes, there are simulators, but I say they’re good candidates for the worst software I’ve ever used. Both work terribly, require a fairly strong machine to even start, and if you’re lucky (or not) to run it, you can forget about experiencing anything even close to a real device.
Update: I started testing on the latest BB 7.0 simulator recently and must say it’s not that bad anymore.
Each one of these tools deserve a longer testing and a separate blog post, so just a short note here.
Web Inspector Remote, now a part of PhoneGap. Lets you use the Web Inspector you know from Safari and Chrome browsers to remotely debug your projects running on mobile devices or simulators. Really easy to use, especially on a Mac. A little buggy, sometimes it can’t render the whole DOM properly, but I believe it’s going to get better eventually. Recommended.
Similar to Weinre but looks way better. Built with Node.js and Socket.IO, supports iOS, Android & WebOS. Definitely worth checking.
Another remote JavaScript debugger for iPhone/Android/WindowsPhone7 build with Node.js.
A multi-platform mobile environment emulator as a Chrome plugin. Targeted towards PhoneGap, WebWorks, WAC, Opera, mobile web development and testing.
Profile and inspect web applications running on iOS Simulator
Yeah, I’m pretty late with this, but here’s a nice way to hide the url bar on iPhone: window.scrollTo(0, 1);.
Update: Doing it right
<ul id=”contents”>
<li><a href=”#chapter1”>Chapter 1</a></li>
<li><a href=”#chapter2”>Chapter 2</a></li>
<li><a href=”#chapter3”>Chapter 3</a></li>
</ul>
#contents a::after {
content: leader('.')
target-counter(attr(href), page);
}
Via Håkon Wium Lie at Fronteers 2010
@page {
size: letter;
marks: crop cropss;
margin: 2.54cm;
}
@page:left {
@bottom-left {
content: counter(page);
}
}