Razones por las que HTML y CSS puedan hacerte decir "qué carajo". Una selección de errores, incertidumbres y dilemas frecuentemente frustrantes de HTML y CSS.
Creada por @mdo.
Versión en español por @uncasually.
rem
y Safari móvilclear
<input>
type
a <button>
position
aclaradoposition
y anchura width
fixed
con transform
Incluye siempre un doctype. Les recomiendo el simple doctype de HTML5:
<!DOCTYPE html>
Omisión de el doctype puede causar problemas con malformación de tablas, formularios <input>
, y más problemas generando la página.
Los elementos que tienen el ancho width
especificado se alargan cuando tienen relleno padding
y/o un borde con border-width
.
Para evitar estos problemas usa el ya común reset box-sizing: border-box;
.
rem
y Safari móvilMientras que Safari móvil permite el uso de rems
en todos los valores de la propiedad, se vuelve loco cuando se utilizan las rems
en media queries
y el texto de la página se vuelve infinitamente intermitente entre varios tamaños.
Por ahora, mejor usar las unidades em
en vez de las unidades rem
.
html {
font-size: 16px;
}
/* Causa problemas en Safari móvil */
@media (min-width: 40rem) {
html {
font-size: 20px;
}
}
/* Funciona perfectamente bien en Safari móvil */
@media (min-width: 40em) {
html {
font-size: 20px;
}
}
Ayuda! Si tienes un link para reportar bugs a Apple o WebKit, me encantaría incluirlo aquí. Este problema sólo ocurre en la versión de Safari para dispositivos móviles y no en la versión de escritorio, por lo tanto, no se bien dónde reportar este error.
Los elementos flotantes float
siempre deben venir primero en el orden del documento. Esto se debe a que los elementos float
necesitan algo a que envolverse alrededor, si no, aparecen con defectos en la calculación de la posición.
<div class="parent">
<div class="float">Float</div>
<div class="content">
<!-- … -->
</div>
</div>
clear
Si utilizas float
, es probablemente necesario emplear la propiedad clear
en el elemento subsecuente a uno float
, para evitar que el elemento flote hacia arriba. Para usar la propiedad clear
, puedes usar uno de estos ejemplos.
Aquí está el micro clearfix que usa clear
con una clase separada.
.clearfix:before,
.clearfix:after {
display: table;
content: "";
}
.clearfix:after {
clear: both;
}
Alternativamente, especifica overflow
, con auto
o hidden
en el elemento principal.
.parent {
overflow: auto; /* clearfix */
}
.other-parent {
overflow: hidden; /* clearfix */
}
Ten en cuenta que overflow
puede causar otros defectos secundarios indeseables, generalmente alrededor de elementos posicionados dentro del elemento padre.
Pro-Tip! Hazte un favor a ti mismo y a tus colegas incluyendo el comentario /* clearfix */
al utilizar la propiedad clear
para floats
ya que la propiedad se puede usar por otras razones.
Un elemento padre que solo tiene contenido float
tendrá la altura calcuda height: 0;
. Usa un clearfix en el elementro padre para obligar al navegador a calcular una altura.
Elementos float
son automaticamente a nivel de bloque display: block;
. No es necesario especificar display
ya que sera ignorado por el navegador a menos que tenga el valor none
.
.element {
float: left;
display: block; /* No es necesario */
}
Fun fact: Hace años, tuvimos que especificar display: inline;
para hacer que la propiedad float
funcione correctamente en IE6 y evitar el bug de margen duplicado. Sin embargo, esos días han quedado atrás.
Los márgenes superiores e inferiores de los elementos adyacentes (uno tras otro) se cierran (collapse) en varias situaciones, pero nunca en elementos posicionados float
o absolute
. Lee este artículo MDN o la especificación CSS2 de márgenes cerrados en Español o Inglés para averiguar más.
Los márgenes horizontales nunca se cierran.
Las filas de una tabla <tr>
no pueden tener bordes a menos que uses el valor border-collapse: collapse;
en el <table>
padre.
Por otra parte, si el <tr>
y sus hijos <td>
o <th>
tienen el mismo border-width
, las propiedades de los bordes de las líneas <tr>
son ignoradas. Puedes ver un ejemplo en este JS Bin
<input>
Por razones desconocidas, Firefox aplica un line-height
a los botones de envío y <input>
que no se puede modificar con CSS. A este punto, tienes dos alternativas para lidiar con esto:
<button>
line-height
en tus botones.Si usas la primera alternativa (y recomiendo ésta de todos modos porque los <button>
son geniales) esto es lo que necesitas saber:
<!-- No es tan bueno -->
<input type="submit" value="Enviar">
<input type="button" value="Cancelar">
<!-- Súper bien en todas partes -->
<button type="submit">Enviar</button>
<button type="button">Cancelar</button>
Si prefieres usar la segunda opción, simplemente excluye line-height
y en cambio usa sólo padding
para alinear el texto del botón. Mira este ejemplo en JS Bin en Firefox per ver el problema y la solución.
¡Buenas noticias! Parece que a lo mejor habrá una solución para esto en Firefox 30. Estas son buenas noticias para nosotros en el futuro, pero ten en cuenta que no cambia los problemas en las versiones anteriores.
Firefox añade bordes internos a los botones <input>
y <button>
en la propiedad :focus
. Al parecer, es para la accesibilidad, pero su ubicación parece bastante extraña. Usa esta solución en CSS para ignorar estos bordes:
input::-moz-focus-inner,
button::-moz-focus-inner {
padding: 0;
border: 0;
}
Puedes ver esta solución en acción en el mismo ejemplo en JS Bin mencionado en la sección anterior.
Pro-Tip! No olvides incluir un estado focus
para links y elementos <button>
y <input>
. Proveer utilidades para la accesibilidad es fundamental, tanto para los usuarios avanzados que usan pestañas para navegar contenido o los usuarios con problemas de vista.
type
a los <button>
El valor inicial es submit
, es decir, cualquier botón en un formulario puede enviar el formulario. Es mejor usar type="button"
para todo lo que no envía el formulario, y usar type="submit"
para todos los botones para enviar.
<button type="submit">Enviar</button>
<button type="button">Cancelar</button>
Para todas las acciones que requieren un <button>
y no son parte de un formulario, usa type="button"
.
<button class="dismiss" type="button">x</button>
Dato curioso: Al parecer, IE7 no soporta adecuadamente el atributo value
en elementos <button>
. En lugar de leer el contenido del atributo, lee el “innerHTML” (el contenido entre la apertura y cierre de la etiqueta <button>
). Sin embargo, no me preocupo mucho de esto por dos razones: el uso de IE7 está a la baja, y es bastante raro el uso conjunto de un valor y el “innerHTML” en un <button>
Internet Explorer 9 y versiones anteriores tienen un máximo de 4096 selectores por hoja de estilo. También tienen un límite de 31 hojas de estilo y etiquetas <style></style>
incluidas juntos por página. Cualquier cosa más, después de este límite es omitido por el navegador. Te toca escoger entre dividir tu CSS o refactorizarlo. Yo sugeriría lo último.
Por si acaso, así es como los navegadores cuentan selectores:
/* Un selector */
.element { }
/* Dos selectores más */
.element,
.other-element { }
/* Tres selectores más */
input[type="text"],
.form-control,
.form-group > input { }
position
aclaradoLos elementos con position: fixed;
son colocados en relación al “viewport” del navegador. Los elementos position: absolute;
se posicionan en relación a su bloque padre más cercano que tenga una posición aparte a static
(como por ejemplo, relative
, absolute
, o fixed
).
position
y anchura width
No asignes width: 100%;
a un elemento con position: [absolute|fixed];
, left
, y right
. El uso de width: 100%;
es igual al uso combinado de left: 0;
y right: 0;
. Usa uno o el otro, pero no ambos.
fixed
con transform
Los navegadores interrumpen el position: fixed;
cuando el elemento padre tiene la propiedad transform
. El uso de transform
crea un bloque de contenido nuevo, y esto efectivamente obliga al padre a posicionarse con position: relative;
y el elemento fixed
a comportarse como position: absolute;
.
Aquí está un ejemplo y puedes tambien leer el post de Eric Meyers sobre este asunto.