Hola:
Pues eso de estar optimizado habría que discutirlo, y sobre un número grande de campos, si son del mismo tipo con un bucle y pocas florituras se puede validar de manera optima, y solo con una alerta (lo de los colores también sería fácil...
Un ejemplico sencillo:
var obligatorios = ["nombre", "telefono", "mensaje"];
function validar(f) {
var erroneos = new Array();
var mensajes = new Array();
for (i = 0, total = obligatorios.length; i < total; i++) {
if (f[obligatorios[i]].value == "") {
erroneos.push(obligatorios[i]);
mensajes.push("debe rellenar el campo " + obligatorios[i]);
}
}
if (erroneos.length > 0) {
alert(mensajes.join("\n");
f[erroneos.pop()].focus();
}
return (mensajes.length == 0)
}
Para validaciones algo más complejas, bastaría con usar la idea del post de
_cronos2
Por cierto, el código lo puse "a capella", pero se puede ver que es bastante sencillo...
Saludos