La condición dice:
![]()
Si quieres poner una imagen como fondo del <body> y posicionarla abajo de la ventana del browser (background-position: bottom) y el contenido de tu sitio no llega hasta el fondo de la ventana, la imagen de fondo llegará sólo hasta donde llegue el contenido.
Para solucionarlo, basta con definir:
html {
height: 100%;
}
Ahora, esta solución es útil cuando sabes que el contenido es y será menor al alto de la ventana; si tu contenido es dinámico es mejor que utilices min-height:
html {
min-height: 100%;
}
Gracias a inyaka por hacerlo notar.

Dado un contenedor que contiene uno o más elementos flotando en su interior, siempre y cuando puedas definir un ancho fijo:
#container {
width: 600px;
display: inline-block;
}
.floto {
float: left;
}
Este método se comporta bien cuando el ancho de los elementos interiores que están flotando es menor que el del padre; las cosas comienzan a complicarse cuando aumentan:
Para contrarrestarlo, define también ancho fijo en los elementos flotantes:
#container {
width: 600px;
display: inline-block;
}
.floto {
width: 280px;
float: left;
}
Nada es perfecto… es un método más.
]]>
Pero recientemente un cliente pidió que los tabs se pudieran navegar con el historial del browser, o sea que si vas seleccionado diferentes tabs e incluso saliendo a otras páginas, puedas volver a ellas con el botón ‘Back’ o ‘Volver’ del navegador, y volver a pasar por ellos. Esto me resultó en un problema no menor que me costó solucionar, ya que los tabs suelen reaccionar ante eventos del click del mouse (como por ejemplo para mostrar tal <div> al clickear tal enlace <a> y que a éste se le agregue una class="selected" que indique su estado de seleccionado). Y esto suelo no quedar registrado en el caché del browser para que pueda ser navegado como se pidió. Pero bueno, pude solucionarlo y aquí lo comparto por si lo necesitan; implica 2 pasos diferentes los cuales deben funcionar en conjunto:
Primero, crearemos una simple función en jQuery para que funcionen los tabs. Esta es una de las maneras más simples de crear este tipo de menúes. Para el HTML:
<div class="tabs"><!-- .tabs --> <ul id="menu_tabs"> <li><a href="#item1">Item 1</a></li> ... </ul> <div id="item1" class="caja"><!-- #item1 --> <h2>Item 1</h2> <p>Donec gravida posuere arcu.</p> </div><!-- /#item1 --> ...</div><!-- /.tabs -->
Le aplicamos la siguiente instrucción en jQuery:
$(function(){
// definimos variables para el contenedor y los<div>'s de los tabs
var tabContainers = $('.tabs > div');
// creamos el evento click para cada uno de los items del menu de tabs
$('div.tabs ul a').each(function() {
$(this).click(function(){
// guardamos el ancla (#item1 por ej.) en una variable del link clickeado
var hash = $(this).attr('href');
// escondemos todos los tabs
tabContainers.hide();
// mostramos el <div> que sea igual al ancla guardado
$(hash).show();
// jugamos agregando y quitando classes del menu
$('div.tabs ul a').removeClass('selected');
$('a[href='+hash+']').addClass('selected');
});
});
// para comenzar, hacemos que el primer elemento sea el clickeado
$('div.tabs ul a:first').click();
});

Bien, con esto tienes tu menú de tabs funcionando de manera básica pero práctica. Ahora como notarás, al ir por los tabs y volver con el botón del navegador éstos no seguirán el mismo recorrido devuelta, aunque en la URL sí se vea que van cambiando. Para que esto ocurra, debemos comparar no el hash del enlace (<a href="#item1"> por ej.), sino comparar con la URL que va cambiando. Además se debe incluir el plugin jQuery BBQ, el que realiza el ingreso de la URL con tabs al caché del browser. Con el mismo HTML, miren la nueva función:
$(function(){
var tabContainers = $('.tabs > div');
// creamos un nuevo evento y lo incluimos al browser
$(window).bind('hashchange', function () {
// nuestra variable no la sacamos del <a> sino de la URL y dejamos el primero seleccionado
var hash = window.location.hash || '#item1';
// el resto es prácticamente lo mismo
tabContainers.hide();
$(hash).show();
$('div.tabs ul a').removeClass('selected');
$('a[href='+hash+']').addClass('selected');
});
// ejecutamos este nuevo evento 'hashchange' mediante un trigger
$(window).trigger('hashchange');
});
En este ejemplo, incluso podemos abrir mediante la URL en el tab que queramos, por ejemplo con el siguiente link abriremos el demo en el tab 3:
]]>Ya he comentado sobre las características de este nuevo estándar, y en este momento nos concentraremos en una maqueta funcional utilizando las nuevas etiquetas y sus nuevas posibilidades. Es interesante saber que podemos utilizar elementos de HTML 5 en estos momentos aunque la mayoría de los browsers aún no lo soporten; esto se debe a que CSS puede dar estilo a cualquier etiqueta, aunque ésta prácticamente no exista (aún). Por ejemplo, si me da la gana puedo inventar una etiqueta propia y darle estilos:
<jorge></jorge>
jorge {
display: block;
width: 300px;
height: 100px;
border: 1px solid #666
}
Aunque semánticamente no va a tener valor alguno para los buscadores (y menos para los usuarios). Pero en este artículo comencemos a armar una estructura completamente en HTML 5:
<header>
<p>Header</p>
</header>
<nav>
<p>Menu</p>
</nav>
<section>
<p>Section</p>
<article>Article</article>
<article>Article</article>
</section>
<footer>
<p>Footer</p>
</footer>

Por defecto CSS asume que un elemento es inline. Para elementos definidos en HTML 4 como <div> ó <fieldset>, los estilos predeterminados por el browser para estas etiquetas los sobreponen y los hacen bloques, pero por esta vez lo haremos manualmente para las nuevas etiquetas HTML 5 que vayamos a utilizar:
header, nav, section, article, footer {
display: block;
}
Luego podremos definir los estilos para crear la estructura que nos convenga:
header {
width: 90%;
overflow: hidden;
}
nav {
width:20%;
float: left;
margin-right: 1%;
}
section {
width:67%;
float: left;
}
article {
background: #999;
}
footer {
width:90%;
overflow: hidden;
clear:both;
}
Los browsers modernos no tendrán problemas hasta ahora; sin embargo los hechos en Redmond se rehusarán a mostrar los estilos CSS hasta que tengamos que enseñarles a comportarse como se debe. Por suerte con una pequeña ayuda de Javascript crearemos estos elementos para que IE sepa qué hacer con ellos y los estilos ya definidos:
document.createElement("header");
document.createElement("nav");
document.createElement("section");
document.createElement("article");
document.createElement("footer");
Ahora un ejemplo utilizando la nueva etiqueta <video />, la que (por estos momentos) utiliza el codec Ogg Theora para comprimir los videos (necesitarás Quicktime ó similar para poder exportarla en este formato). Con un poco de JS podremos manejar los botones de comando y la línea de tiempo de las películas sin mayores complicaciones, como en el siguiente ejemplo:
function Play(str) {
var video = document.getElementById(str)
video.play();
}
Ver ejemplo 3 (en Safari 4, Opera 10+, Firefox 3.5+, Chrome 2+)
Desarrollar pensando en 3 versiones de browser de una misma empresa, cada uno menos peor que el otro, es un problema grave. En este artículo, quiero compartir mi experiencia sobre cómo lograr los menos problemas posibles, creando un layout que se vea de manera similar en la mayoría de los navegadores disponibles en el mercado. Básicamente enunciaré algunos consejos prácticos que por mi experiencia ayudan en esta ardua tarea:
No pretendo difundir el mío, pero sinceramente no me ha dado problemas de ningún tipo y me acompaña siempre en mis grandes proyectos. Con él, me permito reescribir los estilos que defina como prioritarios, sin perder tiempo en arreglar los defectos de IE6. Un impresindible en grandes proyectos.
No basta con cabecearse cuando encuentras un descalce en tu layout que piensas funciona perfecto en todos los navegadores, hasta que lo pruebas en IE6. Deberías conocer -y prevenir- que IE6 tiene problemas posicionando relative/absolute/fixed, con el modelo de caja, doble margen a elementos flotados, utilizando z-index, soportando canal alpha para archivos PNG, con porcentaje como unidad de medida, con overflow, con pseudo-classes, con min-height, max-height, min-width, max-width… etc, etc, etc. Con eso en mente, puedes evitar muchos problemas desde el comienzo.
Microsoft lo presentó como una necesaria actualización a IE6, pero fue un gran FAIL. Arregló algunos bugs, pero sacó a luz otros nuevos; realmente me intriga qué sucede con el departamento de informática de esa compañía, cómo logran caer en los mismos errores una y otra vez. El principal problema de IE7 es el uso de position: relative/absolute aunque me he deparado con algunos errores menores por ahí.
Siento que Microsoft se apresuró mucho en lanzar IE8, probablemente presionada por las contínuas mejoras de sus compeditores Opera, Safari y Mozilla. A raíz de esto, he visto como de una actualización a la siguiente el comportamiento de este browser respecto al renderizado de HTML y CSS es muy diferente, muy pero my diferente; a tal nivel de que un cliente reclame que su nuevo y flamante sitio no se vea bien en este navegador, y antes que yo pudiera investigar qué estaba sucediendo el cliente me comenta:
Bah, ahora se ve bien… actualice IE8 anoche y se arregló.
Mi solución hasta ahora es una alternativa que viene de la misma casa de Redmont: una etiqueta <meta> que hace que IE8 se comporte como si fuera IE7; así de simple. Hace lo mismo que el Compatibility Button, pero lo ejecuta desde el comienzo de la carga del documento:
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7"/>

Aunque seas un master de las hojas de estilo y del HTML, no deberías dejar para el final probar en los principales browser, y menos aún confiarte del preview de Dreameaver (grave error); debes probar casi que a cada nueva definición de propiedad. El costo de volver atrás es muy alto como para arriesgarte, no pierdas tu tiempo por confiarte demasiado. Probando en Safari y Firefox primero, luego en IE7 e IE6 para los detalles menores… pero nunca, nunca maquetar para IE: lo más seguro es que tendrás que deshacer más de lo que ya hayas hecho.
Me puse a indagar por la web y encontré varias discusiones sobre qué solución es mejor que otra, y ninguna fue conclusiva. No hay solución aparente que funcione de igual manera para todos los browsers y que sea utilizada, por ejemplo, con comentarios condicionales. Básicamente me encontré con 2: una que involucra HTML pero la mejor manera de implementarlo es mediante Javascript y la segunda sencillamente con Javascript. Explicaré ambas a continuación, pero antes el HTML común que sería del tipo:
<select>
<option>Primero</option>
<option disabled="disabled">Segundo</option>
<option>Tercero</option>
</select>

Para que IE interprete la opción <option disabled="disabled">Segundo</option> como deshabilitado, debes cambiar la etiqueta <option> por <optgroup>; el problema es que <optgroup> se compone ligeramente diferente de <option> por lo que el HTML quedaría así:
<select>
<option>Primero</option>
<optgroup label="Segundo">Segundo</optgroup>
<option>Tercero</option>
</select>
Esta solución funciona perfecto en todos los browsers, por lo que puede ser hecho automáticamente mediante jQuery:
$('option:disabled').each(function(){
var texto = $(this).text();
$(this).replaceWith("<optgroup label='"+texto+"'>"+texto+"</optgroup>")
});

Como el problema es sólo de IE, prefiero encerraro en un if() que detecte el browser como podrán apreciar en el ejemplo. Además, notarán que <optgroup> tiene una leve diferencia de estilo que <option disabled="disabled"> pero que se puede subsanar fácilmente mediante CSS.
Ver solución 1 (en IE notarán)
Esta solución no es una solución en sí sino un parche para el problema: ya que IE no considera el atributo disabled, entonces cada vez que el <option disabled="disabled"> sea seleccionado por el usuario (tomando en cuenta que todos los otros browsers no dejarán que sea seleccionado) la selección será automáticamente trasladada al primer <option> del <select>, vale decir del ejemplo HTML si hago click a <optgroup label="Segundo">Segundo</optgroup>, automáticamente seré redireccionado a <option>Primero</option>. El JS:
$('option:disabled').css('color','gray');
$('select').change(function(){
checkDisabledOptions(this);
});
function checkDisabledOptions(el){
if(el.options[el.options.selectedIndex].disabled){
el.selectedIndex = 0;
}
}
Esta solución es una mezcla entre jQuery y Javascript puro, tomada de la mejor implementación encontrada de entre 20 otras vistas; es la más simple y con menos líneas de código. Además, para esta solución es bueno siempre en el primero item del <select> la opción <option>Seleccione</option> o cualquiera que sea que no tenga un value válido (value=""), así aportamos a la accesibilidad y podremos validar ese ítem de formulario.
Ver solución 2 (en IE notarán)
Espero Rodrigo te haya servido, y gracias por hacer me ver este tema; me entretuve bastante resolviéndolo.
Últimamente he logrado probar e implementar 2 soluciones diferentes para solucionar este drama que nos reúne. Ambas se implementan mediante Javascript y necesitan de leves retoques para funcionar (no se frustren si no se ve a la primera, basta con pensar denuevo cómo están las estructuras de tus archivos y colocar adecuadamente las rutas).
Esta segunda versión está de lujo y me hizo volver a creer en el trabajo de Twinhelix. Lo que hace esto es a través de un behavior agrega soporte casi-nativo del canal alpha de PNG para IE5.5+ sin tener que hacer cambios en el documento HTML. Otras ventajas:
img, div { behavior: url(iepngfix.htc) }
var blankImg = ‘/imagenes/blank.gif’;
Ver ejemplo 1 (con IE6, claro).
Bajar Twinhelix IEPNGFix v2
Irrumpió en la web hace muy poco y la está rompiendo. Este método se aplica mediante el llamado de un Javascript, el que al igual que el anterior lee un archivo clear.gif y lo aplica a los PNG’s haciéndolos transparentes para IE6. Su plus es que pesa sólo 1kb y para su implementación sólo se requiere llamar el .js. Claro que se debe tener el cuidado de aplicar las rutas, tanto del .js como del .gif correctamente. Puedes llamar el unitpngfix.js mediante comentarios condicionales, de la siguiente manera:
<!–[if lt IE 7]>
<script src="js/unitpngfix.js" type="text/javascript"></script>
<![endif]–>
En la primera línea de código del unitpngfix.js, debes configurar la ruta desde dónde llamar clear.gif, y nuevamente recomiendo que sea absolutamente:
var clear="/imagenes/clear.gif"
Y ya. Si seteaste bien las rutas, deberías de ver algo similar al ejemplo 2.
Ver ejemplo 2 (con IE6, insisto).
Bajar Unit PNG Fix
Y: ¿Cuál es mejor? Hasta ahora, ambas me han funcionado perfecto, por lo que les dejo a uds. definir su favorito.
]]>Cuando defines un float para una caja contenedora hacia un lado y luego le das un margin en esa misma dirección, lo que hace IE6 es simplemente duplicarla. Así nomás, sin pedir permiso.
Bueno el HTML y CSS para este ejemplo será bastante básico:
#caja {
float: left;
margin-left: 100px;
}
Para esta #caja, lo que se hizo fue darle un float: left; y un margin-left: 100px; Pero IE6 lo que hace es interpretar 200px a esa caja de margin-left. Quién lo entiende…
Pero bueno, la idea es darle una solución a esa gracia de browser (y no mediante un hack). Para corregirlo, es sólo agregar un display: inline; a #caja y todo se resuelte.
#caja {
float: left;
margin-left: 100px;
display: inline;
}

Requerimientos: Mac OSX con 10.4+ y Dashboard habilitado.
]]>
Bueno, espero ahora sepan de qué escribo. Esta vez nuevamente es una elegante técnica que involucra overflow del contenedor y padding y margin negativo en las columnas. Me gustaría hacer una pausa en estas dos importantes propiedades, sólo para dejar claro lo que involucra.
Para más claridad aún, nuevamente una imagen de ejemplo.


Como pueden leer en el muy muy útil artículo sobre el modelo de caja (si no lo han leído, háganlo ya que es muy muy útil), el padding sí modifica el ancho de nuestra caja, no así el margin. Otro detalle my importante, y que ahora nos concierne, es que el margin acepta números negativos (y que suele tener problemas de interpretación en IE6, principalmente cuando son links los involucrados), no así padding que sólo permite cantidades positivas.
Bueno, al grano. Primero, a las columnas (2 o más) deben decirles que tengan un padding-bottom de 30.000 (bien exagerado, aunque el máximo que se permite es de 32768px pero con 30000 basta). Con eso, nuestro scroll vertical se va a marear de tan grande que va a quedar. Este padding-bottom empujará nuestras columnas (y sus estilos de fondo, color o imagen) hasta no más poder, pero luego les damos un margin-bottom negativo con la misma cantidad. Con esto, nuestra caja vuelve donde estaba al comienzo, pero nuestros fondos siguen con el scroll vertical eterno. Finalmente, la caja contenedora debe esconder todo el exceso y por ende ese scroll, por lo que le damos un overflow: hidden y ya (o sea, todo lo que sobre, escóndelo). Bastante lógico.
div#container {
overflow: hidden;
}
div#izq, div#der {
float: left;
padding-bottom: 30000px;
margin-bottom: -30000px;
}
Un cuidado que deben tener es que si están flotando las cajas, su contenedor colapsará. Para esto, .clearfix será la solución ideal.
]]>